kernel - do not have hold ref on object across a vm_map_split()
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 10 Jun 2011 17:35:24 +0000 (10:35 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 10 Jun 2011 17:35:24 +0000 (10:35 -0700)
* Just use vm_object_lock() (which uses a pool token) and do not hold
  a count on the object which can cause a deadlock when vm_map_split()
  tries to destroy the original object.

Found-by: Venkatesh Srinivas <me@endeavour.zapto.org>
sys/vm/vm_map.c

index f3fcef8..5c7df73 100644 (file)
@@ -2996,24 +2996,27 @@ vm_map_copy_entry(vm_map_t src_map, vm_map_t dst_map,
                /*
                 * Make a copy of the object.
                 *
-                * The object must be held prior to checking the object type
-                * and for the call to vm_object_collapse().
+                * The object must be locked prior to checking the object type
+                * and for the call to vm_object_collapse() and vm_map_split().
+                * We cannot use *_hold() here because the split code will
+                * probably try to destroy the object.  The lock is a pool
+                * token and doesn't care.
                 */
                if ((src_object = src_entry->object.vm_object) != NULL) {
-                       vm_object_hold(src_object);
+                       vm_object_lock(src_object);
                        if ((src_object->handle == NULL) &&
                                (src_object->type == OBJT_DEFAULT ||
                                 src_object->type == OBJT_SWAP)) {
                                vm_object_collapse(src_object);
                                if ((src_object->flags & (OBJ_NOSPLIT|OBJ_ONEMAPPING)) == OBJ_ONEMAPPING) {
                                        vm_map_split(src_entry);
-                                       vm_object_drop(src_object);
+                                       vm_object_unlock(src_object);
                                        src_object = src_entry->object.vm_object;
-                                       vm_object_hold(src_object);
+                                       vm_object_lock(src_object);
                                }
                        }
                        vm_object_reference_locked(src_object);
-                       vm_object_drop(src_object);
+                       vm_object_unlock(src_object);
                        vm_object_clear_flag(src_object, OBJ_ONEMAPPING);
                        dst_entry->object.vm_object = src_object;
                        src_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY);