Fix a deadlock between msync(..., MS_INVALIDATE) and vm_fault. The

invalidation code cannot wait for paging to complete while holding a
    vnode lock, so we don't wait.  Instead we simply allow the lower level
    code to simply block on any busy pages it encounters.  I think Yahoo
    may be the only entity in the entire world that actually uses this
    msync feature :-).

Bug reported by:  Paul Saab <paul@mu.org>
This commit is contained in:
Matthew Dillon 2000-01-21 20:17:01 +00:00
parent 5461ac5c7d
commit ff359f84c9

View File

@ -1636,35 +1636,39 @@ vm_map_clean(map, start, end, syncio, invalidate)
if (object->size < OFF_TO_IDX( offset + size)) if (object->size < OFF_TO_IDX( offset + size))
size = IDX_TO_OFF(object->size) - offset; size = IDX_TO_OFF(object->size) - offset;
} }
if (object && (object->type == OBJT_VNODE)) { if (object && (object->type == OBJT_VNODE) &&
(current->protection & VM_PROT_WRITE)) {
/* /*
* Flush pages if writing is allowed. XXX should we continue * Flush pages if writing is allowed, invalidate them
* on an error? * if invalidation requested. Pages undergoing I/O
* will be ignored by vm_object_page_remove().
* *
* XXX Doing async I/O and then removing all the pages from * We cannot lock the vnode and then wait for paging
* the object before it completes is probably a very bad * to complete without deadlocking against vm_fault.
* idea. * Instead we simply call vm_object_page_remove() and
* allow it to block internally on a page-by-page
* basis when it encounters pages undergoing async
* I/O.
*/ */
if (current->protection & VM_PROT_WRITE) { int flags;
int flags;
if (object->type == OBJT_VNODE) vm_object_reference(object);
vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, curproc); vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, curproc);
flags = (syncio || invalidate) ? OBJPC_SYNC : 0; flags = (syncio || invalidate) ? OBJPC_SYNC : 0;
flags |= invalidate ? OBJPC_INVAL : 0; flags |= invalidate ? OBJPC_INVAL : 0;
vm_object_page_clean(object, vm_object_page_clean(object,
OFF_TO_IDX(offset), OFF_TO_IDX(offset),
OFF_TO_IDX(offset + size + PAGE_MASK), OFF_TO_IDX(offset + size + PAGE_MASK),
flags); flags);
if (invalidate) { if (invalidate) {
vm_object_pip_wait(object, "objmcl"); /*vm_object_pip_wait(object, "objmcl");*/
vm_object_page_remove(object, vm_object_page_remove(object,
OFF_TO_IDX(offset), OFF_TO_IDX(offset),
OFF_TO_IDX(offset + size + PAGE_MASK), OFF_TO_IDX(offset + size + PAGE_MASK),
FALSE); FALSE);
}
if (object->type == OBJT_VNODE)
VOP_UNLOCK(object->handle, 0, curproc);
} }
VOP_UNLOCK(object->handle, 0, curproc);
vm_object_deallocate(object);
} }
start += size; start += size;
} }