Index: sys/vm/vm_object.c =================================================================== --- sys/vm/vm_object.c +++ sys/vm/vm_object.c @@ -1426,10 +1426,10 @@ static int vm_object_backing_scan(vm_object_t object, int op) { - int r = 1; vm_page_t p; vm_object_t backing_object; vm_pindex_t backing_offset_index; + int r = 1, pbusy; VM_OBJECT_ASSERT_WLOCKED(object); VM_OBJECT_ASSERT_WLOCKED(object->backing_object); @@ -1566,14 +1566,7 @@ } pp = vm_page_lookup(object, new_pindex); - if ( - (op & OBSC_COLLAPSE_NOWAIT) != 0 && - (pp != NULL && pp->valid == 0) - ) { - if (backing_object->type == OBJT_SWAP) - swap_pager_freespace(backing_object, - p->pindex, 1); - + if (pp != NULL && pp->valid == 0) { /* * The page in the parent is not (yet) valid. * We don't know anything about the state of @@ -1585,7 +1578,30 @@ * page before we can (re)lock the parent. * Hence we can get here. */ - p = next; + if ((op & OBSC_COLLAPSE_NOWAIT) != 0) { + p = next; + continue; + } + + /* + * Same thing goes for the WAIT case, except we + * must not skip any pages in the backing + * object. Relock and try again from the top, + * draining busy status (if any) on the parent + * page. + */ + pbusy = vm_page_busied(pp); + if (pbusy) + vm_page_lock(pp); + VM_OBJECT_WUNLOCK(object); + VM_OBJECT_WUNLOCK(backing_object); + + if (pbusy) + vm_page_busy_sleep(pp, "vmocolp"); + + VM_OBJECT_WLOCK(object); + VM_OBJECT_WLOCK(backing_object); + p = TAILQ_FIRST(&backing_object->memq); continue; } if (