Author: mjg
Date: Fri Oct 31 09:25:28 2014
New Revision: 273895
URL: https://svnweb.freebsd.org/changeset/base/273895

Log:
  filedesc: make fdinit return with source filedesc locked and new one sized
  appropriately
  
  Assert FILEDESC_XLOCK_ASSERT only for already used tables in fdgrowtable.
  We don't have to call it with the lock held if we are just creating new
  filedesc.
  
  As a side note, strictly speaking processes can have fdtables with
  fd_lastfile = -1, but then they cannot enter fdgrowtable. Very first file
  descriptor they get will be 0 and the only syscall allowing to choose fd 
number
  requires an active file descriptor. Should this ever change, we can add an 
'init'
  (or similar) parameter to fdgrowtable.

Modified:
  head/sys/kern/kern_descrip.c

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Fri Oct 31 09:19:46 2014        
(r273894)
+++ head/sys/kern/kern_descrip.c        Fri Oct 31 09:25:28 2014        
(r273895)
@@ -1524,7 +1524,13 @@ fdgrowtable(struct filedesc *fdp, int nf
        int nnfiles, onfiles;
        NDSLOTTYPE *nmap, *omap;
 
-       FILEDESC_XLOCK_ASSERT(fdp);
+       /*
+        * If lastfile is -1 this struct filedesc was just allocated and we are
+        * growing it to accomodate for the one we are going to copy from. There
+        * is no need to have a lock on this one as it's not visible to anyone.
+        */
+       if (fdp->fd_lastfile != -1)
+               FILEDESC_XLOCK_ASSERT(fdp);
 
        KASSERT(fdp->fd_nfiles > 0, ("zero-length file table"));
 
@@ -1791,37 +1797,52 @@ finstall(struct thread *td, struct file 
 /*
  * Build a new filedesc structure from another.
  * Copy the current, root, and jail root vnode references.
+ *
+ * If fdp is not NULL, return with it shared locked.
  */
 struct filedesc *
 fdinit(struct filedesc *fdp)
 {
-       struct filedesc0 *newfdp;
+       struct filedesc0 *newfdp0;
+       struct filedesc *newfdp;
 
-       newfdp = malloc(sizeof *newfdp, M_FILEDESC, M_WAITOK | M_ZERO);
-       FILEDESC_LOCK_INIT(&newfdp->fd_fd);
-       if (fdp != NULL) {
-               FILEDESC_SLOCK(fdp);
-               newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
-               if (newfdp->fd_fd.fd_cdir)
-                       VREF(newfdp->fd_fd.fd_cdir);
-               newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
-               if (newfdp->fd_fd.fd_rdir)
-                       VREF(newfdp->fd_fd.fd_rdir);
-               newfdp->fd_fd.fd_jdir = fdp->fd_jdir;
-               if (newfdp->fd_fd.fd_jdir)
-                       VREF(newfdp->fd_fd.fd_jdir);
+       newfdp0 = malloc(sizeof *newfdp0, M_FILEDESC, M_WAITOK | M_ZERO);
+       newfdp = &newfdp0->fd_fd;
+
+       /* Create the file descriptor table. */
+       FILEDESC_LOCK_INIT(newfdp);
+       newfdp->fd_refcnt = 1;
+       newfdp->fd_holdcnt = 1;
+       newfdp->fd_cmask = CMASK;
+       newfdp->fd_map = newfdp0->fd_dmap;
+       newfdp->fd_lastfile = -1;
+       newfdp->fd_files = (struct fdescenttbl *)&newfdp0->fd_dfiles;
+       newfdp->fd_files->fdt_nfiles = NDFILE;
+
+       if (fdp == NULL)
+               return (newfdp);
+
+       if (fdp->fd_lastfile >= newfdp->fd_nfiles)
+               fdgrowtable(newfdp, fdp->fd_lastfile + 1);
+
+       FILEDESC_SLOCK(fdp);
+       newfdp->fd_cdir = fdp->fd_cdir;
+       if (newfdp->fd_cdir)
+               VREF(newfdp->fd_cdir);
+       newfdp->fd_rdir = fdp->fd_rdir;
+       if (newfdp->fd_rdir)
+               VREF(newfdp->fd_rdir);
+       newfdp->fd_jdir = fdp->fd_jdir;
+       if (newfdp->fd_jdir)
+               VREF(newfdp->fd_jdir);
+
+       while (fdp->fd_lastfile >= newfdp->fd_nfiles) {
                FILEDESC_SUNLOCK(fdp);
+               fdgrowtable(newfdp, fdp->fd_lastfile + 1);
+               FILEDESC_SLOCK(fdp);
        }
 
-       /* Create the file descriptor table. */
-       newfdp->fd_fd.fd_refcnt = 1;
-       newfdp->fd_fd.fd_holdcnt = 1;
-       newfdp->fd_fd.fd_cmask = CMASK;
-       newfdp->fd_dfiles.fdt_nfiles = NDFILE;
-       newfdp->fd_fd.fd_files = (struct fdescenttbl *)&newfdp->fd_dfiles;
-       newfdp->fd_fd.fd_map = newfdp->fd_dmap;
-       newfdp->fd_fd.fd_lastfile = -1;
-       return (&newfdp->fd_fd);
+       return (newfdp);
 }
 
 static struct filedesc *
@@ -1905,14 +1926,6 @@ fdcopy(struct filedesc *fdp)
                return (NULL);
 
        newfdp = fdinit(fdp);
-       FILEDESC_SLOCK(fdp);
-       while (fdp->fd_lastfile >= newfdp->fd_nfiles) {
-               FILEDESC_SUNLOCK(fdp);
-               FILEDESC_XLOCK(newfdp);
-               fdgrowtable(newfdp, fdp->fd_lastfile + 1);
-               FILEDESC_XUNLOCK(newfdp);
-               FILEDESC_SLOCK(fdp);
-       }
        /* copy all passable descriptors (i.e. not kqueue) */
        newfdp->fd_freefile = -1;
        for (i = 0; i <= fdp->fd_lastfile; ++i) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to