[Midnightbsd-cvs] src [8504] trunk/sys: vnode_free_list_mtx is required

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Sep 18 18:43:06 EDT 2016


Revision: 8504
          http://svnweb.midnightbsd.org/src/?rev=8504
Author:   laffer1
Date:     2016-09-18 18:43:06 -0400 (Sun, 18 Sep 2016)
Log Message:
-----------
vnode_free_list_mtx is required

Modified Paths:
--------------
    trunk/sys/kern/vfs_subr.c
    trunk/sys/sys/mount.h

Modified: trunk/sys/kern/vfs_subr.c
===================================================================
--- trunk/sys/kern/vfs_subr.c	2016-09-18 22:42:46 UTC (rev 8503)
+++ trunk/sys/kern/vfs_subr.c	2016-09-18 22:43:06 UTC (rev 8504)
@@ -69,6 +69,7 @@
 #include <sys/reboot.h>
 #include <sys/sched.h>
 #include <sys/sleepqueue.h>
+#include <sys/smp.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
@@ -4697,20 +4698,54 @@
  * These are helper functions for filesystems to traverse their
  * active vnodes.  See MNT_VNODE_FOREACH_ACTIVE() in sys/mount.h
  */
-struct vnode *
-__mnt_vnode_next_active(struct vnode **mvp, struct mount *mp)
+static void
+mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *mp)
 {
+
+	KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
+
+	MNT_ILOCK(mp);
+	MNT_REL(mp);
+	MNT_IUNLOCK(mp);
+	free(*mvp, M_VNODE_MARKER);
+	*mvp = NULL;
+}
+
+#ifdef SMP
+#define	ALWAYS_YIELD	(mp_ncpus == 1)
+#else
+#define	ALWAYS_YIELD	1
+#endif
+
+static struct vnode *
+mnt_vnode_next_active(struct vnode **mvp, struct mount *mp)
+{
 	struct vnode *vp, *nvp;
 
-	if (should_yield())
-		kern_yield(PRI_UNCHANGED);
-	MNT_ILOCK(mp);
+	mtx_assert(&vnode_free_list_mtx, MA_OWNED);
 	KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
+restart:
 	vp = TAILQ_NEXT(*mvp, v_actfreelist);
+	TAILQ_REMOVE(&mp->mnt_activevnodelist, *mvp, v_actfreelist);
 	while (vp != NULL) {
-		VI_LOCK(vp);
-		if (vp->v_mount == mp && vp->v_type != VMARKER &&
-		    (vp->v_iflag & VI_DOOMED) == 0)
+		if (vp->v_type == VMARKER) {
+			vp = TAILQ_NEXT(vp, v_actfreelist);
+			continue;
+		}
+		if (!VI_TRYLOCK(vp)) {
+			if (ALWAYS_YIELD || should_yield()) {
+				TAILQ_INSERT_BEFORE(vp, *mvp, v_actfreelist);
+				mtx_unlock(&vnode_free_list_mtx);
+				kern_yield(PRI_USER);
+				mtx_lock(&vnode_free_list_mtx);
+				goto restart;
+			}
+			continue;
+		}
+		KASSERT(vp->v_type != VMARKER, ("locked marker %p", vp));
+		KASSERT(vp->v_mount == mp || vp->v_mount == NULL,
+		    ("alien vnode on the active list %p %p", vp, mp));
+		if (vp->v_mount == mp && (vp->v_iflag & VI_DOOMED) == 0)
 			break;
 		nvp = TAILQ_NEXT(vp, v_actfreelist);
 		VI_UNLOCK(vp);
@@ -4719,54 +4754,49 @@
 
 	/* Check if we are done */
 	if (vp == NULL) {
-		__mnt_vnode_markerfree_active(mvp, mp);
-		/* MNT_IUNLOCK(mp); -- done in above function */
-		mtx_assert(MNT_MTX(mp), MA_NOTOWNED);
+		mtx_unlock(&vnode_free_list_mtx);
+		mnt_vnode_markerfree_active(mvp, mp);
 		return (NULL);
 	}
-	mtx_lock(&vnode_free_list_mtx);
-	TAILQ_REMOVE(&mp->mnt_activevnodelist, *mvp, v_actfreelist);
 	TAILQ_INSERT_AFTER(&mp->mnt_activevnodelist, vp, *mvp, v_actfreelist);
 	mtx_unlock(&vnode_free_list_mtx);
-	MNT_IUNLOCK(mp);
+	ASSERT_VI_LOCKED(vp, "active iter");
+	KASSERT((vp->v_iflag & VI_ACTIVE) != 0, ("Non-active vp %p", vp));
 	return (vp);
 }
+#undef ALWAYS_YIELD
 
 struct vnode *
+__mnt_vnode_next_active(struct vnode **mvp, struct mount *mp)
+{
+
+	if (should_yield())
+		kern_yield(PRI_UNCHANGED);
+	mtx_lock(&vnode_free_list_mtx);
+	return (mnt_vnode_next_active(mvp, mp));
+}
+
+struct vnode *
 __mnt_vnode_first_active(struct vnode **mvp, struct mount *mp)
 {
-	struct vnode *vp, *nvp;
+	struct vnode *vp;
 
 	*mvp = malloc(sizeof(struct vnode), M_VNODE_MARKER, M_WAITOK | M_ZERO);
 	MNT_ILOCK(mp);
 	MNT_REF(mp);
+	MNT_IUNLOCK(mp);
 	(*mvp)->v_type = VMARKER;
+	(*mvp)->v_mount = mp;
 
+	mtx_lock(&vnode_free_list_mtx);
 	vp = TAILQ_FIRST(&mp->mnt_activevnodelist);
-	while (vp != NULL) {
-		VI_LOCK(vp);
-		if (vp->v_mount == mp && vp->v_type != VMARKER &&
-		    (vp->v_iflag & VI_DOOMED) == 0)
-			break;
-		nvp = TAILQ_NEXT(vp, v_actfreelist);
-		VI_UNLOCK(vp);
-		vp = nvp;
-	}
-
-	/* Check if we are done */
 	if (vp == NULL) {
-		MNT_REL(mp);
-		MNT_IUNLOCK(mp);
-		free(*mvp, M_VNODE_MARKER);
-		*mvp = NULL;
+		mtx_unlock(&vnode_free_list_mtx);
+		mnt_vnode_markerfree_active(mvp, mp);
 		return (NULL);
 	}
-	(*mvp)->v_mount = mp;
-	mtx_lock(&vnode_free_list_mtx);
-	TAILQ_INSERT_AFTER(&mp->mnt_activevnodelist, vp, *mvp, v_actfreelist);
-	mtx_unlock(&vnode_free_list_mtx);
-	MNT_IUNLOCK(mp);
-	return (vp);
+	TAILQ_INSERT_BEFORE(vp, *mvp, v_actfreelist);
+	return (mnt_vnode_next_active(mvp, mp));
 }
 
 void
@@ -4773,19 +4803,11 @@
 __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *mp)
 {
 
-	if (*mvp == NULL) {
-		MNT_IUNLOCK(mp);
+	if (*mvp == NULL)
 		return;
-	}
 
-	mtx_assert(MNT_MTX(mp), MA_OWNED);
-
-	KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
 	mtx_lock(&vnode_free_list_mtx);
 	TAILQ_REMOVE(&mp->mnt_activevnodelist, *mvp, v_actfreelist);
 	mtx_unlock(&vnode_free_list_mtx);
-	MNT_REL(mp);
-	MNT_IUNLOCK(mp);
-	free(*mvp, M_VNODE_MARKER);
-	*mvp = NULL;
+	mnt_vnode_markerfree_active(mvp, mp);
 }

Modified: trunk/sys/sys/mount.h
===================================================================
--- trunk/sys/sys/mount.h	2016-09-18 22:42:46 UTC (rev 8503)
+++ trunk/sys/sys/mount.h	2016-09-18 22:43:06 UTC (rev 8504)
@@ -217,17 +217,12 @@
 struct vnode *__mnt_vnode_first_active(struct vnode **mvp, struct mount *mp);
 void          __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
 
-#define MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) \
-	for (vp = __mnt_vnode_first_active(&(mvp), (mp)); \
+#define MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) 				\
+	for (vp = __mnt_vnode_first_active(&(mvp), (mp)); 		\
 		(vp) != NULL; vp = __mnt_vnode_next_active(&(mvp), (mp)))
 
 #define MNT_VNODE_FOREACH_ACTIVE_ABORT(mp, mvp)				\
-	do {								\
-		MNT_ILOCK(mp);						\
-		__mnt_vnode_markerfree_active(&(mvp), (mp));		\
-		/* MNT_IUNLOCK(mp); -- done in above function */	\
-		mtx_assert(MNT_MTX(mp), MA_NOTOWNED);			\
-	} while (0)
+	__mnt_vnode_markerfree_active(&(mvp), (mp))
 
 /*
  * Definitions for MNT_VNODE_FOREACH.



More information about the Midnightbsd-cvs mailing list