diff options
author | phk <phk@FreeBSD.org> | 2004-12-14 20:48:40 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2004-12-14 20:48:40 +0000 |
commit | eab55e158905b42bd76bba4164b30ab5db8d0d86 (patch) | |
tree | 25bd69d8ef4773a8dd5da2b06a6b0b6fb6434422 /sys/kern/kern_descrip.c | |
parent | ef590407757a212568b3a5f9265dad4c8f3c98a6 (diff) | |
download | FreeBSD-src-eab55e158905b42bd76bba4164b30ab5db8d0d86.zip FreeBSD-src-eab55e158905b42bd76bba4164b30ab5db8d0d86.tar.gz |
Fix a deadlock I introduced this morning.
Mostly from: tegge
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index f988a41..659c4c5 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1607,12 +1607,11 @@ fdfree(struct thread *td) if (fdtol != NULL) FREE(fdtol, M_FILEDESC_TO_LEADER); } - FILEDESC_LOCK(fdp); - if (--fdp->fd_refcnt > 0) { - FILEDESC_UNLOCK(fdp); + FILEDESC_LOCK_FAST(fdp); + i = --fdp->fd_refcnt; + FILEDESC_UNLOCK_FAST(fdp); + if (i > 0) return; - } - /* * We are the last reference to the structure, so we can * safely assume it will not change out from under us. @@ -1622,6 +1621,7 @@ fdfree(struct thread *td) if (*fpp) (void) closef(*fpp, td); } + FILEDESC_LOCK(fdp); /* XXX This should happen earlier. */ mtx_lock(&fdesc_mtx); @@ -2324,6 +2324,7 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp) nrele++; } FILEDESC_UNLOCK_FAST(fdp); + fddrop(fdp); while (nrele--) vrele(olddp); } @@ -2418,7 +2419,7 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) if (fdp == NULL) continue; FILEDESC_LOCK_FAST(fdp); - for (n = 0; n < fdp->fd_nfiles; ++n) { + for (n = 0; fdp->fd_refcnt > 0 && n < fdp->fd_nfiles; ++n) { if ((fp = fdp->fd_ofiles[n]) == NULL) continue; xf.xf_fd = n; |