Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Oct 2015 09:33:28 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r289496 - head/sys/vm
Message-ID:  <201510180933.t9I9XSCX004707@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sun Oct 18 09:33:28 2015
New Revision: 289496
URL: https://svnweb.freebsd.org/changeset/base/289496

Log:
  Only marker is guaranteed to be present on the queue after the relock
  in vm_pageout_fallback_object_lock() and vm_pageout_page_lock().  The
  check for the m->queue == queue assumes that the page does belong to a
  queue.
  
  Modify the 'unchanged' calculation bu dereferencing the marker tailq
  pointers, which is known to belong to the queue.  Since for a page m
  linked to the queue, m->queue must be equal to the queue index, assert
  this instead of checking.
  
  In collaboration with:	alc
  Sponsored by:	The FreeBSD Foundation (kib)
  MFC after:	2 weeks

Modified:
  head/sys/vm/vm_pageout.c

Modified: head/sys/vm/vm_pageout.c
==============================================================================
--- head/sys/vm/vm_pageout.c	Sun Oct 18 09:02:17 2015	(r289495)
+++ head/sys/vm/vm_pageout.c	Sun Oct 18 09:33:28 2015	(r289496)
@@ -292,11 +292,21 @@ vm_pageout_fallback_object_lock(vm_page_
 	vm_page_lock(m);
 	vm_pagequeue_lock(pq);
 
-	/* Page queue might have changed. */
+	/*
+	 * The page's object might have changed, and/or the page might
+	 * have moved from its original position in the queue.  If the
+	 * page's object has changed, then the caller should abandon
+	 * processing the page because the wrong object lock was
+	 * acquired.  Use the marker's plinks.q, not the page's, to
+	 * determine if the page has been moved.  The state of the
+	 * page's plinks.q can be indeterminate; whereas, the marker's
+	 * plinks.q must be valid.
+	 */
 	*next = TAILQ_NEXT(&marker, plinks.q);
-	unchanged = (m->queue == queue &&
-		     m->object == object &&
-		     &marker == TAILQ_NEXT(m, plinks.q));
+	unchanged = m->object == object &&
+	    m == TAILQ_PREV(&marker, pglist, plinks.q);
+	KASSERT(!unchanged || m->queue == queue,
+	    ("page %p queue %d %d", m, queue, m->queue));
 	TAILQ_REMOVE(&pq->pq_pl, &marker, plinks.q);
 	return (unchanged);
 }
@@ -333,7 +343,9 @@ vm_pageout_page_lock(vm_page_t m, vm_pag
 
 	/* Page queue might have changed. */
 	*next = TAILQ_NEXT(&marker, plinks.q);
-	unchanged = (m->queue == queue && &marker == TAILQ_NEXT(m, plinks.q));
+	unchanged = m == TAILQ_PREV(&marker, pglist, plinks.q);
+	KASSERT(!unchanged || m->queue == queue,
+	    ("page %p queue %d %d", m, queue, m->queue));
 	TAILQ_REMOVE(&pq->pq_pl, &marker, plinks.q);
 	return (unchanged);
 }



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