Date: Fri, 31 Oct 2014 09:25:28 +0000 (UTC) From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r273895 - head/sys/kern Message-ID: <201410310925.s9V9PT62006495@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410310925.s9V9PT62006495>