Index: sys/vm/swap_pager.c =================================================================== --- sys/vm/swap_pager.c +++ sys/vm/swap_pager.c @@ -424,6 +424,8 @@ static void swp_pager_meta_free(vm_object_t, vm_pindex_t, vm_pindex_t); static void swp_pager_meta_free_all(vm_object_t); static daddr_t swp_pager_meta_ctl(vm_object_t, vm_pindex_t, int); +static vm_pindex_t swp_pager_meta_find_least(vm_object_t, vm_pindex_t, + daddr_t*); static void swp_pager_init_freerange(daddr_t *start, daddr_t *num) @@ -985,10 +987,13 @@ * Transfer source to destination. */ swp_pager_init_freerange(&s_free, &n_free); - for (i = 0; i < dstobject->size; ++i) { - srcaddr = swp_pager_meta_ctl(srcobject, i + offset, SWM_POP); - if (srcaddr == SWAPBLK_NONE) - continue; + + /* + * Search srcobject pindex of corresponding dstobject between 0 and + * dstobject->size to transfer. + */ + for (i = 0; (i = swp_pager_meta_find_least(srcobject, i + offset, + &srcaddr) - offset) < dstobject->size; ++i) { dstaddr = swp_pager_meta_ctl(dstobject, i, 0); if (dstaddr != SWAPBLK_NONE) { /* @@ -2136,17 +2141,23 @@ /* * Returns the least page index which is greater than or equal to the * parameter pindex and for which there is a swap block allocated. + * If removal argument is passed, the swpblk is removed. * Returns object's size if the object's type is not swap or if there * are no allocated swap blocks for the object after the requested * pindex. */ vm_pindex_t -swap_pager_find_least(vm_object_t object, vm_pindex_t pindex) +swp_pager_meta_find_least(vm_object_t object, vm_pindex_t pindex, + daddr_t *removal) { struct swblk *sb; int i; - VM_OBJECT_ASSERT_LOCKED(object); + if (removal) + VM_OBJECT_ASSERT_WLOCKED(object); + else + VM_OBJECT_ASSERT_LOCKED(object); + if (object->type != OBJT_SWAP) return (object->size); @@ -2155,19 +2166,17 @@ if (sb == NULL) return (object->size); if (sb->p < pindex) { - for (i = pindex % SWAP_META_PAGES; i < SWAP_META_PAGES; i++) { + for (i = pindex % SWAP_META_PAGES; i < SWAP_META_PAGES; i++) if (sb->d[i] != SWAPBLK_NONE) - return (sb->p + i); - } + goto found; sb = SWAP_PCTRIE_LOOKUP_GE(&object->un_pager.swp.swp_blks, roundup(pindex, SWAP_META_PAGES)); if (sb == NULL) return (object->size); } - for (i = 0; i < SWAP_META_PAGES; i++) { + for (i = 0; i < SWAP_META_PAGES; i++) if (sb->d[i] != SWAPBLK_NONE) - return (sb->p + i); - } + goto found; /* * We get here if a swblk is present in the trie but it @@ -2175,6 +2184,31 @@ */ MPASS(0); return (object->size); +found: + if (removal) { + *removal = sb->d[i]; + sb->d[i] = SWAPBLK_NONE; + if (swp_pager_swblk_empty(sb, 0, SWAP_META_PAGES)) { + SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, + sb->p); + uma_zfree(swblk_zone, sb); + } + } + return (sb->p + i); +} + +/* + * Returns the least page index which is greater than or equal to the + * parameter pindex and for which there is a swap block allocated. + * Returns object's size if the object's type is not swap or if there + * are no allocated swap blocks for the object after the requested + * pindex. + */ +vm_pindex_t +swap_pager_find_least(vm_object_t object, vm_pindex_t pindex) +{ + + return swp_pager_meta_find_least(object, pindex, NULL); } /*