summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortedu <tedu@openbsd.org>2003-05-06 20:52:14 +0000
committertedu <tedu@openbsd.org>2003-05-06 20:52:14 +0000
commit8e2a8047a63d78fa0105abcbde4c110e9a226106 (patch)
treed99bc902b124f9ef61747a5a1fb551d4c96eaabb
parentavoid doing a lookup on no longer mounted directories. (diff)
downloadwireguard-openbsd-8e2a8047a63d78fa0105abcbde4c110e9a226106.tar.xz
wireguard-openbsd-8e2a8047a63d78fa0105abcbde4c110e9a226106.zip
attempt to put a process's cwd back in place after a forced umount.
won't always work, but it's the best we can do for now. this covers at least some of the failure cases the previous commit to vfs_lookup.c checks for. ok weingart@
-rw-r--r--sys/kern/vfs_subr.c4
-rw-r--r--sys/kern/vfs_syscalls.c32
-rw-r--r--sys/ufs/mfs/mfs_vfsops.c9
3 files changed, 37 insertions, 8 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index b4192a84ee9..6d30d424d67 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_subr.c,v 1.90 2003/05/01 21:13:05 tedu Exp $ */
+/* $OpenBSD: vfs_subr.c,v 1.91 2003/05/06 20:52:14 tedu Exp $ */
/* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */
/*
@@ -1771,7 +1771,7 @@ vfs_unmountall(void)
nmp = CIRCLEQ_PREV(mp, mnt_list);
if ((vfs_busy(mp, LK_EXCLUSIVE|LK_NOWAIT, NULL, p)) != 0)
continue;
- if ((error = dounmount(mp, MNT_FORCE, curproc)) != 0) {
+ if ((error = dounmount(mp, MNT_FORCE, curproc, NULL)) != 0) {
printf("unmount of %s failed with error %d\n",
mp->mnt_stat.f_mntonname, error);
allerror = 1;
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index d9283e3445e..016dbefd8e8 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.102 2003/05/05 00:21:52 tedu Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.103 2003/05/06 20:52:14 tedu Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -426,16 +426,17 @@ sys_unmount(p, v, retval)
if (vfs_busy(mp, LK_EXCLUSIVE, NULL, p))
return (EBUSY);
- return (dounmount(mp, SCARG(uap, flags), p));
+ return (dounmount(mp, SCARG(uap, flags), p, vp));
}
/*
* Do the actual file system unmount.
*/
int
-dounmount(struct mount *mp, int flags, struct proc *p)
+dounmount(struct mount *mp, int flags, struct proc *p, struct vnode *olddp)
{
struct vnode *coveredvp;
+ struct proc *p2;
int error;
int hadsyncer = 0;
@@ -460,7 +461,30 @@ dounmount(struct mount *mp, int flags, struct proc *p)
}
CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
- coveredvp->v_mountedhere = (struct mount *)0;
+ if (olddp) {
+ /*
+ * Try to put processes back in a real directory
+ * after a forced unmount.
+ * XXX We're not holding a ref on olddp, which may
+ * change, so compare id numbers.
+ */
+ LIST_FOREACH(p2, &allproc, p_list) {
+ struct filedesc *fdp = p2->p_fd;
+ if (fdp->fd_cdir &&
+ fdp->fd_cdir->v_id == olddp->v_id) {
+ vrele(fdp->fd_cdir);
+ vref(coveredvp);
+ fdp->fd_cdir = coveredvp;
+ }
+ if (fdp->fd_rdir &&
+ fdp->fd_rdir->v_id == olddp->v_id) {
+ vrele(fdp->fd_rdir);
+ vref(coveredvp);
+ fdp->fd_rdir = coveredvp;
+ }
+ }
+ }
+ coveredvp->v_mountedhere = NULL;
vrele(coveredvp);
}
mp->mnt_vfc->vfc_refcount--;
diff --git a/sys/ufs/mfs/mfs_vfsops.c b/sys/ufs/mfs/mfs_vfsops.c
index e9e6a7013e8..f02d061e52d 100644
--- a/sys/ufs/mfs/mfs_vfsops.c
+++ b/sys/ufs/mfs/mfs_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfs_vfsops.c,v 1.22 2002/07/12 14:02:23 art Exp $ */
+/* $OpenBSD: mfs_vfsops.c,v 1.23 2003/05/06 20:52:14 tedu Exp $ */
/* $NetBSD: mfs_vfsops.c,v 1.10 1996/02/09 22:31:28 christos Exp $ */
/*
@@ -259,6 +259,7 @@ mfs_start(mp, flags, p)
struct proc *p;
{
struct vnode *vp = VFSTOUFS(mp)->um_devvp;
+ struct vnode *rvp;
struct mfsnode *mfsp = VTOMFS(vp);
struct buf *bp;
caddr_t base;
@@ -278,8 +279,12 @@ mfs_start(mp, flags, p)
* EINTR/ERESTART.
*/
if (sleepreturn != 0) {
+ if (ufs_root(mp, &rvp))
+ rvp = NULL;
+ else
+ vput(rvp);
if (vfs_busy(mp, LK_EXCLUSIVE|LK_NOWAIT, NULL, p) ||
- dounmount(mp, 0, p))
+ dounmount(mp, 0, p, rvp))
CLRSIG(p, CURSIG(p));
sleepreturn = 0;
continue;