summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2008-07-30 18:16:06 +0000
committerkib <kib@FreeBSD.org>2008-07-30 18:16:06 +0000
commit85be7d90931f1721d90ba92387c99e9dd6f5ebec (patch)
treed19baac22a60d4175977ccc5b7376d9bb7bcfc05 /sys/vm
parent6cfc47d2bdeb65da7831a9d200a136973967c8f4 (diff)
downloadFreeBSD-src-85be7d90931f1721d90ba92387c99e9dd6f5ebec.zip
FreeBSD-src-85be7d90931f1721d90ba92387c99e9dd6f5ebec.tar.gz
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
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vnode_pager.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 4758456..61f4fd9 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -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);
OpenPOWER on IntegriCloud