diff options
| author | Ian Dowse <iedowse@FreeBSD.org> | 2001-05-16 18:04:37 +0000 |
|---|---|---|
| committer | Ian Dowse <iedowse@FreeBSD.org> | 2001-05-16 18:04:37 +0000 |
| commit | 0864ef1e8a449b1533c7e0ea673e9614aaa9a81f (patch) | |
| tree | d7aaca11b211abc1efdc147eb5280e6a31ca436e /sys/kern/vfs_subr.c | |
| parent | 73cf2c3089f11d4b82c44eef06de12f8f86cc47e (diff) | |
Notes
Diffstat (limited to 'sys/kern/vfs_subr.c')
| -rw-r--r-- | sys/kern/vfs_subr.c | 56 |
1 files changed, 45 insertions, 11 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index cf2ea29349e3..2f4dc8d95326 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1627,10 +1627,22 @@ vdrop(vp) /* * Remove any vnodes in the vnode table belonging to mount point mp. * - * If MNT_NOFORCE is specified, there should not be any active ones, + * If FORCECLOSE is not specified, there should not be any active ones, * return error if any are found (nb: this is a user error, not a - * system error). If MNT_FORCE is specified, detach any active vnodes + * system error). If FORCECLOSE is specified, detach any active vnodes * that are found. + * + * If WRITECLOSE is set, only flush out regular file vnodes open for + * writing. + * + * SKIPSYSTEM causes any vnodes marked VSYSTEM to be skipped. + * + * `rootrefs' specifies the base reference count for the root vnode + * of this filesystem. The root vnode is considered busy if its + * v_usecount exceeds this value. On a successful return, vflush() + * will call vrele() on the root vnode exactly rootrefs times. + * If the SKIPSYSTEM or WRITECLOSE flags are specified, rootrefs must + * be zero. */ #ifdef DIAGNOSTIC static int busyprt = 0; /* print out busy vnodes */ @@ -1638,15 +1650,26 @@ SYSCTL_INT(_debug, OID_AUTO, busyprt, CTLFLAG_RW, &busyprt, 0, ""); #endif int -vflush(mp, skipvp, flags) +vflush(mp, rootrefs, flags) struct mount *mp; - struct vnode *skipvp; + int rootrefs; int flags; { struct proc *p = curproc; /* XXX */ - struct vnode *vp, *nvp; - int busy = 0; + struct vnode *vp, *nvp, *rootvp = NULL; + int busy = 0, error; + if (rootrefs > 0) { + KASSERT((flags & (SKIPSYSTEM | WRITECLOSE)) == 0, + ("vflush: bad args")); + /* + * Get the filesystem root vnode. We can vput() it + * immediately, since with rootrefs > 0, it won't go away. + */ + if ((error = VFS_ROOT(mp, &rootvp)) != 0) + return (error); + vput(rootvp); + } mtx_lock(&mntvnode_mtx); loop: for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) { @@ -1657,11 +1680,6 @@ loop: if (vp->v_mount != mp) goto loop; nvp = LIST_NEXT(vp, v_mntvnodes); - /* - * Skip over a selected vnode. - */ - if (vp == skipvp) - continue; mtx_lock(&vp->v_interlock); /* @@ -1717,8 +1735,24 @@ loop: busy++; } mtx_unlock(&mntvnode_mtx); + if (rootrefs > 0 && (flags & FORCECLOSE) == 0) { + /* + * If just the root vnode is busy, and if its refcount + * is equal to `rootrefs', then go ahead and kill it. + */ + mtx_lock(&rootvp->v_interlock); + KASSERT(busy > 0, ("vflush: not busy")); + KASSERT(rootvp->v_usecount >= rootrefs, ("vflush: rootrefs")); + if (busy == 1 && rootvp->v_usecount == rootrefs) { + vgonel(rootvp, p); + busy = 0; + } else + mtx_unlock(&rootvp->v_interlock); + } if (busy) return (EBUSY); + for (; rootrefs > 0; rootrefs--) + vrele(rootvp); return (0); } |
