The behaviour of the lockmgr going back at least to the 4.4BSD-Lite2 was

to downgrade the exclusive lock to shared one when exclusive lock owner
requested shared lock. New lockmgr panics instead.

The vnode_pager_lock function requests shared lock on the vnode backing
the OBJT_VNODE, and can be called when the current thread already holds
an exlcusive lock on the vnode. For instance, it happens when handling
page fault from the VOP_WRITE() uiomove that writes to the file, with
the faulted in page fetched from the vm object backed by the same file.
We then get the situation described above.

Verify whether the vnode is already exclusively locked by the curthread
and request recursed exclusive vnode lock instead of shared, if true.

Reported by:	gallatin
Discussed with:	attilio
This commit is contained in:
kib 2008-07-30 18:16:06 +00:00
parent 6cfc47d2bd
commit 85be7d9093

View File

@ -1179,6 +1179,7 @@ vnode_pager_lock(vm_object_t first_object)
{
struct vnode *vp;
vm_object_t backing_object, object;
int locked, lockf;
VM_OBJECT_LOCK_ASSERT(first_object, MA_OWNED);
for (object = first_object; object != NULL; object = backing_object) {
@ -1196,13 +1197,19 @@ vnode_pager_lock(vm_object_t first_object)
return NULL;
}
vp = object->handle;
locked = VOP_ISLOCKED(vp);
VI_LOCK(vp);
VM_OBJECT_UNLOCK(object);
if (first_object != object)
VM_OBJECT_UNLOCK(first_object);
VFS_ASSERT_GIANT(vp->v_mount);
if (vget(vp, LK_CANRECURSE | LK_INTERLOCK |
LK_RETRY | LK_SHARED, curthread)) {
if (locked == LK_EXCLUSIVE)
lockf = LK_CANRECURSE | LK_INTERLOCK | LK_RETRY |
LK_EXCLUSIVE;
else
lockf = LK_CANRECURSE | LK_INTERLOCK | LK_RETRY |
LK_SHARED;
if (vget(vp, lockf, curthread)) {
VM_OBJECT_LOCK(first_object);
if (object != first_object)
VM_OBJECT_LOCK(object);