diff options
author | 2003-05-06 20:52:14 +0000 | |
---|---|---|
committer | 2003-05-06 20:52:14 +0000 | |
commit | 8e2a8047a63d78fa0105abcbde4c110e9a226106 (patch) | |
tree | d99bc902b124f9ef61747a5a1fb551d4c96eaabb | |
parent | avoid doing a lookup on no longer mounted directories. (diff) | |
download | wireguard-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.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 32 | ||||
-rw-r--r-- | sys/ufs/mfs/mfs_vfsops.c | 9 |
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; |