svn commit: r273895 - head/sys/kern
Mateusz Guzik
mjg at FreeBSD.org
Fri Oct 31 09:25:29 UTC 2014
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) {
More information about the svn-src-all
mailing list