Index: sys/vm/swap_pager.c =================================================================== --- sys/vm/swap_pager.c +++ sys/vm/swap_pager.c @@ -311,8 +311,7 @@ racct_sub_cred(cred, RACCT_SWAP, decr); } -#define SWM_FREE 0x02 /* free, period */ -#define SWM_POP 0x04 /* pop out */ +#define SWM_POP 0x02 /* pop out */ static int swap_pager_full = 2; /* swap space exhaustion (task killing) */ static int swap_pager_almost_full = 1; /* swap space exhaustion (w/hysteresis)*/ @@ -911,6 +910,7 @@ vm_pindex_t offset, int destroysource) { vm_pindex_t i; + daddr_t first_free, num_free; VM_OBJECT_ASSERT_WLOCKED(srcobject); VM_OBJECT_ASSERT_WLOCKED(dstobject); @@ -937,8 +937,10 @@ /* * transfer source to destination. */ + first_free = SWAPBLK_NONE; + num_free = 0; for (i = 0; i < dstobject->size; ++i) { - daddr_t dstaddr; + daddr_t dstaddr, srcaddr; /* * Locate (without changing) the swapblk on the destination, @@ -947,41 +949,40 @@ * source is thrown away. */ dstaddr = swp_pager_meta_ctl(dstobject, i, 0); + srcaddr = swp_pager_meta_ctl(srcobject, i + offset, SWM_POP); + if (srcaddr == SWAPBLK_NONE) + continue; if (dstaddr == SWAPBLK_NONE) { /* * Destination has no swapblk and is not resident, * copy source. + * + * swp_pager_meta_build() can sleep. */ - daddr_t srcaddr; - - srcaddr = swp_pager_meta_ctl( - srcobject, - i + offset, - SWM_POP - ); - - if (srcaddr != SWAPBLK_NONE) { - /* - * swp_pager_meta_build() can sleep. - */ - vm_object_pip_add(srcobject, 1); - VM_OBJECT_WUNLOCK(srcobject); - vm_object_pip_add(dstobject, 1); - swp_pager_meta_build(dstobject, i, srcaddr); - vm_object_pip_wakeup(dstobject); - VM_OBJECT_WLOCK(srcobject); - vm_object_pip_wakeup(srcobject); - } - } else { + vm_object_pip_add(srcobject, 1); + VM_OBJECT_WUNLOCK(srcobject); + vm_object_pip_add(dstobject, 1); + swp_pager_meta_build(dstobject, i, srcaddr); + vm_object_pip_wakeup(dstobject); + VM_OBJECT_WLOCK(srcobject); + vm_object_pip_wakeup(srcobject); + } + else { /* * Destination has valid swapblk or it is represented * by a resident page. We destroy the sourceblock. */ - - swp_pager_meta_ctl(srcobject, i + offset, SWM_FREE); + if (first_free + num_free == srcaddr) + num_free++; + else { + swp_pager_freeswapspace(first_free, num_free); + first_free = srcaddr; + num_free = 1; + } } } + swp_pager_freeswapspace(first_free, num_free); /* * Free left over swap blocks in source. @@ -1082,8 +1083,11 @@ static void swap_pager_unswapped(vm_page_t m) { + daddr_t srcaddr; - swp_pager_meta_ctl(m->object, m->pindex, SWM_FREE); + srcaddr = swp_pager_meta_ctl(m->object, m->pindex, SWM_POP); + if (srcaddr != SWAPBLK_NONE) + swp_pager_freeswapspace(srcaddr, 1); } /* @@ -2001,19 +2005,17 @@ /* * SWP_PAGER_METACTL() - misc control of swap and vm_page_t meta data. * - * This routine is capable of looking up, popping, or freeing - * swapblk assignments in the swap meta data or in the vm_page_t. - * The routine typically returns the swapblk being looked-up, or popped, - * or SWAPBLK_NONE if the block was freed, or SWAPBLK_NONE if the block - * was invalid. This routine will automatically free any invalid - * meta-data swapblks. + * This routine is capable of looking up, or popping swapblk + * assignments in the swap meta data or in the vm_page_t. The + * routine typically returns the swapblk being looked-up, or popped, + * or SWAPBLK_NONE if the block was invalid. This routine will + * automatically free any invalid meta-data swapblks. * * When acting on a busy resident page and paging is in progress, we * have to wait until paging is complete but otherwise can act on the * busy page. * - * SWM_FREE remove and free swap block from metadata - * SWM_POP remove from meta data but do not free.. pop it out + * SWM_POP remove from meta data.. pop it out */ static daddr_t swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags) @@ -2021,7 +2023,7 @@ struct swblk *sb; daddr_t r1; - if ((flags & (SWM_FREE | SWM_POP)) != 0) + if ((flags & SWM_POP) != 0) VM_OBJECT_ASSERT_WLOCKED(object); else VM_OBJECT_ASSERT_LOCKED(object); @@ -2040,7 +2042,7 @@ r1 = sb->d[pindex % SWAP_META_PAGES]; if (r1 == SWAPBLK_NONE) return (SWAPBLK_NONE); - if ((flags & (SWM_FREE | SWM_POP)) != 0) { + if ((flags & SWM_POP) != 0) { sb->d[pindex % SWAP_META_PAGES] = SWAPBLK_NONE; if (swp_pager_swblk_empty(sb, 0, SWAP_META_PAGES)) { SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, @@ -2048,10 +2050,6 @@ uma_zfree(swblk_zone, sb); } } - if ((flags & SWM_FREE) != 0) { - swp_pager_freeswapspace(r1, 1); - r1 = SWAPBLK_NONE; - } return (r1); }