Page MenuHomeFreeBSD

D23397.id67400.diff
No OneTemporary

D23397.id67400.diff

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

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)

Event Timeline