The pagedaemon inspects the top-most sleeping pmemrange allocation for for size and constraint, and passes this information to the inactive scanner. The idea is that an extremely high-size and strict-constraint allocation that fails repeatedly would percolate to the top of the list. To ensure the scanner can inspect this allocation's constraint via the pointer, it gets locked. Then we release tons of memory from the buffer cache, and run the scanner to recover free memory. At the same time, other running operations free and allocate memory and wakeup all the sleeping pmemrange allocations, but no, not this one, because it is locked so that the pointer won't become invalid. When the scan is done, we may once again have meager memory resources because all the good stuff was allocated by asyncronous allocators, potentially creating substantial fragmentation not compatible with the constraint. Now, the sleeping request gets unlocked and woken to re-check it's requirements and guess what, the constraint fails it goes back to sleep, and we need to go around again... In practice this is a hard uvm deadlock. Instead, copy the constraint from the request, do not lock the allocation request and ignore the pointer. Instrumentation is showing this top-most request is ALWAYS satisfied during the bufbackoff() sequence, but we'll continue passing the constraint to the scanner as a last-ditch effort. ok claudio beck kettenis