vfs: fix freevnode accounting
Most notably add the missing decrement to vhold_smr. .-'---`-. ,' `. | \ | \ \ _ \ ,\ _ ,'-,/-)\ ( * \ \,' ,' ,'-) `._,) -',-') \/ ''/ ) / / / ,'-' Reported by: Dan Nelson <dnelson_1901@yahoo.com> Fixes: r362827 ("vfs: protect vnodes with smr")
This commit is contained in:
parent
7758c80f74
commit
19337211f8
@ -1293,6 +1293,28 @@ static int vnlruproc_sig;
|
||||
*/
|
||||
#define VNLRU_FREEVNODES_SLOP 128
|
||||
|
||||
static __inline void
|
||||
vn_freevnodes_inc(void)
|
||||
{
|
||||
struct vdbatch *vd;
|
||||
|
||||
critical_enter();
|
||||
vd = DPCPU_PTR(vd);
|
||||
vd->freevnodes++;
|
||||
critical_exit();
|
||||
}
|
||||
|
||||
static __inline void
|
||||
vn_freevnodes_dec(void)
|
||||
{
|
||||
struct vdbatch *vd;
|
||||
|
||||
critical_enter();
|
||||
vd = DPCPU_PTR(vd);
|
||||
vd->freevnodes--;
|
||||
critical_exit();
|
||||
}
|
||||
|
||||
static u_long
|
||||
vnlru_read_freevnodes(void)
|
||||
{
|
||||
@ -3195,19 +3217,14 @@ vunref(struct vnode *vp)
|
||||
void
|
||||
vhold(struct vnode *vp)
|
||||
{
|
||||
struct vdbatch *vd;
|
||||
int old;
|
||||
|
||||
CTR2(KTR_VFS, "%s: vp %p", __func__, vp);
|
||||
old = atomic_fetchadd_int(&vp->v_holdcnt, 1);
|
||||
VNASSERT(old >= 0 && (old & VHOLD_ALL_FLAGS) == 0, vp,
|
||||
("%s: wrong hold count %d", __func__, old));
|
||||
if (old != 0)
|
||||
return;
|
||||
critical_enter();
|
||||
vd = DPCPU_PTR(vd);
|
||||
vd->freevnodes--;
|
||||
critical_exit();
|
||||
if (old == 0)
|
||||
vn_freevnodes_dec();
|
||||
}
|
||||
|
||||
void
|
||||
@ -3268,8 +3285,11 @@ vhold_smr(struct vnode *vp)
|
||||
}
|
||||
|
||||
VNASSERT(count >= 0, vp, ("invalid hold count %d\n", count));
|
||||
if (atomic_fcmpset_int(&vp->v_holdcnt, &count, count + 1))
|
||||
if (atomic_fcmpset_int(&vp->v_holdcnt, &count, count + 1)) {
|
||||
if (count == 0)
|
||||
vn_freevnodes_dec();
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3309,17 +3329,13 @@ vdbatch_enqueue(struct vnode *vp)
|
||||
VNASSERT(!VN_IS_DOOMED(vp), vp,
|
||||
("%s: deferring requeue of a doomed vnode", __func__));
|
||||
|
||||
critical_enter();
|
||||
vd = DPCPU_PTR(vd);
|
||||
vd->freevnodes++;
|
||||
if (vp->v_dbatchcpu != NOCPU) {
|
||||
VI_UNLOCK(vp);
|
||||
critical_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
sched_pin();
|
||||
critical_exit();
|
||||
vd = DPCPU_PTR(vd);
|
||||
mtx_lock(&vd->lock);
|
||||
MPASS(vd->index < VDBATCH_SIZE);
|
||||
MPASS(vd->tab[vd->index] == NULL);
|
||||
@ -3444,6 +3460,7 @@ vdropl(struct vnode *vp)
|
||||
return;
|
||||
}
|
||||
if (!VN_IS_DOOMED(vp)) {
|
||||
vn_freevnodes_inc();
|
||||
vdrop_deactivate(vp);
|
||||
/*
|
||||
* Also unlocks the interlock. We can't assert on it as we
|
||||
@ -3458,7 +3475,8 @@ vdropl(struct vnode *vp)
|
||||
* We may be racing against vhold_smr. If they win we can just pretend
|
||||
* we never got this far, they will vdrop later.
|
||||
*/
|
||||
if (!atomic_cmpset_int(&vp->v_holdcnt, 0, VHOLD_NO_SMR)) {
|
||||
if (__predict_false(!atomic_cmpset_int(&vp->v_holdcnt, 0, VHOLD_NO_SMR))) {
|
||||
vn_freevnodes_inc();
|
||||
VI_UNLOCK(vp);
|
||||
/*
|
||||
* We lost the aforementioned race. Any subsequent access is
|
||||
@ -3466,6 +3484,9 @@ vdropl(struct vnode *vp)
|
||||
*/
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Don't bump freevnodes as this one is going away.
|
||||
*/
|
||||
freevnode(vp);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user