Index: sys/vm/vm_fault.c =================================================================== --- sys/vm/vm_fault.c (revision 298579) +++ sys/vm/vm_fault.c (working copy) @@ -137,7 +137,12 @@ release_page(struct faultstate *fs) vm_page_xunbusy(fs->m); vm_page_lock(fs->m); - vm_page_deactivate(fs->m); + if (fs->m->valid == 0) { + if (fs->m->wire_count == 0) + vm_page_free(fs->m); + } else { + vm_page_deactivate(fs->m); + } vm_page_unlock(fs->m); fs->m = NULL; } @@ -294,7 +299,7 @@ vm_fault_hold(vm_map_t map, vm_offset_t vaddr, vm_ struct faultstate fs; struct vnode *vp; vm_page_t m; - int locked, error; + int locked, error, dead; hardfault = 0; growstack = TRUE; @@ -414,7 +419,7 @@ fast_failed: fs.lookup_still_valid = TRUE; - fs.first_m = NULL; + fs.m = fs.first_m = NULL; /* * Search for the page at object/offset. @@ -423,11 +428,20 @@ fast_failed: fs.pindex = fs.first_pindex; while (TRUE) { /* - * If the object is dead, we stop here + * If the object is marked for imminent termination, + * we retry here, since the collapse pass has raced + * with us. Otherwise, if we see terminally dead + * object, return fail. */ - if (fs.object->flags & OBJ_DEAD) { + if ((fs.object->flags & OBJ_DEAD) != 0) { + dead = fs.object->type == OBJT_DEAD; + if (fs.m != NULL && fs.m != fs.first_m) + release_page(&fs); unlock_and_deallocate(&fs); - return (KERN_PROTECTION_FAILURE); + if (dead) + return (KERN_PROTECTION_FAILURE); + pause("vmf_de", 1); + goto RetryFault; } /* @@ -843,6 +857,8 @@ vnode_locked: */ if (vm_page_rename(fs.m, fs.first_object, fs.first_pindex)) { + VM_OBJECT_WUNLOCK(fs.first_object); + release_page(&fs); unlock_and_deallocate(&fs); goto RetryFault; } Index: sys/vm/vm_object.c =================================================================== --- sys/vm/vm_object.c (revision 298579) +++ sys/vm/vm_object.c (working copy) @@ -1583,7 +1583,7 @@ vm_object_backing_scan(vm_object_t object, int op) continue; } - KASSERT(pp == NULL || pp->valid != 0, + KASSERT(pp == NULL || pp->wire_count > 0 || pp->valid != 0, ("unbusy invalid page %p", pp)); if (pp != NULL || vm_pager_has_page(object, @@ -1673,11 +1673,14 @@ vm_object_qcollapse(vm_object_t object) void vm_object_collapse(vm_object_t object) { + vm_object_t backing_object, new_backing_object; + VM_OBJECT_ASSERT_WLOCKED(object); - + + if ((object->flags & OBJ_DEAD) != 0) + return; + vm_object_pip_add(object, 1); while (TRUE) { - vm_object_t backing_object; - /* * Verify that the conditions are right for collapse: * @@ -1703,14 +1706,14 @@ vm_object_collapse(vm_object_t object) break; } - if ( - object->paging_in_progress != 0 || - backing_object->paging_in_progress != 0 - ) { + if (object->paging_in_progress > 1 /* one ref is from us */ || + backing_object->paging_in_progress != 0) { vm_object_qcollapse(object); VM_OBJECT_WUNLOCK(backing_object); break; } + vm_object_pip_add(backing_object, 1); + /* * We know that we can either collapse the backing object (if * the parent is the only reference to it) or (perhaps) have @@ -1793,6 +1796,7 @@ vm_object_collapse(vm_object_t object) KASSERT(backing_object->ref_count == 1, ( "backing_object %p was somehow re-referenced during collapse!", backing_object)); + vm_object_pip_wakeup(backing_object); backing_object->type = OBJT_DEAD; backing_object->ref_count = 0; VM_OBJECT_WUNLOCK(backing_object); @@ -1800,8 +1804,6 @@ vm_object_collapse(vm_object_t object) object_collapses++; } else { - vm_object_t new_backing_object; - /* * If we do not entirely shadow the backing object, * there is nothing we can do so we give up. @@ -1809,6 +1811,7 @@ vm_object_collapse(vm_object_t object) if (object->resident_page_count != object->size && !vm_object_backing_scan(object, OBSC_TEST_ALL_SHADOWED)) { + vm_object_pip_wakeup(backing_object); VM_OBJECT_WUNLOCK(backing_object); break; } @@ -1841,6 +1844,7 @@ vm_object_collapse(vm_object_t object) * its ref_count was at least 2, it will not vanish. */ backing_object->ref_count--; + vm_object_pip_wakeup(backing_object); VM_OBJECT_WUNLOCK(backing_object); object_bypasses++; } @@ -1849,6 +1853,7 @@ vm_object_collapse(vm_object_t object) * Try again with this object's new backing object. */ } + vm_object_pip_wakeup(object); } /* Index: sys/vm/vm_page.c =================================================================== --- sys/vm/vm_page.c (revision 298579) +++ sys/vm/vm_page.c (working copy) @@ -1838,8 +1838,10 @@ retry: m < &m_ret[npages]; m++) { if ((req & VM_ALLOC_WIRED) != 0) m->wire_count = 0; - if (m >= m_tmp) + if (m >= m_tmp) { m->object = NULL; + m->oflags |= VPO_UNMANAGED; + } vm_page_free(m); } return (NULL); @@ -2580,7 +2582,8 @@ vm_page_cache(vm_page_t m) cache_was_empty = vm_radix_is_empty(&object->cache); if (vm_radix_insert(&object->cache, m)) { mtx_unlock(&vm_page_queue_free_mtx); - if (object->resident_page_count == 0) + if (object->type == OBJT_VNODE && + object->resident_page_count == 0) vdrop(object->handle); m->object = NULL; vm_page_free(m);