kernel - Fix deadlock assertion panic with mmap/read combos
* Normally the uiomove() is called with the buffer locked. When
uiomove()ing into mmap'd memory this can cause a lock recursion and
panic, or a deadlock.
* Fix the problem by adding bqhold() and bqdrop() and adjusting the use
of the b_refs field to prevent the buffer from being invalidated,
allowing VFS VOP_READ operations to release the buffer prior to the
uiomove() into user memory.
* Adjust brelse() and getnewbuf() to do the right thing. Note that there
are two cases where b_refs can transition from 0->1. The VFS
release/uiomove case will only transition b_refs while the buffer is
locked while findblk() will transition b_refs at any time (while holding
the spin lock). We only care about retaining the VM pages in the
transition-during-locked case.
* Original problem reproducable with
grep -r --mmap SomeString /usr/pkgsrc
Reported-by: YONETANI Tomokazu <qhwt.dfly@les.ath.cx>