Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Oct 2017 16:31:50 +0000 (UTC)
From:      Alan Cox <alc@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r324601 - head/sys/kern
Message-ID:  <201710131631.v9DGVoLf089000@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: alc
Date: Fri Oct 13 16:31:50 2017
New Revision: 324601
URL: https://svnweb.freebsd.org/changeset/base/324601

Log:
  Address two problems with sendfile(..., SF_NOCACHE) and apply one
  "optimization".  First, sendfile(..., SF_NOCACHE) frees pages without
  checking whether those pages are mapped.  This can leave the system
  with mappings to free or repurposed pages.  Second, a page can be
  busied between the time of the current busy test and acquiring the
  object lock.  Essentially, the test performed before the object lock
  is acquired can only be regarded as an optimization to short-circuit
  further work on the page.  It cannot, however, be relied upon to prove
  that it is safe to free the page.  Third, when sendfile(..., SF_NOCACHE)
  was originally implemented, vm_page_deactivate_noreuse() did not yet
  exist.  Use vm_page_deactivate_noreuse() instead of vm_page_deactivate(),
  because it comes closer to freeing the page.
  
  In collaboration with:	glebius
  Discussed with:	gallatin, kib, markj
  X-MFC after:	r324448

Modified:
  head/sys/kern/kern_sendfile.c

Modified: head/sys/kern/kern_sendfile.c
==============================================================================
--- head/sys/kern/kern_sendfile.c	Fri Oct 13 16:23:05 2017	(r324600)
+++ head/sys/kern/kern_sendfile.c	Fri Oct 13 16:31:50 2017	(r324601)
@@ -143,10 +143,23 @@ sendfile_free_page(vm_page_t pg, bool nocache)
 			vm_page_free(pg);
 		else if (nocache) {
 			if (!vm_page_xbusied(pg) && VM_OBJECT_TRYWLOCK(obj)) {
-				vm_page_free(pg);
+				bool freed;
+
+				/* Only free unmapped pages. */
+				if (obj->ref_count == 0 ||
+				    !pmap_page_is_mapped(pg))
+					/*
+					 * The busy test before the object is
+					 * locked cannot be relied upon.
+					 */
+					freed = vm_page_try_to_free(pg);
+				else
+					freed = false;
 				VM_OBJECT_WUNLOCK(obj);
+				if (!freed)
+					vm_page_deactivate_noreuse(pg);
 			} else
-				vm_page_deactivate(pg);
+				vm_page_deactivate_noreuse(pg);
 		}
 	}
 	vm_page_unlock(pg);



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