diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 2fc6a0e1995a..0ef7212777ca 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -290,14 +290,17 @@ RetryFault:; * * XXX vnode_pager_lock() can block without releasing the map lock. */ - if (!fs.map->system_map) + if (fs.first_object->flags & OBJ_NEEDGIANT) mtx_lock(&Giant); VM_OBJECT_LOCK(fs.first_object); vm_object_reference_locked(fs.first_object); fs.vp = vnode_pager_lock(fs.first_object); KASSERT(fs.vp == NULL || !fs.map->system_map, ("vm_fault: vnode-backed object mapped by system map")); - if (debug_mpsafevm && !fs.map->system_map) + KASSERT((fs.first_object->flags & OBJ_NEEDGIANT) == 0 || + !fs.map->system_map, + ("vm_fault: Object requiring giant mapped by system map")); + if (fs.first_object->flags & OBJ_NEEDGIANT && debug_mpsafevm) mtx_unlock(&Giant); vm_object_pip_add(fs.first_object, 1); @@ -378,10 +381,12 @@ RetryFault:; } unlock_map(&fs); if (fs.vp != NULL) { - mtx_lock(&Giant); + int vfslck; + + vfslck = VFS_LOCK_GIANT(fs.vp->v_mount); vput(fs.vp); - mtx_unlock(&Giant); fs.vp = NULL; + VFS_UNLOCK_GIANT(vfslck); } VM_OBJECT_LOCK(fs.object); if (fs.m == vm_page_lookup(fs.object, diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index ae0197601c66..63078ff83d77 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1230,6 +1230,7 @@ vm_object_shadow( length = PQ_L2_SIZE / 3 + PQ_PRIME1; result->pg_color = (source->pg_color + length * source->generation) & PQ_L2_MASK; + result->flags |= source->flags & OBJ_NEEDGIANT; VM_OBJECT_UNLOCK(source); next_index = (result->pg_color + PQ_L2_SIZE / 3 + PQ_PRIME1) & PQ_L2_MASK; diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index df3bddd64a30..2de99093d333 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -145,6 +145,7 @@ struct vm_object { #define OBJ_CLEANING 0x0200 #define OBJ_ONEMAPPING 0x2000 /* One USE (a single, non-forked) mapping flag */ #define OBJ_DISCONNECTWNT 0x4000 /* disconnect from vnode wanted */ +#define OBJ_NEEDGIANT 0x8000 /* object requires Giant */ #define IDX_TO_OFF(idx) (((vm_ooffset_t)(idx)) << PAGE_SHIFT) #define OFF_TO_IDX(off) ((vm_pindex_t)(((vm_ooffset_t)(off)) >> PAGE_SHIFT)) diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 2ad9d15cbb4a..733eea45d4f5 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -231,6 +231,8 @@ vnode_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, object->un_pager.vnp.vnp_size = size; object->handle = handle; + if (VFS_NEEDSGIANT(vp->v_mount)) + vm_object_set_flag(object, OBJ_NEEDGIANT); vp->v_object = object; } else { object->ref_count++; @@ -1188,6 +1190,7 @@ vnode_pager_lock(vm_object_t first_object) 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)) { VM_OBJECT_LOCK(first_object);