summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>1998-12-10 23:48:14 +0000
committerArtur Grabowski <art@cvs.openbsd.org>1998-12-10 23:48:14 +0000
commit8cd28d6913d14cfea823502780f14346913b7660 (patch)
tree8cb6c1062cfa02914c46e922a4bf10300cc3efcc
parent3355c8c983a8923b015cbdcef2b87de65aefada5 (diff)
Several fixes to dounmount.
- Check for MNT_UNMOUNT before doing the actual unmount. It shouldn't matter for normal unmounts that go through sys_unmount, because they won't be able to do a lookup on the mountpoint when it's being unmounted, but mfs calls dounmount directly (and there was still a race). - clear the MNT_UNMOUNT flag after reenabling the lock (almost impossible race). - clear the MNT_MWAIT flag after doing a wakeup on the mountpoint.
-rw-r--r--sys/kern/vfs_syscalls.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 8abc6e739a1..a9c02ad2f9f 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.47 1998/11/12 04:30:01 csapuntz Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.48 1998/12/10 23:48:13 art Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -427,6 +427,12 @@ dounmount(mp, flags, p)
int error;
simple_lock(&mountlist_slock);
+ if (mp->mnt_flag & MNT_UNMOUNT) {
+ simple_unlock(&mountlist_slock);
+ mp->mnt_flag |= MNT_WAIT;
+ sleep(mp, PVFS);
+ return ENOENT;
+ }
mp->mnt_flag |= MNT_UNMOUNT;
lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
mp->mnt_flag &=~ MNT_ASYNC;
@@ -442,11 +448,12 @@ dounmount(mp, flags, p)
if (error) {
if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
(void) vfs_allocate_syncvnode(mp);
- mp->mnt_flag &= ~MNT_UNMOUNT;
lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
&mountlist_slock, p);
+ mp->mnt_flag &= ~MNT_UNMOUNT;
if (mp->mnt_flag & MNT_MWAIT)
wakeup((caddr_t)mp);
+ mp->mnt_flag &= ~MNT_MWAIT;
return (error);
}
CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);