Page MenuHomeFreeBSD

vm_page: Fix dequeue on arches with weak ordering
ClosedPublic

Authored by markj on Wed, Jul 15, 5:15 PM.
Tags
None
Referenced Files
Unknown Object (File)
Wed, Jul 22, 8:19 AM
Unknown Object (File)
Wed, Jul 22, 4:47 AM
Unknown Object (File)
Wed, Jul 22, 4:15 AM
Unknown Object (File)
Wed, Jul 22, 2:21 AM
Unknown Object (File)
Tue, Jul 21, 5:50 PM
Unknown Object (File)
Tue, Jul 21, 7:34 AM
Unknown Object (File)
Tue, Jul 21, 7:23 AM
Unknown Object (File)
Mon, Jul 20, 8:48 PM
Subscribers

Details

Summary

A vm_page's a.queue field records the page queue index for the page
queue to which the page belongs. The PGA_ENQUEUED flag indicates
whether the page is actually enqueued in that queue's TAILQ. When
modifying the a.queue field, you need to hold the page queue lock for
the queue corresponding to the old value, unless the old value is
PQ_NONE.

Suppose a managed page is freed. vm_page_free_prep() calls
vm_page_dequeue_deferred(), which checks whether the page belongs to a
queue; if so it schedules an asynchronous dequeue operation so that page
queue lock acquisitions can be batched if possible.

The dequeue operation must be completed before the page's plinks.q
fields are reused. So, during page allocation, we call
vm_page_dequeue() to finish the dequeue operation. Similarly, since the
buddy allocator uses the plinks.q fields for its own internal linkage,
vm_freelist_add() calls vm_page_dequeue().

_vm_page_pqstate_commit_dequeue() is the function which actually removes
the page from its queue. It sets a.queue = PG_NONE and removes the page
from its queue. However, the update to the page's atomic state is
relaxed, so on systems with store reordering, it may race with a
concurrent enqueue of the page into the buddy queues (probably more
likely) or a page queue.

Fix this: use a release store to update the page's queue state in
_vm_page_pqstate_commit_dequeue(), and make sure that vm_page_dequeue()
uses an acquire load when comparing m->a.queue == PQ_NONE.

PR: 296767

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

markj requested review of this revision.Wed, Jul 15, 5:15 PM
This revision is now accepted and ready to land.Thu, Jul 16, 2:43 PM

I'm surprised that we didn't see this on arm64.

In D58261#1336806, @alc wrote:

I'm surprised that we didn't see this on arm64.

I think there was one arm64 poudriere user who saw a similar panic a few years ago, and I couldn't figure out the problem at the time. I haven't been able to find the report in my inbox though.