diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2001-11-21 21:13:35 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2001-11-21 21:13:35 +0000 |
commit | bad4e9e394c7a617d250c28564484a7b7a699720 (patch) | |
tree | d8dd32073b43b015e8be17044a5d759b674cc974 /sys/kern/vfs_subr.c | |
parent | c24e90e0637476fbd9d6983cfb62b935af4c7d97 (diff) |
Added vfs_isbusy. Useful for verifying that a mount point is locked
Added vfs_mount_foreach_vnode. Several places in the code seem to want to
traverse the mount list and they all seem to handle locking differently.
Centralize traversing the mount list in one place so that we only need
to get the locking right once.
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r-- | sys/kern/vfs_subr.c | 166 |
1 files changed, 103 insertions, 63 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 9d3216d622b..e4efaff930f 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_subr.c,v 1.71 2001/11/15 06:40:39 art Exp $ */ +/* $OpenBSD: vfs_subr.c,v 1.72 2001/11/21 21:13:34 csapuntz Exp $ */ /* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */ /* @@ -112,6 +112,8 @@ int vfs_free_netcred __P((struct radix_node *, void *)); void vfs_free_addrlist __P((struct netexport *)); static __inline__ void vputonfreelist __P((struct vnode *)); +int vflush_vnode(struct vnode *, void *); + #ifdef DEBUG void printlockedvnodes __P((void)); #endif @@ -196,6 +198,12 @@ vfs_unbusy(mp, p) lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, p); } +int +vfs_isbusy(struct mount *mp) +{ + return (lockstatus(&mp->mnt_lock)); +} + /* * Lookup a filesystem type, and if found allocate and initialize * a mount structure for it. @@ -863,14 +871,10 @@ struct ctldebug debug1 = { "busyprt", &busyprt }; #endif int -vflush(mp, skipvp, flags) - struct mount *mp; - struct vnode *skipvp; - int flags; -{ - struct proc *p = curproc; - register struct vnode *vp, *nvp; - int busy = 0; +vfs_mount_foreach_vnode(struct mount *mp, + int (*func)(struct vnode *, void *), void *arg) { + struct vnode *vp, *nvp; + int error = 0; simple_lock(&mntvnode_slock); loop: @@ -878,65 +882,101 @@ loop: if (vp->v_mount != mp) goto loop; nvp = vp->v_mntvnodes.le_next; - /* - * Skip over a selected vnode. - */ - if (vp == skipvp) - continue; + simple_lock(&vp->v_interlock); + simple_unlock(&mntvnode_slock); - simple_lock(&vp->v_interlock); - /* - * Skip over a vnodes marked VSYSTEM. - */ - if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) { - simple_unlock(&vp->v_interlock); - continue; - } - /* - * If WRITECLOSE is set, only flush out regular file - * vnodes open for writing. - */ - if ((flags & WRITECLOSE) && - (vp->v_writecount == 0 || vp->v_type != VREG)) { - simple_unlock(&vp->v_interlock); - continue; - } - /* - * With v_usecount == 0, all we need to do is clear - * out the vnode data structures and we are done. - */ - if (vp->v_usecount == 0) { - simple_unlock(&mntvnode_slock); + error = func(vp, arg); + + simple_lock(&mntvnode_slock); + + if (error != 0) + break; + } + simple_unlock(&mntvnode_slock); + + return (error); +} + + +struct vflush_args { + struct vnode *skipvp; + int busy; + int flags; +}; + +int +vflush_vnode(struct vnode *vp, void *arg) { + struct vflush_args *va = arg; + struct proc *p = curproc; + + if (vp == va->skipvp) { + simple_unlock(&vp->v_interlock); + return (0); + } + + if ((va->flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) { + simple_unlock(&vp->v_interlock); + return (0); + } + + /* + * If WRITECLOSE is set, only flush out regular file + * vnodes open for writing. + */ + if ((va->flags & WRITECLOSE) && + (vp->v_writecount == 0 || vp->v_type != VREG)) { + simple_unlock(&vp->v_interlock); + return (0); + } + + /* + * With v_usecount == 0, all we need to do is clear + * out the vnode data structures and we are done. + */ + if (vp->v_usecount == 0) { + vgonel(vp, p); + return (0); + } + + /* + * If FORCECLOSE is set, forcibly close the vnode. + * For block or character devices, revert to an + * anonymous device. For all other files, just kill them. + */ + if (va->flags & FORCECLOSE) { + if (vp->v_type != VBLK && vp->v_type != VCHR) { vgonel(vp, p); - simple_lock(&mntvnode_slock); - continue; - } - /* - * If FORCECLOSE is set, forcibly close the vnode. - * For block or character devices, revert to an - * anonymous device. For all other files, just kill them. - */ - if (flags & FORCECLOSE) { - simple_unlock(&mntvnode_slock); - if (vp->v_type != VBLK && vp->v_type != VCHR) { - vgonel(vp, p); - } else { - vclean(vp, 0, p); - vp->v_op = spec_vnodeop_p; - insmntque(vp, (struct mount *)0); - } - simple_lock(&mntvnode_slock); - continue; + } else { + vclean(vp, 0, p); + vp->v_op = spec_vnodeop_p; + insmntque(vp, (struct mount *)0); } + return (0); + } + #ifdef DEBUG - if (busyprt) - vprint("vflush: busy vnode", vp); + if (busyprt) + vprint("vflush: busy vnode", vp); #endif - simple_unlock(&vp->v_interlock); - busy++; - } - simple_unlock(&mntvnode_slock); - if (busy) + simple_unlock(&vp->v_interlock); + va->busy++; + return (0); +} + +int +vflush(mp, skipvp, flags) + struct mount *mp; + struct vnode *skipvp; + int flags; +{ + struct vflush_args va; + va.skipvp = skipvp; + va.busy = 0; + va.flags = flags; + + vfs_mount_foreach_vnode(mp, vflush_vnode, &va); + + if (va.busy) return (EBUSY); return (0); } |