Cache the next queue element when traversing a page queue.
When QUEUE_MACRO_DEBUG_TRASH is configured, removing a queue element invalidates its queue linkage pointers. vm_pageout_collect_batch() was relying on these pointers remaining valid after a removal, so modify it to fetch the next queued page before dequeuing the current page. Submitted by: Don Morris <dgmorris@earthlink.net> Reviewed by: cem, vangyzen MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D20842
This commit is contained in:
parent
55c94d640f
commit
d70f0ab38d
@ -266,7 +266,7 @@ static __always_inline void
|
||||
vm_pageout_collect_batch(struct scan_state *ss, const bool dequeue)
|
||||
{
|
||||
struct vm_pagequeue *pq;
|
||||
vm_page_t m, marker;
|
||||
vm_page_t m, marker, n;
|
||||
|
||||
marker = ss->marker;
|
||||
pq = ss->pq;
|
||||
@ -277,7 +277,8 @@ vm_pageout_collect_batch(struct scan_state *ss, const bool dequeue)
|
||||
vm_pagequeue_lock(pq);
|
||||
for (m = TAILQ_NEXT(marker, plinks.q); m != NULL &&
|
||||
ss->scanned < ss->maxscan && ss->bq.bq_cnt < VM_BATCHQUEUE_SIZE;
|
||||
m = TAILQ_NEXT(m, plinks.q), ss->scanned++) {
|
||||
m = n, ss->scanned++) {
|
||||
n = TAILQ_NEXT(m, plinks.q);
|
||||
if ((m->flags & PG_MARKER) == 0) {
|
||||
KASSERT((m->aflags & PGA_ENQUEUED) != 0,
|
||||
("page %p not enqueued", m));
|
||||
|
Loading…
Reference in New Issue
Block a user