svn commit: r338536 - head/sys/vm
Mark Johnston
markj at FreeBSD.org
Sat Sep 8 21:49:45 UTC 2018
Author: markj
Date: Sat Sep 8 21:49:43 2018
New Revision: 338536
URL: https://svnweb.freebsd.org/changeset/base/338536
Log:
Relax an assertion in vm_pqbatch_process_page().
While executing vm_pqbatch_process_page(m), m->queue may change to
PQ_NONE if the page daemon is concurrently freeing the page. In this
case m's queue state flags must be clear, so vm_pqbatch_process_page()
will be a no-op, but the race could cause spurious assertion failures.
Correct the assertion which assumed that m->queue's value does not
change while the page queue lock is held.
Reviewed by: alc, kib
Reported and tested by: pho
Approved by: re (gjb)
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D17027
Modified:
head/sys/vm/vm_page.c
Modified: head/sys/vm/vm_page.c
==============================================================================
--- head/sys/vm/vm_page.c Sat Sep 8 19:17:22 2018 (r338535)
+++ head/sys/vm/vm_page.c Sat Sep 8 21:49:43 2018 (r338536)
@@ -3107,28 +3107,35 @@ static inline void
vm_pqbatch_process_page(struct vm_pagequeue *pq, vm_page_t m)
{
struct vm_domain *vmd;
- uint8_t aflags;
+ uint8_t qflags;
CRITICAL_ASSERT(curthread);
vm_pagequeue_assert_locked(pq);
- KASSERT(pq == vm_page_pagequeue(m),
- ("page %p doesn't belong to %p", m, pq));
- aflags = m->aflags;
- if ((aflags & PGA_DEQUEUE) != 0) {
- if (__predict_true((aflags & PGA_ENQUEUED) != 0)) {
+ /*
+ * The page daemon is allowed to set m->queue = PQ_NONE without
+ * the page queue lock held. In this case it is about to free the page,
+ * which must not have any queue state.
+ */
+ qflags = atomic_load_8(&m->aflags) & PGA_QUEUE_STATE_MASK;
+ KASSERT(pq == vm_page_pagequeue(m) || qflags == 0,
+ ("page %p doesn't belong to queue %p but has queue state %#x",
+ m, pq, qflags));
+
+ if ((qflags & PGA_DEQUEUE) != 0) {
+ if (__predict_true((qflags & PGA_ENQUEUED) != 0)) {
TAILQ_REMOVE(&pq->pq_pl, m, plinks.q);
vm_pagequeue_cnt_dec(pq);
}
vm_page_dequeue_complete(m);
- } else if ((aflags & (PGA_REQUEUE | PGA_REQUEUE_HEAD)) != 0) {
- if ((aflags & PGA_ENQUEUED) != 0)
+ } else if ((qflags & (PGA_REQUEUE | PGA_REQUEUE_HEAD)) != 0) {
+ if ((qflags & PGA_ENQUEUED) != 0)
TAILQ_REMOVE(&pq->pq_pl, m, plinks.q);
else {
vm_pagequeue_cnt_inc(pq);
vm_page_aflag_set(m, PGA_ENQUEUED);
}
- if ((aflags & PGA_REQUEUE_HEAD) != 0) {
+ if ((qflags & PGA_REQUEUE_HEAD) != 0) {
KASSERT(m->queue == PQ_INACTIVE,
("head enqueue not supported for page %p", m));
vmd = vm_pagequeue_domain(m);
More information about the svn-src-all
mailing list