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
This commit is contained in:
parent
bee4a63bb7
commit
69b8585e79
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=289496
@ -292,11 +292,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);
|
||||
}
|
||||
@ -333,7 +343,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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user