diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2019-03-21 13:30:48 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2019-03-21 13:30:48 +0000 |
commit | 7ae3486e6d927eaf8d3c6207cf90a26e94678daf (patch) | |
tree | 9d3ccd474a0f8ba451287a645cca2b9af75d9028 | |
parent | 8b0f6c42152b9afbd13efa2d23add5ed664ac639 (diff) | |
download | src-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.c | 20 |
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 |