summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2015-11-02 13:14:27 +0000
committerkib <kib@FreeBSD.org>2015-11-02 13:14:27 +0000
commit1cfef4015ed1c4b9f7101ea6be8b785dd4b11f0d (patch)
tree2764e6d02df371036e65361126994599e31ac738
parent53802741e62fe78e1a0e452b31642498a27474bb (diff)
downloadFreeBSD-src-1cfef4015ed1c4b9f7101ea6be8b785dd4b11f0d.zip
FreeBSD-src-1cfef4015ed1c4b9f7101ea6be8b785dd4b11f0d.tar.gz
MFC r289496:
Modify the 'unchanged' calculation bu dereferencing the marker tailq pointers, which is known to belong to the queue.
-rw-r--r--sys/vm/vm_pageout.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index ed80b1b..2cc738d 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -286,11 +286,21 @@ vm_pageout_fallback_object_lock(vm_page_t m, vm_page_t *next)
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);
}
@@ -327,7 +337,9 @@ vm_pageout_page_lock(vm_page_t m, vm_page_t *next)
/* 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);
}
OpenPOWER on IntegriCloud