Do not grab the `vmmaplk' recursively, prevent a self-deadlock.
authormpi <mpi@openbsd.org>
Sat, 20 May 2023 12:48:36 +0000 (12:48 +0000)
committermpi <mpi@openbsd.org>
Sat, 20 May 2023 12:48:36 +0000 (12:48 +0000)
commitb8462368b06c88b48d3cc260552a44ba42ca10ce
tree150a3a2660b1d261284d0418821121e88bff0466
parent6a9ebb2fe80ab5d5e37c3efa9a90826539df8d1b
Do not grab the `vmmaplk' recursively, prevent a self-deadlock.

Change the semantic of vm_map_busy() to be able to completely unlock the
`vmmaplk' instead of downgrading it to a read lock in mlock(2).  This is
necessary because uvm_fault_wire() tries to re-grab the same lock.

We now keep track of the thread currently holding the vmmap busy to ensure
it can relock & unbusy the vmmap.  The new pattern becomes:

....vm_map_lock(map);
....vm_map_busy(map); /* prevent other threads to grab an exclusive lock */
....vm_map_unlock(map);
....
..../*
.... * Do some stuff generally requiring a tsleep(9).
.... */
....
....vm_map_lock(map);
....vm_map_unbusy(map); /* allow other threads to make progress after unlock */
....vm_map_unlock(map);

Fix adapted from NetBSD's r1.249 of uvm/uvm_map.c.  Issue reported by
Jacqueline Jolicoeur exposed by a "wallet refresh" of the Monero App.
Panic hand-copied below:

sleep_finish()
rw_enter()
uvmfault_lookup()
uvm_fault_check()
uvm_fault()
uvm_fault_wire()
uvm_map_pageable_wire()
sys_mlock()

This version skips bumping the map's timestamp if the lock is acquired by the
thread marked the VM map busy.  This prevents a KASSERT() reported by bluhm@
triggered by regress/misc/posixtestsuite conformance/interfaces/mmap/18-1

ok kettenis@
sys/uvm/uvm_map.c
sys/uvm/uvm_map.h