Index: head/sys/vm/swap_pager.c =================================================================== --- head/sys/vm/swap_pager.c +++ head/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 0x01 /* 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 dstaddr, first_free, num_free, srcaddr; VM_OBJECT_ASSERT_WLOCKED(srcobject); VM_OBJECT_ASSERT_WLOCKED(dstobject); @@ -935,53 +935,44 @@ } /* - * transfer source to destination. + * Transfer source to destination. */ + first_free = SWAPBLK_NONE; + num_free = 0; for (i = 0; i < dstobject->size; ++i) { - daddr_t dstaddr; - - /* - * Locate (without changing) the swapblk on the destination, - * unless it is invalid in which case free it silently, or - * if the destination is a resident page, in which case the - * source is thrown away. - */ + srcaddr = swp_pager_meta_ctl(srcobject, i + offset, SWM_POP); + if (srcaddr == SWAPBLK_NONE) + continue; dstaddr = swp_pager_meta_ctl(dstobject, i, 0); - 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); - } + 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 +1073,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); } /* @@ -1999,21 +1993,17 @@ } /* - * SWP_PAGER_METACTL() - misc control of swap and vm_page_t meta data. + * SWP_PAGER_METACTL() - misc control of swap 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 removing swapblk + * assignments in the swap meta data. It returns the swapblk being + * looked-up, popped, or SWAPBLK_NONE if the block was invalid. * * 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 but do not free it */ static daddr_t swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags) @@ -2021,7 +2011,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,17 +2030,13 @@ 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, rounddown(pindex, SWAP_META_PAGES)); uma_zfree(swblk_zone, sb); } - } - if ((flags & SWM_FREE) != 0) { - swp_pager_freeswapspace(r1, 1); - r1 = SWAPBLK_NONE; } return (r1); }