summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-11-27 09:10:33 +0000
committerkib <kib@FreeBSD.org>2016-11-27 09:10:33 +0000
commitd6471013890dc459dd941fa7871c1c0893df21e9 (patch)
tree984af61cd17ae369bf7736ecb5c60112edb90148 /sys/ufs
parent593ac3706b39851cbc3bd96af1f392264c03be3c (diff)
downloadFreeBSD-src-d6471013890dc459dd941fa7871c1c0893df21e9.zip
FreeBSD-src-d6471013890dc459dd941fa7871c1c0893df21e9.tar.gz
MFC r308618:
Provide simple mutual exclusion between mount point update and unmount. In the update path in ffs_mount(), drop vfs_busy() reference around namei().
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 47137ac..3760e8f 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -147,7 +147,7 @@ ffs_mount(struct mount *mp)
struct ufsmount *ump = NULL;
struct fs *fs;
pid_t fsckpid = 0;
- int error, flags;
+ int error, error1, flags;
uint64_t mntorflags;
accmode_t accmode;
struct nameidata ndp;
@@ -453,6 +453,11 @@ ffs_mount(struct mount *mp)
*/
if (mp->mnt_flag & MNT_SNAPSHOT)
return (ffs_snapshot(mp, fspec));
+
+ /*
+ * Must not call namei() while owning busy ref.
+ */
+ vfs_unbusy(mp);
}
/*
@@ -460,7 +465,18 @@ ffs_mount(struct mount *mp)
* and verify that it refers to a sensible disk device.
*/
NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
- if ((error = namei(&ndp)) != 0)
+ error = namei(&ndp);
+ if ((mp->mnt_flag & MNT_UPDATE) != 0) {
+ /*
+ * Unmount does not start if MNT_UPDATE is set. Mount
+ * update busies mp before setting MNT_UPDATE. We
+ * must be able to retain our busy ref succesfully,
+ * without sleep.
+ */
+ error1 = vfs_busy(mp, MBF_NOWAIT);
+ MPASS(error1 == 0);
+ }
+ if (error != 0)
return (error);
NDFREE(&ndp, NDF_ONLY_PNBUF);
devvp = ndp.ni_vp;
OpenPOWER on IntegriCloud