Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Current support for iterating over mnt_vnodelist is rudiment...
details: https://anonhg.NetBSD.org/src/rev/2e5baa6e5ab8
branches: trunk
changeset: 327349:2e5baa6e5ab8
user: hannken <hannken%NetBSD.org@localhost>
date: Wed Mar 05 09:37:29 2014 +0000
description:
Current support for iterating over mnt_vnodelist is rudimentary. Every
caller has to care about list and vnode mutexes, reference count being zero,
intermediate vnode states like VI_CLEAN, VI_XLOCK, VI_MARKER and so on.
Add an interface to iterate over a vnode list:
void vfs_vnode_iterator_init(struct mount *mp, struct vnode_iterator **marker)
void vfs_vnode_iterator_destroy(struct vnode_iterator *marker)
bool vfs_vnode_iterator_next(struct vnode_iterator *marker, struct vnode **vpp)
vfs_vnode_iterator_next() returns either "false / *vpp == NULL" when done
or "true / *vpp != NULL" to return the next referenced vnode from the list.
To make vrecycle() work in this environment change it to
bool vrecycle(struct vnode *vp)
where "vp" is a referenced vnode to be destroyed if this is the last reference.
Discussed on tech-kern.
Welcome to 6.99.34
diffstat:
share/man/man9/vnode.9 | 14 +-
sys/kern/vfs_mount.c | 155 +++++++++++++++++++++++++++-------------
sys/kern/vfs_vnode.c | 33 ++++---
sys/sys/mount.h | 7 +-
sys/sys/param.h | 4 +-
sys/sys/vnode.h | 4 +-
sys/ufs/ext2fs/ext2fs_vfsops.c | 43 +++--------
sys/ufs/ffs/ffs_vfsops.c | 41 +++-------
sys/ufs/lfs/lfs_syscalls.c | 22 ++++-
9 files changed, 180 insertions(+), 143 deletions(-)
diffs (truncated from 638 to 300 lines):
diff -r 6d349c63d7fc -r 2e5baa6e5ab8 share/man/man9/vnode.9
--- a/share/man/man9/vnode.9 Wed Mar 05 08:45:13 2014 +0000
+++ b/share/man/man9/vnode.9 Wed Mar 05 09:37:29 2014 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: vnode.9,v 1.59 2014/02/22 11:28:18 wiz Exp $
+.\" $NetBSD: vnode.9,v 1.60 2014/03/05 09:37:29 hannken Exp $
.\"
.\" Copyright (c) 2001, 2005, 2006 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd February 22, 2014
+.Dd March 5, 2014
.Dt VNODE 9
.Os
.Sh NAME
@@ -79,7 +79,7 @@
.Ft void
.Fn ungetnewvnode "struct vnode *vp"
.Ft int
-.Fn vrecycle "struct vnode *vp" "struct kmutex_t *inter_lkp"
+.Fn vrecycle "struct vnode *vp"
.Ft void
.Fn vgone "struct vnode *vp"
.Ft void
@@ -616,12 +616,12 @@
.Xr VFS_VGET 9
which may need to push back a vnode in case of a locking race
condition.
-.It Fn vrecycle "vp" "inter_lkp"
-Recycle the unused vnode
+.It Fn vrecycle "vp"
+Recycle the referenced vnode
.Fa vp
-from the front of the freelist.
+if this is the last reference.
.Fn vrecycle
-is a null operation if the reference count is greater than zero.
+is a null operation if the reference count is greater than one.
.It Fn vgone "vp"
Eliminate all activity associated with the unlocked vnode
.Fa vp
diff -r 6d349c63d7fc -r 2e5baa6e5ab8 sys/kern/vfs_mount.c
--- a/sys/kern/vfs_mount.c Wed Mar 05 08:45:13 2014 +0000
+++ b/sys/kern/vfs_mount.c Wed Mar 05 09:37:29 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_mount.c,v 1.26 2014/02/27 13:00:06 hannken Exp $ */
+/* $NetBSD: vfs_mount.c,v 1.27 2014/03/05 09:37:29 hannken Exp $ */
/*-
* Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.26 2014/02/27 13:00:06 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.27 2014/03/05 09:37:29 hannken Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -375,6 +375,82 @@
return vp;
}
+struct vnode_iterator {
+ struct vnode vi_vnode;
+};
+
+void
+vfs_vnode_iterator_init(struct mount *mp, struct vnode_iterator **vipp)
+{
+ struct vnode *vp;
+
+ vp = vnalloc(mp);
+
+ mutex_enter(&mntvnode_lock);
+ TAILQ_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
+ vp->v_usecount = 1;
+ mutex_exit(&mntvnode_lock);
+
+ *vipp = (struct vnode_iterator *)vp;
+}
+
+void
+vfs_vnode_iterator_destroy(struct vnode_iterator *vi)
+{
+ struct vnode *mvp = &vi->vi_vnode;
+
+ mutex_enter(&mntvnode_lock);
+ KASSERT(ISSET(mvp->v_iflag, VI_MARKER));
+ if (mvp->v_usecount != 0)
+ TAILQ_REMOVE(&mvp->v_mount->mnt_vnodelist, mvp, v_mntvnodes);
+ mutex_exit(&mntvnode_lock);
+ vnfree(mvp);
+}
+
+bool
+vfs_vnode_iterator_next(struct vnode_iterator *vi, struct vnode **vpp)
+{
+ struct vnode *mvp = &vi->vi_vnode;
+ struct mount *mp = mvp->v_mount;
+ struct vnode *vp;
+ int error;
+
+ KASSERT(ISSET(mvp->v_iflag, VI_MARKER));
+
+ do {
+ mutex_enter(&mntvnode_lock);
+ vp = TAILQ_NEXT(mvp, v_mntvnodes);
+ TAILQ_REMOVE(&mp->mnt_vnodelist, mvp, v_mntvnodes);
+ mvp->v_usecount = 0;
+ if (vp == NULL) {
+ mutex_exit(&mntvnode_lock);
+ *vpp = NULL;
+ return false;
+ }
+
+ mutex_enter(vp->v_interlock);
+ while ((vp->v_iflag & VI_MARKER) != 0) {
+ mutex_exit(vp->v_interlock);
+ vp = TAILQ_NEXT(vp, v_mntvnodes);
+ if (vp == NULL) {
+ mutex_exit(&mntvnode_lock);
+ *vpp = NULL;
+ return false;
+ }
+ mutex_enter(vp->v_interlock);
+ }
+
+ TAILQ_INSERT_AFTER(&mp->mnt_vnodelist, vp, mvp, v_mntvnodes);
+ mvp->v_usecount = 1;
+ mutex_exit(&mntvnode_lock);
+ error = vget(vp, 0);
+ KASSERT(error == 0 || error == ENOENT);
+ } while (error != 0);
+
+ *vpp = vp;
+ return true;
+}
+
/*
* Move a vnode from one mount queue to another.
*/
@@ -426,99 +502,78 @@
#endif
static vnode_t *
-vflushnext(vnode_t *mvp, int *when)
+vflushnext(struct vnode_iterator *marker, int *when)
{
+ struct vnode *vp;
if (hardclock_ticks > *when) {
- mutex_exit(&mntvnode_lock);
yield();
- mutex_enter(&mntvnode_lock);
*when = hardclock_ticks + hz / 10;
}
- return vunmark(mvp);
+ if (vfs_vnode_iterator_next(marker, &vp))
+ return vp;
+ return NULL;
}
int
vflush(struct mount *mp, vnode_t *skipvp, int flags)
{
- vnode_t *vp, *mvp;
+ vnode_t *vp;
+ struct vnode_iterator *marker;
int busy = 0, when = 0;
/* First, flush out any vnode references from vrele_list. */
vrele_flush();
- /* Allocate a marker vnode. */
- mvp = vnalloc(mp);
-
- /*
- * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
- * and vclean() are called.
- */
- mutex_enter(&mntvnode_lock);
- for (vp = TAILQ_FIRST(&mp->mnt_vnodelist);
- vp != NULL;
- vp = vflushnext(mvp, &when)) {
- vmark(mvp, vp);
- if (vp->v_mount != mp || vismarker(vp))
- continue;
+ vfs_vnode_iterator_init(mp, &marker);
+ while ((vp = vflushnext(marker, &when)) != NULL) {
/*
* Skip over a selected vnode.
*/
- if (vp == skipvp)
- continue;
- /*
- * First try to recycle the vnode.
- */
- if (vrecycle(vp, &mntvnode_lock)) {
- mutex_enter(&mntvnode_lock);
- continue;
- }
- mutex_enter(vp->v_interlock);
- /*
- * Ignore clean but still referenced vnodes.
- */
- if ((vp->v_iflag & VI_CLEAN) != 0) {
- mutex_exit(vp->v_interlock);
+ if (vp == skipvp) {
+ vrele(vp);
continue;
}
/*
* Skip over a vnodes marked VSYSTEM.
*/
if ((flags & SKIPSYSTEM) && (vp->v_vflag & VV_SYSTEM)) {
- mutex_exit(vp->v_interlock);
+ vrele(vp);
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)) {
+ if ((flags & WRITECLOSE) && vp->v_type == VREG) {
+ mutex_enter(vp->v_interlock);
+ if (vp->v_writecount == 0) {
+ mutex_exit(vp->v_interlock);
+ vrele(vp);
+ continue;
+ }
mutex_exit(vp->v_interlock);
+ }
+ /*
+ * First try to recycle the vnode.
+ */
+ if (vrecycle(vp))
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) {
- mutex_exit(&mntvnode_lock);
- if (vget(vp, 0) == 0)
- vgone(vp);
- mutex_enter(&mntvnode_lock);
+ vgone(vp);
continue;
}
#ifdef DEBUG
if (busyprt)
vprint("vflush: busy vnode", vp);
#endif
- mutex_exit(vp->v_interlock);
+ vrele(vp);
busy++;
}
- mutex_exit(&mntvnode_lock);
- vnfree(mvp);
+ vfs_vnode_iterator_destroy(marker);
if (busy)
return (EBUSY);
return (0);
diff -r 6d349c63d7fc -r 2e5baa6e5ab8 sys/kern/vfs_vnode.c
--- a/sys/kern/vfs_vnode.c Wed Mar 05 08:45:13 2014 +0000
+++ b/sys/kern/vfs_vnode.c Wed Mar 05 09:37:29 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_vnode.c,v 1.32 2014/02/27 16:51:38 hannken Exp $ */
+/* $NetBSD: vfs_vnode.c,v 1.33 2014/03/05 09:37:29 hannken Exp $ */
/*-
* Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -116,7 +116,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.32 2014/02/27 16:51:38 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.33 2014/03/05 09:37:29 hannken Exp $");
#define _VFS_VNODE_PRIVATE
@@ -1029,30 +1029,33 @@
}
/*
- * Recycle an unused vnode to the front of the free list.
- * Release the passed interlock if the vnode will be recycled.
+ * Recycle an unused vnode if caller holds the last reference.
*/
-int
-vrecycle(vnode_t *vp, kmutex_t *inter_lkp)
Home |
Main Index |
Thread Index |
Old Index