Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -1022,56 +1022,45 @@ TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes); TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); --count; - if (!VI_TRYLOCK(vp)) - goto next_iter; /* * If it's been deconstructed already, it's still * referenced, or it exceeds the trigger, skip it. * Also skip free vnodes. We are trying to make space * to expand the free list, not reduce it. + * + * Start with a lockless check, but also avoid hogging the + * lock if too many vnodes are of no interest. */ - if (vp->v_usecount || + if (vp->v_usecount != 0 || (!reclaim_nc_src && !LIST_EMPTY(&vp->v_cache_src)) || - ((vp->v_iflag & VI_FREE) != 0) || - (vp->v_iflag & VI_DOOMED) != 0 || (vp->v_object != NULL && - vp->v_object->resident_page_count > trigger)) { - VI_UNLOCK(vp); - goto next_iter; - } - MNT_IUNLOCK(mp); - vholdl(vp); - if (VOP_LOCK(vp, LK_INTERLOCK|LK_EXCLUSIVE|LK_NOWAIT)) { - vdrop(vp); - goto next_iter_mntunlocked; + (vp->v_iflag & VI_FREE) != 0 || + (vp->v_iflag & VI_DOOMED) != 0) { + if (should_yield()) + goto next_iter; + continue; } - VI_LOCK(vp); - /* - * v_usecount may have been bumped after VOP_LOCK() dropped - * the vnode interlock and before it was locked again. - * - * It is not necessary to recheck VI_DOOMED because it can - * only be set by another thread that holds both the vnode - * lock and vnode interlock. If another thread has the - * vnode lock before we get to VOP_LOCK() and obtains the - * vnode interlock after VOP_LOCK() drops the vnode - * interlock, the other thread will be unable to drop the - * vnode lock before our VOP_LOCK() call fails. - */ - if (vp->v_usecount || + if (!VI_TRYLOCK(vp)) + goto next_iter; + + if (vp->v_usecount != 0 || (!reclaim_nc_src && !LIST_EMPTY(&vp->v_cache_src)) || (vp->v_iflag & VI_FREE) != 0 || + (vp->v_iflag & VI_DOOMED) != 0 || (vp->v_object != NULL && vp->v_object->resident_page_count > trigger)) { - VOP_UNLOCK(vp, 0); - vdropl(vp); + VI_UNLOCK(vp); + goto next_iter; + } + MNT_IUNLOCK(mp); + if (VOP_LOCK(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_IGNORE_INTERLOCK) != 0) { + VI_UNLOCK(vp); goto next_iter_mntunlocked; } - KASSERT((vp->v_iflag & VI_DOOMED) == 0, - ("VI_DOOMED unexpectedly detected in vlrureclaim()")); - counter_u64_add(recycles_count, 1); + vholdl(vp); vgonel(vp); VOP_UNLOCK(vp, 0); vdropl(vp); + counter_u64_add(recycles_count, 1); done++; next_iter_mntunlocked: if (!should_yield())