Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_subr.c
Show First 20 Lines • Show All 1,016 Lines • ▼ Show 20 Lines | while (count != 0 && done < target) { | ||||
* lists also break LRU. We prefer to reclaim from the | * lists also break LRU. We prefer to reclaim from the | ||||
* free list for technical reasons. This tends to thrash | * free list for technical reasons. This tends to thrash | ||||
* the free list to keep very unrecently used held vnodes. | * the free list to keep very unrecently used held vnodes. | ||||
* The problem is mitigated by keeping the free list large. | * The problem is mitigated by keeping the free list large. | ||||
*/ | */ | ||||
TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes); | TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes); | ||||
TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); | TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); | ||||
--count; | --count; | ||||
if (!VI_TRYLOCK(vp)) | |||||
goto next_iter; | |||||
/* | /* | ||||
* If it's been deconstructed already, it's still | * If it's been deconstructed already, it's still | ||||
* referenced, or it exceeds the trigger, skip it. | * referenced, or it exceeds the trigger, skip it. | ||||
* Also skip free vnodes. We are trying to make space | * Also skip free vnodes. We are trying to make space | ||||
* to expand the free list, not reduce it. | * 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)) || | (!reclaim_nc_src && !LIST_EMPTY(&vp->v_cache_src)) || | ||||
((vp->v_iflag & VI_FREE) != 0) || | (vp->v_iflag & VI_FREE) != 0 || | ||||
(vp->v_iflag & VI_DOOMED) != 0 || (vp->v_object != NULL && | (vp->v_iflag & VI_DOOMED) != 0) { | ||||
vp->v_object->resident_page_count > trigger)) { | if (should_yield()) | ||||
VI_UNLOCK(vp); | |||||
goto next_iter; | goto next_iter; | ||||
continue; | |||||
} | } | ||||
MNT_IUNLOCK(mp); | if (!VI_TRYLOCK(vp)) | ||||
vholdl(vp); | goto next_iter; | ||||
if (VOP_LOCK(vp, LK_INTERLOCK|LK_EXCLUSIVE|LK_NOWAIT)) { | |||||
vdrop(vp); | if (vp->v_usecount != 0 || | ||||
goto next_iter_mntunlocked; | |||||
} | |||||
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 || | |||||
(!reclaim_nc_src && !LIST_EMPTY(&vp->v_cache_src)) || | (!reclaim_nc_src && !LIST_EMPTY(&vp->v_cache_src)) || | ||||
(vp->v_iflag & VI_FREE) != 0 || | (vp->v_iflag & VI_FREE) != 0 || | ||||
(vp->v_iflag & VI_DOOMED) != 0 || | |||||
(vp->v_object != NULL && | (vp->v_object != NULL && | ||||
vp->v_object->resident_page_count > trigger)) { | vp->v_object->resident_page_count > trigger)) { | ||||
VOP_UNLOCK(vp, 0); | VI_UNLOCK(vp); | ||||
vdropl(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; | goto next_iter_mntunlocked; | ||||
} | } | ||||
KASSERT((vp->v_iflag & VI_DOOMED) == 0, | vholdl(vp); | ||||
("VI_DOOMED unexpectedly detected in vlrureclaim()")); | |||||
counter_u64_add(recycles_count, 1); | |||||
vgonel(vp); | vgonel(vp); | ||||
VOP_UNLOCK(vp, 0); | VOP_UNLOCK(vp, 0); | ||||
vdropl(vp); | vdropl(vp); | ||||
counter_u64_add(recycles_count, 1); | |||||
done++; | done++; | ||||
next_iter_mntunlocked: | next_iter_mntunlocked: | ||||
if (!should_yield()) | if (!should_yield()) | ||||
goto relock_mnt; | goto relock_mnt; | ||||
goto yield; | goto yield; | ||||
next_iter: | next_iter: | ||||
if (!should_yield()) | if (!should_yield()) | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 4,948 Lines • Show Last 20 Lines |