Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Mar 2018 21:15:43 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r331325 - head/sys/kern
Message-ID:  <201803212115.w2LLFhDl094487@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Wed Mar 21 21:15:43 2018
New Revision: 331325
URL: https://svnweb.freebsd.org/changeset/base/331325

Log:
  Elide the object lock in the common case in vfs_vmio_unwire().
  
  The object lock was only needed when attempting to free B_DIRECT
  buffer pages, and for testing for invalid pages (and freeing them
  if so). Handle the latter by instead moving invalid pages near the head
  of the inactive queue, where they will be reclaimed quickly.
  
  Reviewed by:	alc, kib, jeff
  MFC after:	3 weeks
  Differential Revision:	https://reviews.freebsd.org/D14778

Modified:
  head/sys/kern/vfs_bio.c

Modified: head/sys/kern/vfs_bio.c
==============================================================================
--- head/sys/kern/vfs_bio.c	Wed Mar 21 21:13:26 2018	(r331324)
+++ head/sys/kern/vfs_bio.c	Wed Mar 21 21:15:43 2018	(r331325)
@@ -2901,7 +2901,8 @@ vfs_vmio_iodone(struct buf *bp)
 }
 
 /*
- * Unwire a page held by a buf and place it on the appropriate vm queue.
+ * Unwire a page held by a buf and either free it or update the page queues to
+ * reflect its recent use.
  */
 static void
 vfs_vmio_unwire(struct buf *bp, vm_page_t m)
@@ -2910,24 +2911,26 @@ vfs_vmio_unwire(struct buf *bp, vm_page_t m)
 
 	vm_page_lock(m);
 	if (vm_page_unwire_noq(m)) {
-		/*
-		 * Determine if the page should be freed before adding
-		 * it to the inactive queue.
-		 */
-		if (m->valid == 0) {
-			freed = !vm_page_busied(m);
-			if (freed)
-				vm_page_free(m);
-		} else if ((bp->b_flags & B_DIRECT) != 0)
+		if ((bp->b_flags & B_DIRECT) != 0)
 			freed = vm_page_try_to_free(m);
 		else
 			freed = false;
 		if (!freed) {
 			/*
-			 * If the page is unlikely to be reused, let the
-			 * VM know.  Otherwise, maintain LRU.
+			 * Use a racy check of the valid bits to determine
+			 * whether we can accelerate reclamation of the page.
+			 * The valid bits will be stable unless the page is
+			 * being mapped or is referenced by multiple buffers,
+			 * and in those cases we expect races to be rare.  At
+			 * worst we will either accelerate reclamation of a
+			 * valid page and violate LRU, or unnecessarily defer
+			 * reclamation of an invalid page.
+			 *
+			 * The B_NOREUSE flag marks data that is not expected to
+			 * be reused, so accelerate reclamation in that case
+			 * too.  Otherwise, maintain LRU.
 			 */
-			if ((bp->b_flags & B_NOREUSE) != 0)
+			if (m->valid == 0 || (bp->b_flags & B_NOREUSE) != 0)
 				vm_page_deactivate_noreuse(m);
 			else if (m->queue == PQ_ACTIVE)
 				vm_page_reference(m);
@@ -3014,7 +3017,11 @@ vfs_vmio_truncate(struct buf *bp, int desiredpages)
 		    (desiredpages << PAGE_SHIFT), bp->b_npages - desiredpages);
 	} else
 		BUF_CHECK_UNMAPPED(bp);
-	obj = bp->b_bufobj->bo_object;
+
+	/*
+	 * The object lock is needed only if we will attempt to free pages.
+	 */
+	obj = (bp->b_flags & B_DIRECT) != 0 ? bp->b_bufobj->bo_object : NULL;
 	if (obj != NULL)
 		VM_OBJECT_WLOCK(obj);
 	for (i = desiredpages; i < bp->b_npages; i++) {



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