kernel -- vm_object locking Part 2: Lockup a few vm_object users.
authorVenkatesh Srinivas <me@endeavour.zapto.org>
Fri, 4 Mar 2011 14:40:39 +0000 (06:40 -0800)
committerVenkatesh Srinivas <me@endeavour.zapto.org>
Fri, 4 Mar 2011 14:40:39 +0000 (06:40 -0800)
sys/kern/vfs_subr.c
sys/vm/device_pager.c
sys/vm/vm_contig.c
sys/vm/vm_kern.c
sys/vm/vm_map.c
sys/vm/vm_object.c
sys/vm/vm_page.c
sys/vm/vm_pageout.c
sys/vm/vm_zone.c

index 7d75d3f..2b82bc7 100644 (file)
@@ -37,7 +37,6 @@
  *
  *     @(#)vfs_subr.c  8.31 (Berkeley) 5/26/95
  * $FreeBSD: src/sys/kern/vfs_subr.c,v 1.249.2.30 2003/04/04 20:35:57 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_subr.c,v 1.118 2008/09/17 21:44:18 dillon Exp $
  */
 
 /*
@@ -1244,7 +1243,13 @@ vclean_vxlocked(struct vnode *vp, int flags)
         * If the vnode has an object, destroy it.
         */
        lwkt_gettoken(&vmobj_token);
-       if ((object = vp->v_object) != NULL) {
+       object = vp->v_object;
+       if (object != NULL) {
+               /*
+                * Use vm_object_lock() rather than vm_object_hold to avoid
+                * creating an extra (self-)hold on the object.
+                */
+               vm_object_lock(object);
                KKASSERT(object == vp->v_object);
                if (object->ref_count == 0) {
                        if ((object->flags & OBJ_DEAD) == 0)
@@ -1253,6 +1258,7 @@ vclean_vxlocked(struct vnode *vp, int flags)
                        vm_pager_deallocate(object);
                }
                vclrflags(vp, VOBJBUF);
+               vm_object_unlock(object);
        }
        lwkt_reltoken(&vmobj_token);
        KKASSERT((vp->v_flag & VOBJBUF) == 0);
index 5587480..88831ab 100644 (file)
@@ -211,10 +211,12 @@ dev_pager_getpage(vm_object_t object, vm_page_t *mpp, int seqaccess)
                TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist,
                                  page, pageq);
                lwkt_gettoken(&vm_token);
+               vm_object_hold(object);
                crit_enter();
                vm_page_free(*mpp);
                vm_page_insert(page, object, offset);
                crit_exit();
+               vm_object_drop(object);
                lwkt_reltoken(&vm_token);
        }
        mtx_unlock(&dev_pager_mtx);
index 55e6e2e..7c0350a 100644 (file)
@@ -446,6 +446,7 @@ vm_contig_pg_kmap(int start, u_long size, vm_map_t map, int flags)
        /*
         * kernel_object maps 1:1 to kernel_map.
         */
+       vm_object_hold(&kernel_object);
        vm_object_reference(&kernel_object);
        vm_map_insert(map, &count, 
                      &kernel_object, addr,
@@ -467,6 +468,8 @@ vm_contig_pg_kmap(int start, u_long size, vm_map_t map, int flags)
        }
        vm_map_wire(map, addr, addr + size, 0);
 
+       vm_object_drop(&kernel_object);
+
        lwkt_reltoken(&vm_token);
        crit_exit();
        return (addr);
index f8726e1..b28bcb9 100644 (file)
@@ -216,6 +216,7 @@ kmem_alloc3(vm_map_t map, vm_size_t size, int kmflags)
         * race with page-out.  vm_map_wire will wire the pages.
         */
        lwkt_gettoken(&vm_token);
+       vm_object_hold(&kernel_object);
        for (i = gstart; i < size; i += PAGE_SIZE) {
                vm_page_t mem;
 
@@ -227,6 +228,7 @@ kmem_alloc3(vm_map_t map, vm_size_t size, int kmflags)
                vm_page_flag_clear(mem, PG_ZERO);
                vm_page_wakeup(mem);
        }
+       vm_object_drop(&kernel_object);
        lwkt_reltoken(&vm_token);
 
        /*
index 966213d..08b8186 100644 (file)
@@ -2837,6 +2837,7 @@ vm_map_check_protection(vm_map_t map, vm_offset_t start, vm_offset_t end,
  * being a negative impact on memory usage.
  *
  * The vm_map must be exclusively locked.
+ * The orig_object should be held.
  */
 static void
 vm_map_split(vm_map_entry_t entry)
@@ -2885,8 +2886,11 @@ vm_map_split(vm_map_entry_t entry)
        lwkt_gettoken(&vm_token);
        lwkt_gettoken(&vmobj_token);
 
+       vm_object_hold(new_object);
+
        source = orig_object->backing_object;
        if (source != NULL) {
+               vm_object_hold(source);
                /* Referenced by new_object */
                vm_object_reference_locked(source);
                LIST_INSERT_HEAD(&source->shadow_head,
@@ -2898,6 +2902,7 @@ vm_map_split(vm_map_entry_t entry)
                new_object->backing_object = source;
                source->shadow_count++;
                source->generation++;
+               vm_object_drop(source);
        }
 
        for (idx = 0; idx < size; idx++) {
@@ -2947,6 +2952,7 @@ vm_map_split(vm_map_entry_t entry)
        entry->object.vm_object = new_object;
        entry->offset = 0LL;
        vm_object_deallocate_locked(orig_object);
+       vm_object_drop(new_object);
        lwkt_reltoken(&vmobj_token);
        lwkt_reltoken(&vm_token);
 }
index e9d4503..499a0a4 100644 (file)
@@ -488,14 +488,14 @@ vm_object_terminate(vm_object_t object)
        lwkt_reltoken(&vm_token);
 
        /*
-        * Wait for the object hold count to hit zero
+        * Let the pager know object is dead.
         */
-       vm_object_hold_wait(object);
+       vm_pager_deallocate(object);
 
        /*
-        * Let the pager know object is dead.
+        * Wait for the object hold count to hit zero
         */
-       vm_pager_deallocate(object);
+       vm_object_hold_wait(object);
 
        /*
         * Remove the object from the global object list.
index 7a4d42e..174cfe7 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -37,7 +33,6 @@
  *
  *     from: @(#)vm_page.c     7.4 (Berkeley) 5/7/91
  * $FreeBSD: src/sys/vm/vm_page.c,v 1.147.2.18 2002/03/10 05:03:19 alc Exp $
- * $DragonFly: src/sys/vm/vm_page.c,v 1.40 2008/08/25 17:01:42 dillon Exp $
  */
 
 /*
@@ -417,6 +412,7 @@ vm_page_unhold(vm_page_t m)
  *
  * This routine may not block.
  * This routine must be called with the vm_token held.
+ * This routine must be called with the vm_object held.
  * This routine must be called with a critical section held.
  */
 void
@@ -491,6 +487,8 @@ vm_page_remove(vm_page_t m)
 
        object = m->object;
 
+       vm_object_hold(object);
+
        /*
         * Remove the page from the object and update the object.
         */
@@ -500,6 +498,8 @@ vm_page_remove(vm_page_t m)
        object->generation++;
        m->object = NULL;
 
+       vm_object_drop(object);
+
        lwkt_reltoken(&vm_token);
 }
 
@@ -550,12 +550,14 @@ void
 vm_page_rename(vm_page_t m, vm_object_t new_object, vm_pindex_t new_pindex)
 {
        lwkt_gettoken(&vm_token);
+       vm_object_hold(new_object);
        vm_page_remove(m);
        vm_page_insert(m, new_object, new_pindex);
        if (m->queue - m->pc == PQ_CACHE)
                vm_page_deactivate(m);
        vm_page_dirty(m);
        vm_page_wakeup(m);
+       vm_object_drop(new_object);
        lwkt_reltoken(&vm_token);
 }
 
@@ -1575,6 +1577,7 @@ vm_page_grab(vm_object_t object, vm_pindex_t pindex, int allocflags)
        KKASSERT(allocflags &
                (VM_ALLOC_NORMAL|VM_ALLOC_INTERRUPT|VM_ALLOC_SYSTEM));
        lwkt_gettoken(&vm_token);
+       vm_object_hold(object);
 retrylookup:
        if ((m = vm_page_lookup(object, pindex)) != NULL) {
                if (m->busy || (m->flags & PG_BUSY)) {
@@ -1603,6 +1606,7 @@ retrylookup:
                goto retrylookup;
        }
 done:
+       vm_object_drop(object);
        lwkt_reltoken(&vm_token);
        return(m);
 }
index 5d5f70a..589aad8 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -68,7 +64,6 @@
  * rights to redistribute these changes.
  *
  * $FreeBSD: src/sys/vm/vm_pageout.c,v 1.151.2.15 2002/12/29 18:21:04 dillon Exp $
- * $DragonFly: src/sys/vm/vm_pageout.c,v 1.36 2008/07/01 02:02:56 dillon Exp $
  */
 
 /*
@@ -297,6 +292,7 @@ vm_pageout_clean(vm_page_t m)
         * forward scan if room remains.
         */
 
+       vm_object_hold(object);
 more:
        while (ib && pageout_count < vm_pageout_page_count) {
                vm_page_t p;
@@ -364,6 +360,8 @@ more:
        if (ib && pageout_count < vm_pageout_page_count)
                goto more;
 
+       vm_object_drop(object);
+
        /*
         * we allow reads during pageouts...
         */
@@ -489,6 +487,7 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags)
  *
  * The map must be locked.
  * The caller must hold vm_token.
+ * The caller must hold the vm_object.
  */
 static int vm_pageout_object_deactivate_pages_callback(vm_page_t, void *);
 
@@ -497,16 +496,23 @@ vm_pageout_object_deactivate_pages(vm_map_t map, vm_object_t object,
                                   vm_pindex_t desired, int map_remove_only)
 {
        struct rb_vm_page_scan_info info;
+       vm_object_t tmp;
        int remove_mode;
 
-       if (object->type == OBJT_DEVICE || object->type == OBJT_PHYS)
-               return;
-
        while (object) {
                if (pmap_resident_count(vm_map_pmap(map)) <= desired)
                        return;
-               if (object->paging_in_progress)
+
+               vm_object_hold(object);
+
+               if (object->type == OBJT_DEVICE || object->type == OBJT_PHYS) {
+                       vm_object_drop(object);
+                       return;
+               }
+               if (object->paging_in_progress) {
+                       vm_object_drop(object);
                        return;
+               }
 
                remove_mode = map_remove_only;
                if (object->shadow_count > 1)
@@ -526,12 +532,15 @@ vm_pageout_object_deactivate_pages(vm_map_t map, vm_object_t object,
                                &info
                );
                crit_exit();
-               object = object->backing_object;
+               tmp = object->backing_object;
+               vm_object_drop(object);
+               object = tmp;
        }
 }
 
 /*
  * The caller must hold vm_token.
+ * The caller must hold the vm_object.
  */
 static int
 vm_pageout_object_deactivate_pages_callback(vm_page_t p, void *data)
@@ -633,7 +642,7 @@ vm_pageout_map_deactivate_pages(vm_map_t map, vm_pindex_t desired)
                tmpe = tmpe->next;
        }
 
-       if (bigobj)
+       if (bigobj) 
                vm_pageout_object_deactivate_pages(map, bigobj, desired, 0);
 
        /*
@@ -648,7 +657,7 @@ vm_pageout_map_deactivate_pages(vm_map_t map, vm_pindex_t desired)
                case VM_MAPTYPE_NORMAL:
                case VM_MAPTYPE_VPAGETABLE:
                        obj = tmpe->object.vm_object;
-                       if (obj)
+                       if (obj) 
                                vm_pageout_object_deactivate_pages(map, obj, desired, 0);
                        break;
                default:
index c21d6e6..82e0ceb 100644 (file)
@@ -407,6 +407,7 @@ zget(vm_zone_t z)
                 * simply populate an existing mapping.
                 */
                lwkt_gettoken(&vm_token);
+               vm_object_hold(z->zobj);
                savezpc = z->zpagecount;
                nbytes = z->zpagecount * PAGE_SIZE;
                nbytes -= nbytes % z->zsize;
@@ -418,7 +419,7 @@ zget(vm_zone_t z)
                        m = vm_page_alloc(z->zobj, z->zpagecount,
                                          z->zallocflag);
                        /* note: z might be modified due to blocking */
-                       if (m == NULL)
+                       if (m == NULL) 
                                break;
 
                        /*
@@ -439,6 +440,7 @@ zget(vm_zone_t z)
                        vmstats.v_wire_count++;
                }
                nitems = ((z->zpagecount * PAGE_SIZE) - nbytes) / z->zsize;
+               vm_object_drop(z->zobj);
                lwkt_reltoken(&vm_token);
        } else if (z->zflags & ZONE_SPECIAL) {
                /*