summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_subr.c
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2009-03-02 20:51:39 +0000
committerkan <kan@FreeBSD.org>2009-03-02 20:51:39 +0000
commite17295cf6f26850137ec6961ede7e51335800027 (patch)
tree9bdfa8b0a45be61bcefa1da8f539dc8e2b94de30 /sys/kern/vfs_subr.c
parent59b707a4088dcbed0e291bb0f6a50159053fd9e6 (diff)
downloadFreeBSD-src-e17295cf6f26850137ec6961ede7e51335800027.zip
FreeBSD-src-e17295cf6f26850137ec6961ede7e51335800027.tar.gz
Change vfs_busy to wait until an outcome of pending unmount
operation is known and to retry or fail accordingly to that outcome. This fixes the problem with namespace traversing programs failing with random ENOENT errors if someone just happened to try to unmount that same filesystem at the same time. Reported by: dhw Reviewed by: kib, attilio Sponsored by: Juniper Networks, Inc.
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r--sys/kern/vfs_subr.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 6f1cdf3..9411e81 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -345,7 +345,19 @@ vfs_busy(struct mount *mp, int flags)
MNT_ILOCK(mp);
MNT_REF(mp);
- if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
+ /*
+ * If mount point is currenly being unmounted, sleep until the
+ * mount point fate is decided. If thread doing the unmounting fails,
+ * it will clear MNTK_UNMOUNT flag before waking us up, indicating
+ * that this mount point has survived the unmount attempt and vfs_busy
+ * should retry. Otherwise the unmounter thread will set MNTK_REFEXPIRE
+ * flag in addition to MNTK_UNMOUNT, indicating that mount point is
+ * about to be really destroyed. vfs_busy needs to release its
+ * reference on the mount point in this case and return with ENOENT,
+ * telling the caller that mount mount it tried to busy is no longer
+ * valid.
+ */
+ while (mp->mnt_kern_flag & MNTK_UNMOUNT) {
if (flags & MBF_NOWAIT || mp->mnt_kern_flag & MNTK_REFEXPIRE) {
MNT_REL(mp);
MNT_IUNLOCK(mp);
@@ -357,12 +369,8 @@ vfs_busy(struct mount *mp, int flags)
mtx_unlock(&mountlist_mtx);
mp->mnt_kern_flag |= MNTK_MWAIT;
msleep(mp, MNT_MTX(mp), PVFS, "vfs_busy", 0);
- MNT_REL(mp);
- MNT_IUNLOCK(mp);
if (flags & MBF_MNTLSTLOCK)
mtx_lock(&mountlist_mtx);
- CTR1(KTR_VFS, "%s: failed busying after sleep", __func__);
- return (ENOENT);
}
if (flags & MBF_MNTLSTLOCK)
mtx_unlock(&mountlist_mtx);
OpenPOWER on IntegriCloud