diff options
author | phk <phk@FreeBSD.org> | 2004-12-14 09:09:51 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2004-12-14 09:09:51 +0000 |
commit | 8a94ce5ea17343a8b3d2cee98003de0983f20f6c (patch) | |
tree | a124be58d8d15d3196f2e36e300b247427361e0f /sys/kern | |
parent | 8a05c599fb4f8f27a2c63fdb3057d7500581d0f7 (diff) | |
download | FreeBSD-src-8a94ce5ea17343a8b3d2cee98003de0983f20f6c.zip FreeBSD-src-8a94ce5ea17343a8b3d2cee98003de0983f20f6c.tar.gz |
Add a new kind of reference count (fd_holdcnt) to struct filedesc
which holds on to just the data structure and the mutex. (The
existing refcount (fd_refcnt) holds onto the open files in the
descriptor.)
The fd_holdcnt is protected by fdesc_mtx, fd_refcnt by FILEDESC_LOCK.
Add fdhold(struct proc *) which gets a hold on the filedescriptors of
the specified proc..
Add fddrop(struct filedesc *) which drops the fd_holdcnt and if zero
destroys the mutex and frees the memory.
Initialize the fd_holdcnt to one in fdinit(). Normal operations on
the filedesc structure will not change it.
In fdfree() use fddrop() to dispose of the mutex and structure. Hold
the FILEDESC_LOCK() until we have cleaned out the contents and carefully
set the fields to null values during cleanup.
Use fdhold()/fddrop() in mountcheckdirs() and sysctl_kern_file().
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_descrip.c | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 0c683cd..f988a41 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1394,6 +1394,7 @@ fdinit(struct filedesc *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_fd.fd_ofiles = newfdp->fd_dfiles; newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags; @@ -1402,6 +1403,34 @@ fdinit(struct filedesc *fdp) return (&newfdp->fd_fd); } +static struct filedesc * +fdhold(struct proc *p) +{ + struct filedesc *fdp; + + mtx_lock(&fdesc_mtx); + fdp = p->p_fd; + if (fdp != NULL) + fdp->fd_holdcnt++; + mtx_unlock(&fdesc_mtx); + return (fdp); +} + +static void +fddrop(struct filedesc *fdp) +{ + int i; + + mtx_lock(&fdesc_mtx); + i = --fdp->fd_holdcnt; + mtx_unlock(&fdesc_mtx); + if (i > 0) + return; + + mtx_destroy(&fdp->fd_mtx); + FREE(fdp, M_FILEDESC); +} + /* * Share a filedesc structure. */ @@ -1588,7 +1617,6 @@ fdfree(struct thread *td) * We are the last reference to the structure, so we can * safely assume it will not change out from under us. */ - FILEDESC_UNLOCK(fdp); fpp = fdp->fd_ofiles; for (i = fdp->fd_lastfile; i-- >= 0; fpp++) { if (*fpp) @@ -1604,14 +1632,22 @@ fdfree(struct thread *td) FREE(fdp->fd_ofiles, M_FILEDESC); if (NDSLOTS(fdp->fd_nfiles) > NDSLOTS(NDFILE)) FREE(fdp->fd_map, M_FILEDESC); + + fdp->fd_nfiles = 0; + if (fdp->fd_cdir) vrele(fdp->fd_cdir); + fdp->fd_cdir = NULL; if (fdp->fd_rdir) vrele(fdp->fd_rdir); + fdp->fd_rdir = NULL; if (fdp->fd_jdir) vrele(fdp->fd_jdir); - mtx_destroy(&fdp->fd_mtx); - FREE(fdp, M_FILEDESC); + fdp->fd_jdir = NULL; + + FILEDESC_UNLOCK(fdp); + + fddrop(fdp); } /* @@ -2262,8 +2298,7 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int indx, int dfd, int mode, * mount point. */ void -mountcheckdirs(olddp, newdp) - struct vnode *olddp, *newdp; +mountcheckdirs(struct vnode *olddp, struct vnode *newdp) { struct filedesc *fdp; struct proc *p; @@ -2273,12 +2308,9 @@ mountcheckdirs(olddp, newdp) return; sx_slock(&allproc_lock); LIST_FOREACH(p, &allproc, p_list) { - mtx_lock(&fdesc_mtx); - fdp = p->p_fd; - if (fdp == NULL) { - mtx_unlock(&fdesc_mtx); + fdp = fdhold(p); + if (fdp == NULL) continue; - } nrele = 0; FILEDESC_LOCK_FAST(fdp); if (fdp->fd_cdir == olddp) { @@ -2292,7 +2324,6 @@ mountcheckdirs(olddp, newdp) nrele++; } FILEDESC_UNLOCK_FAST(fdp); - mtx_unlock(&fdesc_mtx); while (nrele--) vrele(olddp); } @@ -2383,11 +2414,9 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) xf.xf_pid = p->p_pid; xf.xf_uid = p->p_ucred->cr_uid; PROC_UNLOCK(p); - mtx_lock(&fdesc_mtx); - if ((fdp = p->p_fd) == NULL) { - mtx_unlock(&fdesc_mtx); + fdp = fdhold(p); + if (fdp == NULL) continue; - } FILEDESC_LOCK_FAST(fdp); for (n = 0; n < fdp->fd_nfiles; ++n) { if ((fp = fdp->fd_ofiles[n]) == NULL) @@ -2406,7 +2435,7 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) break; } FILEDESC_UNLOCK_FAST(fdp); - mtx_unlock(&fdesc_mtx); + fddrop(fdp); if (error) break; } |