summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_map.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2000-01-21 20:17:01 +0000
committerdillon <dillon@FreeBSD.org>2000-01-21 20:17:01 +0000
commitcacb1b6d5fff5e1b1a2abfe09c90f2465863d4fd (patch)
treebd8ecae6ce67984f39cbd92f096f9de8db35914b /sys/vm/vm_map.c
parent9f5625a6c5f75cdc10e4e8a3057875594a8cc610 (diff)
downloadFreeBSD-src-cacb1b6d5fff5e1b1a2abfe09c90f2465863d4fd.zip
FreeBSD-src-cacb1b6d5fff5e1b1a2abfe09c90f2465863d4fd.tar.gz
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>
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r--sys/vm/vm_map.c54
1 files changed, 29 insertions, 25 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index a1f422d3..3f5382e 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1636,35 +1636,39 @@ vm_map_clean(map, start, end, syncio, invalidate)
if (object->size < OFF_TO_IDX( offset + size))
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
- * on an error?
+ * Flush pages if writing is allowed, invalidate them
+ * 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
- * the object before it completes is probably a very bad
- * idea.
+ * We cannot lock the vnode and then wait for paging
+ * to complete without deadlocking against vm_fault.
+ * 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;
- if (object->type == OBJT_VNODE)
- vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, curproc);
- flags = (syncio || invalidate) ? OBJPC_SYNC : 0;
- flags |= invalidate ? OBJPC_INVAL : 0;
- vm_object_page_clean(object,
- OFF_TO_IDX(offset),
- OFF_TO_IDX(offset + size + PAGE_MASK),
- flags);
- if (invalidate) {
- vm_object_pip_wait(object, "objmcl");
- vm_object_page_remove(object,
- OFF_TO_IDX(offset),
- OFF_TO_IDX(offset + size + PAGE_MASK),
- FALSE);
- }
- if (object->type == OBJT_VNODE)
- VOP_UNLOCK(object->handle, 0, curproc);
+ int flags;
+
+ vm_object_reference(object);
+ vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, curproc);
+ flags = (syncio || invalidate) ? OBJPC_SYNC : 0;
+ flags |= invalidate ? OBJPC_INVAL : 0;
+ vm_object_page_clean(object,
+ OFF_TO_IDX(offset),
+ OFF_TO_IDX(offset + size + PAGE_MASK),
+ flags);
+ if (invalidate) {
+ /*vm_object_pip_wait(object, "objmcl");*/
+ vm_object_page_remove(object,
+ OFF_TO_IDX(offset),
+ OFF_TO_IDX(offset + size + PAGE_MASK),
+ FALSE);
}
+ VOP_UNLOCK(object->handle, 0, curproc);
+ vm_object_deallocate(object);
}
start += size;
}
OpenPOWER on IntegriCloud