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,29 +1892,37 @@ swp_pager_meta_free(vm_object_t object, vm_pindex_t pindex, vm_pindex_t count) { struct swblk *sb; - vm_pindex_t last; - int i; + daddr_t first_free, num_free; + vm_pindex_t plimit; + int i, limit; bool empty; VM_OBJECT_ASSERT_WLOCKED(object); if (object->type != OBJT_SWAP || count == 0) return; - last = pindex + count - 1; + first_free = SWAPBLK_NONE; + num_free = 0; + plimit = pindex + count; for (;;) { sb = SWAP_PCTRIE_LOOKUP_GE(&object->un_pager.swp.swp_blks, rounddown(pindex, SWAP_META_PAGES)); - if (sb == NULL || sb->p > last) + if (sb == NULL || sb->p >= plimit) break; - empty = true; - for (i = 0; i < SWAP_META_PAGES; i++) { + i = imax(0, pindex - sb->p); + limit = imin(SWAP_META_PAGES, plimit - sp->p); + empty = (i == 0 && limit == SWAP_META_PAGES); + for (; i < limit; 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 - empty = false; + 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 +1931,7 @@ uma_zfree(swblk_zone, sb); } } + swp_pager_freeswapspace(first_free, num_free); } /* @@ -1933,6 +1944,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 +1952,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); } /*