Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Jun 2014 15:38:40 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r267232 - head/sys/kern
Message-ID:  <201406081538.s58FceEv039084@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun Jun  8 15:38:40 2014
New Revision: 267232
URL: http://svnweb.freebsd.org/changeset/base/267232

Log:
  Use atomics to modify numvnodes variable.
  
  This allows to mostly avoid lock usage in getnewvnode_[drop_]reserve(),
  that reduces number of global vnode_free_list_mtx mutex acquisitions
  from 4 to 2 per NFS request on ZFS, improving SMP scalability.
  
  Reviewed by:	kib
  MFC after:	2 weeks
  Sponsored by:	iXsystems, Inc.

Modified:
  head/sys/kern/vfs_subr.c

Modified: head/sys/kern/vfs_subr.c
==============================================================================
--- head/sys/kern/vfs_subr.c	Sun Jun  8 14:02:25 2014	(r267231)
+++ head/sys/kern/vfs_subr.c	Sun Jun  8 15:38:40 2014	(r267232)
@@ -995,14 +995,25 @@ void
 getnewvnode_reserve(u_int count)
 {
 	struct thread *td;
+	long num;
 
 	td = curthread;
+	/* First try to be quick and racy. */
+	if (numvnodes + count <= desiredvnodes) {
+		num = atomic_fetchadd_long(&numvnodes, count);
+		if (num + count <= desiredvnodes) {
+			td->td_vp_reserv += count;
+			return;
+		} else
+			atomic_subtract_long(&numvnodes, count);
+	}
+
 	mtx_lock(&vnode_free_list_mtx);
 	while (count > 0) {
 		if (getnewvnode_wait(0) == 0) {
 			count--;
 			td->td_vp_reserv++;
-			numvnodes++;
+			atomic_add_long(&numvnodes, 1);
 		}
 	}
 	mtx_unlock(&vnode_free_list_mtx);
@@ -1014,10 +1025,7 @@ getnewvnode_drop_reserve(void)
 	struct thread *td;
 
 	td = curthread;
-	mtx_lock(&vnode_free_list_mtx);
-	KASSERT(numvnodes >= td->td_vp_reserv, ("reserve too large"));
-	numvnodes -= td->td_vp_reserv;
-	mtx_unlock(&vnode_free_list_mtx);
+	atomic_subtract_long(&numvnodes, td->td_vp_reserv);
 	td->td_vp_reserv = 0;
 }
 
@@ -1054,7 +1062,7 @@ getnewvnode(const char *tag, struct moun
 		return (error);
 	}
 #endif
-	numvnodes++;
+	atomic_add_long(&numvnodes, 1);
 	mtx_unlock(&vnode_free_list_mtx);
 alloc:
 	vp = (struct vnode *) uma_zalloc(vnode_zone, M_WAITOK|M_ZERO);
@@ -2385,9 +2393,7 @@ vdropl(struct vnode *vp)
 	 * The vnode has been marked for destruction, so free it.
 	 */
 	CTR2(KTR_VFS, "%s: destroying the vnode %p", __func__, vp);
-	mtx_lock(&vnode_free_list_mtx);
-	numvnodes--;
-	mtx_unlock(&vnode_free_list_mtx);
+	atomic_subtract_long(&numvnodes, 1);
 	bo = &vp->v_bufobj;
 	VNASSERT((vp->v_iflag & VI_FREE) == 0, vp,
 	    ("cleaned vnode still on the free list."));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406081538.s58FceEv039084>