Index: sys/vm/swap_pager.c =================================================================== --- sys/vm/swap_pager.c +++ sys/vm/swap_pager.c @@ -758,10 +758,12 @@ * This routine may not sleep. */ static void -swp_pager_freeswapspace(daddr_t blk, int npages) +swp_pager_freeswapspace(daddr_t blk, daddr_t npages) { struct swdevt *sp; + if (npages == 0) + return; mtx_lock(&sw_dev_mtx); TAILQ_FOREACH(sp, &swtailq, sw_list) { if (blk >= sp->sw_first && blk < sp->sw_end) { @@ -1890,6 +1892,7 @@ swp_pager_meta_free(vm_object_t object, vm_pindex_t pindex, vm_pindex_t count) { struct swblk *sb; + daddr_t first_free, num_free; vm_pindex_t last; int i; bool empty; @@ -1898,6 +1901,8 @@ if (object->type != OBJT_SWAP || count == 0) return; + first_free = SWAPBLK_NONE; + num_free = 0; last = pindex + count - 1; for (;;) { sb = SWAP_PCTRIE_LOOKUP_GE(&object->un_pager.swp.swp_blks, @@ -1908,11 +1913,18 @@ for (i = 0; i < SWAP_META_PAGES; i++) { if (sb->d[i] == SWAPBLK_NONE) continue; - if (pindex <= sb->p + i && sb->p + i <= last) { - swp_pager_freeswapspace(sb->d[i], 1); - sb->d[i] = SWAPBLK_NONE; - } else + if (pindex > sb->p + i || sb->p + i > last) { empty = false; + continue; + } + if (first_free + num_free == sb->d[i]) + num_free++; + else { + swp_pager_freeswapspace(first_free, num_free); + first_free = sb->d[i]; + num_free = 1; + } + sb->d[i] = SWAPBLK_NONE; } pindex = sb->p + SWAP_META_PAGES; if (empty) { @@ -1921,6 +1933,7 @@ uma_zfree(swblk_zone, sb); } } + swp_pager_freeswapspace(first_free, num_free); } /* @@ -1933,6 +1946,7 @@ swp_pager_meta_free_all(vm_object_t object) { struct swblk *sb; + daddr_t first_free, num_free; vm_pindex_t pindex; int i; @@ -1940,16 +1954,26 @@ if (object->type != OBJT_SWAP) return; + first_free = SWAPBLK_NONE; + num_free = 0; for (pindex = 0; (sb = SWAP_PCTRIE_LOOKUP_GE( &object->un_pager.swp.swp_blks, pindex)) != NULL;) { pindex = sb->p + SWAP_META_PAGES; for (i = 0; i < SWAP_META_PAGES; i++) { - if (sb->d[i] != SWAPBLK_NONE) - swp_pager_freeswapspace(sb->d[i], 1); + if (sb->d[i] == SWAPBLK_NONE) + continue; + if (first_free + num_free == sb->d[i]) + num_free++; + else { + swp_pager_freeswapspace(first_free, num_free); + first_free = sb->d[i]; + num_free = 1; + } } SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, sb->p); uma_zfree(swblk_zone, sb); } + swp_pager_freeswapspace(first_free, num_free); } /*