Index: sys/vm/vm_object.c =================================================================== --- sys/vm/vm_object.c +++ sys/vm/vm_object.c @@ -1499,7 +1499,7 @@ { vm_page_t m, m_next; vm_object_t orig_object, new_object, backing_object; - vm_pindex_t idx, offidxstart; + vm_pindex_t busystart, idx, offidxstart; vm_size_t size; orig_object = entry->object.vm_object; @@ -1554,8 +1554,14 @@ * that the object is in transition. */ vm_object_set_flag(orig_object, OBJ_SPLIT); + busystart = size; +#ifdef INVARIANTS + idx = offidxstart; +#endif retry: m = vm_page_find_least(orig_object, offidxstart); + KASSERT(m == NULL || idx <= m->pindex - offidxstart, + ("%s: object %p was repopulated", __func__, orig_object)); for (; m != NULL && (idx = m->pindex - offidxstart) < size; m = m_next) { m_next = TAILQ_NEXT(m, listq); @@ -1610,8 +1616,15 @@ */ vm_reserv_rename(m, new_object, orig_object, offidxstart); #endif + + /* + * orig_object's type may change while sleeping, so keep track + * of the beginning of the busied range. + */ if (orig_object->type != OBJT_SWAP) vm_page_xunbusy(m); + else if (busystart == size) + busystart = idx; } if (orig_object->type == OBJT_SWAP) { /* @@ -1619,8 +1632,10 @@ * and new_object's locks are released and reacquired. */ swap_pager_copy(orig_object, new_object, offidxstart, 0); - TAILQ_FOREACH(m, &new_object->memq, listq) - vm_page_xunbusy(m); + m = vm_page_find_least(new_object, busystart); + if (m != NULL) + TAILQ_FOREACH_FROM(m, &new_object->memq, listq) + vm_page_xunbusy(m); } vm_object_clear_flag(orig_object, OBJ_SPLIT); VM_OBJECT_WUNLOCK(orig_object);