svn commit: r289496 - head/sys/vm
Konstantin Belousov
kib at FreeBSD.org
Sun Oct 18 09:33:30 UTC 2015
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);
}
More information about the svn-src-all
mailing list