Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168224066
D23397.id67400.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D23397.id67400.diff
View Options
Index: sys/kern/vfs_subr.c
===================================================================
--- sys/kern/vfs_subr.c
+++ sys/kern/vfs_subr.c
@@ -1805,20 +1805,13 @@
{
struct mount *mp;
+ VNPASS((vp->v_mflag & VMP_LAZYLIST) == 0, vp);
+
mp = vp->v_mount;
if (mp == NULL)
return;
MNT_ILOCK(mp);
VI_LOCK(vp);
- if (vp->v_mflag & VMP_LAZYLIST) {
- mtx_lock(&mp->mnt_listmtx);
- if (vp->v_mflag & VMP_LAZYLIST) {
- vp->v_mflag &= ~VMP_LAZYLIST;
- TAILQ_REMOVE(&mp->mnt_lazyvnodelist, vp, v_lazylist);
- mp->mnt_lazyvnodelistsize--;
- }
- mtx_unlock(&mp->mnt_listmtx);
- }
vp->v_mount = NULL;
VI_UNLOCK(vp);
VNASSERT(mp->mnt_nvnodelistsize > 0, vp,
@@ -3076,6 +3069,7 @@
struct mount *mp;
VNASSERT(vp->v_holdcnt > 0, vp, ("%s: vnode not held", __func__));
+ VNPASS(!VN_IS_DOOMED(vp), vp);
if ((vp->v_mflag & VMP_LAZYLIST) != 0)
return;
@@ -3089,6 +3083,26 @@
mtx_unlock(&mp->mnt_listmtx);
}
+static void
+vunlazy(struct vnode *vp)
+{
+ struct mount *mp;
+
+ ASSERT_VI_LOCKED(vp, __func__);
+
+ mp = vp->v_mount;
+ if (vp->v_mflag & VMP_LAZYLIST) {
+ VNPASS(!VN_IS_DOOMED(vp), vp);
+ mtx_lock(&mp->mnt_listmtx);
+ if (vp->v_mflag & VMP_LAZYLIST) {
+ vp->v_mflag &= ~VMP_LAZYLIST;
+ TAILQ_REMOVE(&mp->mnt_lazyvnodelist, vp, v_lazylist);
+ mp->mnt_lazyvnodelistsize--;
+ }
+ mtx_unlock(&mp->mnt_listmtx);
+ }
+}
+
static void
vdefer_inactive(struct vnode *vp)
{
@@ -3480,6 +3494,22 @@
vdrop_deactivate(vp);
}
+/*
+ * Can be used when the caller knows the reference must not be last.
+ */
+static void
+vdropnl(struct vnode *vp)
+{
+
+ CTR2(KTR_VFS, "%s: vp %p", __func__, vp);
+#ifdef INVARIANTS
+ int old = atomic_fetchadd_int(&vp->v_holdcnt, -1);
+ VNASSERT(old > 1, vp, ("%s: wrong hold count %d", __func__, old));
+#else
+ atomic_subtract_int(&vp->v_holdcnt, 1);
+#endif
+}
+
/*
* Call VOP_INACTIVE on the vnode and manage the DOINGINACT and OWEINACT
* flags. DOINGINACT prevents us from recursing in calls to vinactive.
@@ -3803,6 +3833,8 @@
CTR2(KTR_VFS, "%s: vp %p", __func__, vp);
td = curthread;
+ vunlazy(vp);
+
/*
* Don't vgonel if we're already doomed.
*/
@@ -6221,8 +6253,7 @@
mnt_vnode_next_lazy_relock(struct vnode *mvp, struct mount *mp,
struct vnode *vp)
{
- const struct vnode *tmp;
- bool held, ret;
+ bool ret;
VNASSERT(mvp->v_mount == mp && mvp->v_type == VMARKER &&
TAILQ_NEXT(mvp, v_lazylist) != NULL, mvp,
@@ -6232,57 +6263,23 @@
ASSERT_VI_UNLOCKED(vp, __func__);
mtx_assert(&mp->mnt_listmtx, MA_OWNED);
- ret = false;
-
TAILQ_REMOVE(&mp->mnt_lazyvnodelist, mvp, v_lazylist);
TAILQ_INSERT_BEFORE(vp, mvp, v_lazylist);
- /*
- * Use a hold to prevent vp from disappearing while the mount vnode
- * list lock is dropped and reacquired. Normally a hold would be
- * acquired with vhold(), but that might try to acquire the vnode
- * interlock, which would be a LOR with the mount vnode list lock.
- */
- held = refcount_acquire_if_not_zero(&vp->v_holdcnt);
+ vholdnz(vp);
mtx_unlock(&mp->mnt_listmtx);
- if (!held)
- goto abort;
VI_LOCK(vp);
- if (!refcount_release_if_not_last(&vp->v_holdcnt)) {
+ if (VN_IS_DOOMED(vp)) {
+ ret = false;
+ VNPASS((vp->v_mflag & VMP_LAZYLIST) == 0, vp);
vdropl(vp);
- goto abort;
- }
- mtx_lock(&mp->mnt_listmtx);
-
- /*
- * Determine whether the vnode is still the next one after the marker,
- * excepting any other markers. If the vnode has not been doomed by
- * vgone() then the hold should have ensured that it remained on the
- * lazy list. If it has been doomed but is still on the lazy list,
- * don't abort, but rather skip over it (avoid spinning on doomed
- * vnodes).
- */
- tmp = mvp;
- do {
- tmp = TAILQ_NEXT(tmp, v_lazylist);
- } while (tmp != NULL && tmp->v_type == VMARKER);
- if (tmp != vp) {
- mtx_unlock(&mp->mnt_listmtx);
- VI_UNLOCK(vp);
- goto abort;
+ maybe_yield();
+ } else {
+ ret = true;
+ vdropnl(vp);
+ VNPASS(vp->v_mflag & VMP_LAZYLIST, vp);
}
-
- ret = true;
- goto out;
-abort:
- maybe_yield();
mtx_lock(&mp->mnt_listmtx);
-out:
- if (ret)
- ASSERT_VI_LOCKED(vp, __func__);
- else
- ASSERT_VI_UNLOCKED(vp, __func__);
- mtx_assert(&mp->mnt_listmtx, MA_OWNED);
return (ret);
}
@@ -6290,7 +6287,7 @@
mnt_vnode_next_lazy(struct vnode **mvp, struct mount *mp, mnt_lazy_cb_t *cb,
void *cbarg)
{
- struct vnode *vp, *nvp;
+ struct vnode *vp;
mtx_assert(&mp->mnt_listmtx, MA_OWNED);
KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
@@ -6306,7 +6303,8 @@
* long string of vnodes we don't care about and hog the list
* as a result. Check for it and requeue the marker.
*/
- if (VN_IS_DOOMED(vp) || !cb(vp, cbarg)) {
+ VNPASS(!VN_IS_DOOMED(vp), vp);
+ if (!cb(vp, cbarg)) {
if (!should_yield()) {
vp = TAILQ_NEXT(vp, v_lazylist);
continue;
@@ -6321,9 +6319,7 @@
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
- * reacquire it and the vnode interlock in the right order.
+ * Try-lock because this is the wrong lock order.
*/
if (!VI_TRYLOCK(vp) &&
!mnt_vnode_next_lazy_relock(*mvp, mp, vp))
@@ -6331,11 +6327,9 @@
KASSERT(vp->v_type != VMARKER, ("locked marker %p", vp));
KASSERT(vp->v_mount == mp || vp->v_mount == NULL,
("alien vnode on the lazy list %p %p", vp, mp));
- if (vp->v_mount == mp && !VN_IS_DOOMED(vp))
- break;
- nvp = TAILQ_NEXT(vp, v_lazylist);
- VI_UNLOCK(vp);
- vp = nvp;
+ VNPASS(vp->v_mount == mp, vp);
+ VNPASS(!VN_IS_DOOMED(vp), vp);
+ break;
}
TAILQ_REMOVE(&mp->mnt_lazyvnodelist, *mvp, v_lazylist);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 28, 12:45 AM (42 m, 2 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37425770
Default Alt Text
D23397.id67400.diff (5 KB)
Attached To
Mode
D23397: vfs: simplify iteration over the lazy list
Attached
Detach File
Event Timeline
Log In to Comment