summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_mount.c
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2003-11-30 23:30:09 +0000
committeriedowse <iedowse@FreeBSD.org>2003-11-30 23:30:09 +0000
commitbc2791c3fa8b4c3bc60213c7cd0e0ada4d3c2ff1 (patch)
treedbc831752fc5a9a178124d9d93afa371b39c27c2 /sys/kern/vfs_mount.c
parent669569d0f623a7bebdc39e888f7ba1175e198698 (diff)
downloadFreeBSD-src-bc2791c3fa8b4c3bc60213c7cd0e0ada4d3c2ff1.zip
FreeBSD-src-bc2791c3fa8b4c3bc60213c7cd0e0ada4d3c2ff1.tar.gz
In dounmount(), only call checkdirs() prior to VFS_UNMOUNT() in the
forced unmount case. Otherwise, a file system that is referenced only by process fd_cdir/fd_rdir references to the file system root vnode will be successfully unmounted without the MNT_FORCE flag. The previous behaviour was not compatible with the unmount semantics required by amd(8), so file systems could be unexpectedly unmounted while there were still references to the file system root directory. Reported by: Erez Zadok <ezk@cs.sunysb.edu> Approved by: re (scottl)
Diffstat (limited to 'sys/kern/vfs_mount.c')
-rw-r--r--sys/kern/vfs_mount.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index b265fc3..c1bf0b9 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1110,8 +1110,12 @@ dounmount(mp, flags, td)
cache_purgevfs(mp); /* remove cache entries for this file sys */
if (mp->mnt_syncer != NULL)
vrele(mp->mnt_syncer);
- /* Move process cdir/rdir refs on fs root to underlying vnode. */
- if (VFS_ROOT(mp, &fsrootvp) == 0) {
+ /*
+ * For forced unmounts, move process cdir/rdir refs on the fs root
+ * vnode to the covered vnode. For non-forced unmounts we want
+ * such references to cause an EBUSY error.
+ */
+ if ((flags & MNT_FORCE) && VFS_ROOT(mp, &fsrootvp) == 0) {
if (mp->mnt_vnodecovered != NULL)
checkdirs(fsrootvp, mp->mnt_vnodecovered);
if (fsrootvp == rootvnode) {
@@ -1128,7 +1132,7 @@ dounmount(mp, flags, td)
vn_finished_write(mp);
if (error) {
/* Undo cdir/rdir and rootvnode changes made above. */
- if (VFS_ROOT(mp, &fsrootvp) == 0) {
+ if ((flags & MNT_FORCE) && VFS_ROOT(mp, &fsrootvp) == 0) {
if (mp->mnt_vnodecovered != NULL)
checkdirs(mp->mnt_vnodecovered, fsrootvp);
if (rootvnode == NULL) {
OpenPOWER on IntegriCloud