FBSD: Avoid recursive osi_VM_StoreAllSegments lock 00/14000/6
authorAndrew Deason <adeason@dson.org>
Wed, 1 Jan 2020 23:09:24 +0000 (17:09 -0600)
committerBenjamin Kaduk <kaduk@mit.edu>
Thu, 11 Mar 2021 22:37:53 +0000 (17:37 -0500)
commitbdd4a0c78b1acaf1c947ca53d16159ef95cc9840
treeae2e9515709128303f09c304b9f22a783a8885ff
parent14cbd02b8a1a4f1d3c30dd4fb2864d35f39a95eb
FBSD: Avoid recursive osi_VM_StoreAllSegments lock

Currently, osi_VM_StoreAllSegments calls vget() for the given vnode,
which requires locking the vnode. However, the vnode should already be
locked. For example, when called from the close syscall, we reach this
function via: vn_close1 -> afs_vop_close -> afs_close ->
afs_StoreOnLastReference -> afs_StoreAllSegments ->
osi_VM_StoreAllSegments. This causes a panic like so:

    kernel: panic: lockmgr_xlock_hard: recursing on non recursive lockmgr 0x[...] @ /usr/src/sys/kern/vfs_subr.c:2730

We can also reach this code path from the BOP_STORE background
operation (BStore -> afs_StoreOnLastReference -> afs_StoreAllSegments
-> osi_VM_StoreAllSegments), initiated from afs_close(), which has the
vnode locked. In this case, we won't be recursively locking the vnode,
since the process calling afs_close() is the one that holds the lock,
and the background thread is the process trying to lock the vnode
again. So we'll just deadlock.

From the comments in this function, it seems like locking the vnode at
all in here is unnecessary, since the vnode should be locked from the
higher-level functions anyway. So just skip the vget and all of the
related looping retry logic. As a result, this function can now become
somewhat simplified.

Change-Id: Ic5a18de46e51dc86190207163ad0fe73bc03cbd7
Reviewed-on: https://gerrit.openafs.org/14000
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
src/afs/FBSD/osi_vm.c