Author: mjg
Date: Fri Aug 21 21:24:14 2020
New Revision: 364464
URL: https://svnweb.freebsd.org/changeset/base/364464

Log:
  vfs: fix freevnode accounting
  
  Most notably add the missing decrement to vhold_smr.
  
      .-'---`-.
    ,'          `.
    |             \
    |              \
    \           _  \
    ,\  _    ,'-,/-)\
    ( * \ \,' ,' ,'-)
     `._,)     -',-')
       \/         ''/
        )        / /
       /       ,'-'
  
  Reported by:  Dan Nelson <dnelson_1...@yahoo.com>
  Fixes:        r362827 ("vfs: protect vnodes with smr")

Modified:
  head/sys/kern/vfs_subr.c

Modified: head/sys/kern/vfs_subr.c
==============================================================================
--- head/sys/kern/vfs_subr.c    Fri Aug 21 20:10:29 2020        (r364463)
+++ head/sys/kern/vfs_subr.c    Fri Aug 21 21:24:14 2020        (r364464)
@@ -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);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to