diff options
author | trasz <trasz@FreeBSD.org> | 2009-02-05 08:46:18 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2009-02-05 08:46:18 +0000 |
commit | a4e8c3ba997f73078710bd9a44277288dca15874 (patch) | |
tree | ad7dbff1afb2c539ce3ab2fe6f719b0af6bcc18a /sys/kern | |
parent | d0a09ee159f618321ade9364ccf8b823779b0ffe (diff) | |
download | FreeBSD-src-a4e8c3ba997f73078710bd9a44277288dca15874.zip FreeBSD-src-a4e8c3ba997f73078710bd9a44277288dca15874.tar.gz |
In some situations, mnt_lockref could go negative due to vfs_unbusy() being
called without calling vfs_busy() first. This made umount(8) hang waiting
for mnt_lockref to become zero, which would never happen.
Reviewed by: kib
Approved by: rwatson (mentor)
Reported by: pho
Found with: stress2
Sponsored by: FreeBSD Foundation
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index a910bf3..be3dc76 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -395,14 +395,16 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) vfs_ref(mp); VOP_UNLOCK(vp, 0); fdrop(fp, td); - if (vp->v_iflag & VI_DOOMED) { + if (mp == NULL) { error = EBADF; goto out; } error = vfs_busy(mp, 0); vfs_rel(mp); - if (error) - goto out; + if (error) { + VFS_UNLOCK_GIANT(vfslocked); + return (error); + } #ifdef MAC error = mac_mount_check_stat(td->td_ucred, mp); if (error) |