Page MenuHomeFreeBSD

vm_page: Allow PG_NOFREE pages to be freed
Needs ReviewPublic

Authored by markj on Sun, Mar 23, 10:56 PM.

Details

Summary

There is at least one case where we need to support it: kmem_malloc()
might need to allocate multiple pages to satisfy a NOFREE allocation,
which it implements by calling vm_page_alloc() in a loop. If it fails
part-way though, it needs to free already-allocated pages, but this was
illegal.

Convert the bump allocator to a linked list; (ab)use the pindex field of
each page in the list to store the number of contiguous pages in the
block. (Originally I added a new plinks member for this purpose, but
it's not safe to use that until after vm_page_dequeue() is called due to
lazy page queue removal.) Then, modify vm_page_free() to support freeing
pages to this list.

Reported by: syzbot+93bc9edd2d0f22ae426a@syzkaller.appspotmail.com
Fixes: a8693e89e3e4 ("vm: Introduce vm_page_alloc_nofree_domain")

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 63087
Build 59971: arc lint + arc unit

Event Timeline

sys/vm/vm_page.c
4148

With this change, everyone can free NOFREE memory. Is there some way to have a function specifically for freeing NOFREE memory so that this assertion can remain in place for freeing "normal" memory?

Do we want some counter to report how many non-freeable pages were freed? It is some kind of leak, I must admit.

The change looks reasonable, but I'm personally not that keen on introducing the ability to free NOFREE pages.
IMO the key issue here is that vm_page_alloc_nofree should not be used to allocate a batch of pages.

One alternative I can think of is to extend the existing NOFREE allocator with a batched allocation routine, similar to the one proposed in D47050.
This would allow us to easily roll the allocator state back if an allocation fails without having to introduce a way of freeing NOFREE pages.

sys/vm/vm_page.c
2651

Is the __noinline here on purpose or a leftover from a debugging session?