svn commit: r360436 - head/sys/vm

Mark Johnston markj at FreeBSD.org
Tue Apr 28 13:51:42 UTC 2020


Author: markj
Date: Tue Apr 28 13:51:41 2020
New Revision: 360436
URL: https://svnweb.freebsd.org/changeset/base/360436

Log:
  Re-check for wirings after busying the page in vm_page_release_locked().
  
  A concurrent unlocked lookup can wire the page after
  vm_page_release_locked() releases the last wiring, in which case
  vm_page_release_locked() must not free the page.  Once the xbusy lock is
  acquired, that, the object lock and the fact that the page is unmapped
  ensure that the wire count cannot increase, so re-check for new wirings
  after the page is xbusied.
  
  Update the comment above vm_page_wired() to reflect the new
  synchronization rules.
  
  Reported by:	glebius
  Reviewed by:	alc, jeff, kib
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D24592

Modified:
  head/sys/vm/vm_page.c
  head/sys/vm/vm_page.h

Modified: head/sys/vm/vm_page.c
==============================================================================
--- head/sys/vm/vm_page.c	Tue Apr 28 13:28:58 2020	(r360435)
+++ head/sys/vm/vm_page.c	Tue Apr 28 13:51:41 2020	(r360436)
@@ -4165,7 +4165,16 @@ vm_page_release_locked(vm_page_t m, int flags)
 		if ((flags & VPR_TRYFREE) != 0 &&
 		    (m->object->ref_count == 0 || !pmap_page_is_mapped(m)) &&
 		    m->dirty == 0 && vm_page_tryxbusy(m)) {
-			vm_page_free(m);
+			/*
+			 * An unlocked lookup may have wired the page before the
+			 * busy lock was acquired, in which case the page must
+			 * not be freed.
+			 */
+			if (__predict_true(!vm_page_wired(m))) {
+				vm_page_free(m);
+				return;
+			}
+			vm_page_xunbusy(m);
 		} else {
 			vm_page_release_toq(m, PQ_INACTIVE, flags != 0);
 		}

Modified: head/sys/vm/vm_page.h
==============================================================================
--- head/sys/vm/vm_page.h	Tue Apr 28 13:28:58 2020	(r360435)
+++ head/sys/vm/vm_page.h	Tue Apr 28 13:51:41 2020	(r360436)
@@ -958,8 +958,8 @@ vm_page_drop(vm_page_t m, u_int val)
  *
  *	Perform a racy check to determine whether a reference prevents the page
  *	from being reclaimable.  If the page's object is locked, and the page is
- *	unmapped and unbusied or exclusively busied by the current thread, no
- *	new wirings may be created.
+ *	unmapped and exclusively busied by the current thread, no new wirings
+ *	may be created.
  */
 static inline bool
 vm_page_wired(vm_page_t m)


More information about the svn-src-all mailing list