summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>2001-11-21 21:13:35 +0000
committerConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>2001-11-21 21:13:35 +0000
commitbad4e9e394c7a617d250c28564484a7b7a699720 (patch)
treed8dd32073b43b015e8be17044a5d759b674cc974 /sys
parentc24e90e0637476fbd9d6983cfb62b935af4c7d97 (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')
-rw-r--r--sys/kern/vfs_subr.c166
-rw-r--r--sys/sys/mount.h5
2 files changed, 107 insertions, 64 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);
}
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index d2286cffd6e..f398a301c69 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mount.h,v 1.39 2001/03/23 00:24:10 mickey Exp $ */
+/* $OpenBSD: mount.h,v 1.40 2001/11/21 21:13:34 csapuntz Exp $ */
/* $NetBSD: mount.h,v 1.48 1996/02/18 11:55:47 fvdl Exp $ */
/*
@@ -535,6 +535,9 @@ struct netexport {
* exported vnode operations
*/
int vfs_busy __P((struct mount *, int, struct simplelock *, struct proc *));
+int vfs_isbusy(struct mount *);
+int vfs_mount_foreach_vnode(struct mount *, int (*func)(struct vnode *,
+ void *), void *);
void vfs_getnewfsid __P((struct mount *));
struct mount *vfs_getvfs __P((fsid_t *));
int vfs_mountedon __P((struct vnode *));