svn commit: r244376 - in stable/9/sys: kern sys
Konstantin Belousov
kib at FreeBSD.org
Tue Dec 18 04:38:35 UTC 2012
Author: kib
Date: Tue Dec 18 04:38:34 2012
New Revision: 244376
URL: http://svnweb.freebsd.org/changeset/base/244376
Log:
MFC r243835:
The vnode_free_list_mtx is required unconditionally when iterating
over the active list.
MFC r244095:
Do not yield while owning a mutex, by stopping acquiring mount interlock.
MFC r244240:
Use user priority for the yield, do not spin on UP. Restructure the
iteration initializer and the iterator to remove code duplication.
Modified:
stable/9/sys/kern/vfs_subr.c
stable/9/sys/sys/mount.h
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/kern/vfs_subr.c
==============================================================================
--- stable/9/sys/kern/vfs_subr.c Tue Dec 18 04:27:33 2012 (r244375)
+++ stable/9/sys/kern/vfs_subr.c Tue Dec 18 04:38:34 2012 (r244376)
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#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 @@ __mnt_vnode_markerfree_all(struct vnode
* 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)
{
- struct vnode *vp, *nvp;
- if (should_yield())
- kern_yield(PRI_UNCHANGED);
+ 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;
+
+ 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,73 +4754,60 @@ __mnt_vnode_next_active(struct vnode **m
/* 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
__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: stable/9/sys/sys/mount.h
==============================================================================
--- stable/9/sys/sys/mount.h Tue Dec 18 04:27:33 2012 (r244375)
+++ stable/9/sys/sys/mount.h Tue Dec 18 04:38:34 2012 (r244376)
@@ -217,17 +217,12 @@ struct vnode *__mnt_vnode_next_active(st
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 svn-src-stable-9
mailing list