When a page lookup fails in a vm_page_grab operation, use the results of the failed search, stored in an iterator, to begin the search for a predecessor to use in a call to vm_page_alloc_after(), to avoid doing that search from the root in vm_page_alloc(), as happens now.
Details
Diff Detail
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
sys/vm/vm_page.c | ||
---|---|---|
4825–4826 | Code only sleeps if the page cannot be busied as requested. Initially this comment made me very confused. | |
4830 | The first sentence of the comment should be an assert instead. Overall this is too detailed comment for the internal function. I would leave only the first paragraph of the comment, edited, IMO. | |
4887 | I am not sure about the semantic of VM_ALLOC_WAITFAIL. If we sleep inside vm_page_grab_lookup(), should we also return NULL for VM_ALLOC_WAITFAIL? (This is the pre-existing bug, if indeed a bug). |
sys/vm/vm_page.c | ||
---|---|---|
4887 | BTW, same question about VM_ALLOC_NOWAIT. |
sys/vm/vm_page.c | ||
---|---|---|
4887 | From my reading of this diff, the bug is in the patch, not the existing code. Without the patch, vm_page_grab_sleep(WAITFAIL) will sleep and then return false, and then vm_page_grab() returns NULL. That's the behaviour I'd expect. With the patch, vm_page_grab_lookup(WAITFAIL) will sleep and return NULL, whereupon we try to allocate a page at the pindex. That's incorrect: after sleeping, we don't know the state of the VM object since the VM object lock was dropped. At that point, WAITFAIL means, "signal failure to the caller and let them handle it". The problem with the patch is that the vm_page_grab_lookup() interface is not rich enough: it needs to tell the caller both whether it found and busied a page, and whether it had to sleep in order to do so. |
Backing out the last update to the patch, since I've evidently completely failed to understand @kib's concerns, and so won't try to eliminate the WAITFAIL case from page grabbing.
In vm_page_grab, if VM_ALLOC_WAITFAIL is set in allocflags and vm_page_grab_lookup returns NULL, return NULL.
Add a *found parameter to vm_page_grab_lookup to distinguish found-but-sleep cases from not-found cases.
sys/vm/vm_page.c | ||
---|---|---|
5082 | A portion of the page is zeroed whether or not it was resident already, but the comment implies that it is zeroed only if it had to be paged in. |
sys/vm/vm_page.c | ||
---|---|---|
4831 | This and the next herald comment could be compactified in the same way, by merging the two paragraphs. | |
4849 | So we normally return non-NULL m and simultaneously set *found to false. IMO this should be either fixed or documented that *found is only meaningful when the return value is NULL. | |
4880 | Could we get mpred there with pindex equal our pindex? I do not see why it is impossible, but I am sure that such mpred is wrong (and asserted by) vm_page_alloc_after(). |
sys/vm/vm_page.c | ||
---|---|---|
4880 | Ignore me, we cannot. |