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:
parent
5461ac5c7d
commit
ff359f84c9
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user