aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2019-03-21 13:30:48 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2019-03-21 13:30:48 +0000
commit7ae3486e6d927eaf8d3c6207cf90a26e94678daf (patch)
tree9d3ccd474a0f8ba451287a645cca2b9af75d9028
parent8b0f6c42152b9afbd13efa2d23add5ed664ac639 (diff)
downloadsrc-7ae3486e6d927eaf8d3c6207cf90a26e94678daf.tar.gz
src-7ae3486e6d927eaf8d3c6207cf90a26e94678daf.zip
nullfs: fix unmounts when filesystem is active.
If vflush() did not completely flushed the mount vnodes queue, either retry for forced unmounts, or give up for non-forced. This situation can occur when new vnodes are instantiated while vflush() worked. Reported and tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week
Notes
Notes: svn path=/head/; revision=345376
-rw-r--r--sys/fs/nullfs/null_vfsops.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index fdb5e9e7e7e0..361a878687d3 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -235,7 +235,7 @@ nullfs_unmount(mp, mntflags)
{
struct null_mount *mntdata;
struct mount *ump;
- int error, flags;
+ int error, flags, rootrefs;
NULLFSDEBUG("nullfs_unmount: mp = %p\n", (void *)mp);
@@ -244,10 +244,20 @@ nullfs_unmount(mp, mntflags)
else
flags = 0;
- /* There is 1 extra root vnode reference (nullm_rootvp). */
- error = vflush(mp, 1, flags, curthread);
- if (error)
- return (error);
+ for (rootrefs = 1;; rootrefs = 0) {
+ /* There is 1 extra root vnode reference (nullm_rootvp). */
+ error = vflush(mp, rootrefs, flags, curthread);
+ if (error)
+ return (error);
+ MNT_ILOCK(mp);
+ if (mp->mnt_nvnodelistsize == 0) {
+ MNT_IUNLOCK(mp);
+ break;
+ }
+ MNT_IUNLOCK(mp);
+ if ((mntflags & MNT_FORCE) == 0)
+ return (EBUSY);
+ }
/*
* Finally, throw away the null_mount structure