Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -4335,6 +4335,17 @@ * perform msync on all vnodes under a mount point * the mount point must be locked. */ +static bool +vfs_msync_filter(struct vnode *vp, void *arg) +{ + struct vm_object *obj; + int flags = *(int *)arg; + + obj = vp->v_object; + return (obj != NULL && vm_object_mightbedirty(obj) && + (flags == MNT_WAIT || VOP_ISLOCKED(vp) == 0)); +} + void vfs_msync(struct mount *mp, int flags) { @@ -4348,7 +4359,7 @@ return; td = curthread; - MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) { + MNT_VNODE_FOREACH_ACTIVE_FILTER(vp, mp, mvp, vfs_msync_filter, &flags) { obj = vp->v_object; if (obj != NULL && vm_object_mightbedirty(obj) && (flags == MNT_WAIT || VOP_ISLOCKED(vp) == 0)) { @@ -5959,7 +5970,8 @@ } static struct vnode * -mnt_vnode_next_active(struct vnode **mvp, struct mount *mp) +mnt_vnode_next_active(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *cbarg) { struct vnode *vp, *nvp; @@ -5972,6 +5984,25 @@ vp = TAILQ_NEXT(vp, v_actfreelist); continue; } + /* + * See if we want to process the vnode. Note we may encounter a + * long string of vnodes we don't care about and hog the list + * as a result. Check for it and requeue the marker. + */ + if (cb != NULL && !cb(vp, cbarg)) { + if (!should_yield()) { + vp = TAILQ_NEXT(vp, v_actfreelist); + continue; + } + TAILQ_REMOVE(&mp->mnt_activevnodelist, *mvp, + v_actfreelist); + TAILQ_INSERT_AFTER(&mp->mnt_activevnodelist, vp, *mvp, + v_actfreelist); + mtx_unlock(&mp->mnt_listmtx); + kern_yield(PRI_USER); + mtx_lock(&mp->mnt_listmtx); + goto restart; + } /* * Try-lock because this is the wrong lock order. If that does * not succeed, drop the mount vnode list lock and try to @@ -6005,17 +6036,19 @@ } struct vnode * -__mnt_vnode_next_active(struct vnode **mvp, struct mount *mp) +__mnt_vnode_next_active(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *cbarg) { if (should_yield()) kern_yield(PRI_USER); mtx_lock(&mp->mnt_listmtx); - return (mnt_vnode_next_active(mvp, mp)); + return (mnt_vnode_next_active(mvp, mp, cb, cbarg)); } struct vnode * -__mnt_vnode_first_active(struct vnode **mvp, struct mount *mp) +__mnt_vnode_first_active(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *cbarg) { struct vnode *vp; @@ -6034,7 +6067,7 @@ return (NULL); } TAILQ_INSERT_BEFORE(vp, *mvp, v_actfreelist); - return (mnt_vnode_next_active(mvp, mp)); + return (mnt_vnode_next_active(mvp, mp, cb, cbarg)); } void Index: sys/sys/mount.h =================================================================== --- sys/sys/mount.h +++ sys/sys/mount.h @@ -256,13 +256,18 @@ /* * Definitions for MNT_VNODE_FOREACH_ACTIVE. */ -struct vnode *__mnt_vnode_next_active(struct vnode **mvp, struct mount *mp); -struct vnode *__mnt_vnode_first_active(struct vnode **mvp, struct mount *mp); +struct vnode *__mnt_vnode_next_active(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *cbarg); +struct vnode *__mnt_vnode_first_active(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *cbarg); 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)); \ - (vp) != NULL; vp = __mnt_vnode_next_active(&(mvp), (mp))) +#define MNT_VNODE_FOREACH_ACTIVE_FILTER(vp, mp, mvp, cb, cbarg) \ + for (vp = __mnt_vnode_first_active(&(mvp), (mp), (cb), (cbarg));\ + (vp) != NULL; vp = __mnt_vnode_next_active(&(mvp), (mp), (cb), (cbarg))) + +#define MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) \ + MNT_VNODE_FOREACH_ACTIVE_FILTER(vp, mp, mvp, NULL, NULL) #define MNT_VNODE_FOREACH_ACTIVE_ABORT(mp, mvp) \ __mnt_vnode_markerfree_active(&(mvp), (mp))