summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_subr.c
diff options
context:
space:
mode:
authorDon Lewis <truckman@FreeBSD.org>2005-08-23 03:44:06 +0000
committerDon Lewis <truckman@FreeBSD.org>2005-08-23 03:44:06 +0000
commitad9f18012156f973302e0267b52edd5038d0076d (patch)
treed9a42681dab4ebc860b15043e63b67155a6729d4 /sys/kern/vfs_subr.c
parent4d3d08301e8efc43b8d96160de9383e44efcb234 (diff)
Notes
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r--sys/kern/vfs_subr.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index c686f95d446f..ceb468637dff 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -570,29 +570,59 @@ vlrureclaim(struct mount *mp)
TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
--count;
if (!VI_TRYLOCK(vp))
- continue;
+ goto next_iter;
/*
* If it's been deconstructed already, it's still
* referenced, or it exceeds the trigger, skip it.
*/
- if ((vp->v_iflag & VI_DOOMED) != 0 || vp->v_usecount ||
- !LIST_EMPTY(&(vp)->v_cache_src) || (vp->v_object != NULL &&
+ if (vp->v_usecount || !LIST_EMPTY(&(vp)->v_cache_src) ||
+ (vp->v_iflag & VI_DOOMED) != 0 || (vp->v_object != NULL &&
vp->v_object->resident_page_count > trigger)) {
VI_UNLOCK(vp);
- continue;
+ goto next_iter;
}
MNT_IUNLOCK(mp);
vholdl(vp);
- if (VOP_LOCK(vp, LK_INTERLOCK|LK_EXCLUSIVE, td)) {
+ if (VOP_LOCK(vp, LK_INTERLOCK|LK_EXCLUSIVE|LK_NOWAIT, td)) {
vdrop(vp);
- MNT_ILOCK(mp);
- continue;
+ 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 || !LIST_EMPTY(&(vp)->v_cache_src) ||
+ (vp->v_object != NULL &&
+ vp->v_object->resident_page_count > trigger)) {
+ VOP_UNLOCK(vp, LK_INTERLOCK, td);
+ goto next_iter_mntunlocked;
+ }
+ KASSERT((vp->v_iflag & VI_DOOMED) == 0,
+ ("VI_DOOMED unexpectedly detected in vlrureclaim()"));
vgonel(vp);
VOP_UNLOCK(vp, 0, td);
vdropl(vp);
done++;
+next_iter_mntunlocked:
+ if ((count % 256) != 0)
+ goto relock_mnt;
+ goto yield;
+next_iter:
+ if ((count % 256) != 0)
+ continue;
+ MNT_IUNLOCK(mp);
+yield:
+ uio_yield();
+relock_mnt:
MNT_ILOCK(mp);
}
MNT_IUNLOCK(mp);