svn commit: r364464 - head/sys/kern

Mateusz Guzik mjg at FreeBSD.org
Fri Aug 21 21:24:23 UTC 2020


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_1901 at 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);
 }
 


More information about the svn-src-all mailing list