diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -142,6 +142,15 @@ daddr_t d[SWAP_META_PAGES]; }; +/* + * A page_range structure records the start address and length of a sequence of + * mapped page addresses. + */ +struct page_range { + daddr_t start; + daddr_t num; +}; + static MALLOC_DEFINE(M_VMPGDATA, "vm_pgdata", "swap pager private data"); static struct mtx sw_dev_mtx; static TAILQ_HEAD(, swdevt) swtailq = TAILQ_HEAD_INITIALIZER(swtailq); @@ -471,7 +480,7 @@ /* * Swap bitmap functions */ -static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages); +static void swp_pager_freeswapspace(const struct page_range *range); static daddr_t swp_pager_getswapspace(int *npages); /* @@ -486,23 +495,21 @@ static daddr_t swp_pager_meta_lookup(vm_object_t, vm_pindex_t); static void -swp_pager_init_freerange(daddr_t *start, daddr_t *num) +swp_pager_init_freerange(struct page_range *range) { - - *start = SWAPBLK_NONE; - *num = 0; + range->start = SWAPBLK_NONE; + range->num = 0; } static void -swp_pager_update_freerange(daddr_t *start, daddr_t *num, daddr_t addr) +swp_pager_update_freerange(struct page_range *range, daddr_t addr) { - - if (*start + *num == addr) { - (*num)++; + if (range->start + range->num == addr) { + range->num++; } else { - swp_pager_freeswapspace(*start, *num); - *start = addr; - *num = 1; + swp_pager_freeswapspace(range); + range->start = addr; + range->num = 1; } } @@ -906,10 +913,13 @@ * This routine may not sleep. */ static void -swp_pager_freeswapspace(daddr_t blk, daddr_t npages) +swp_pager_freeswapspace(const struct page_range *range) { + daddr_t blk, npages; struct swdevt *sp; + blk = range->start; + npages = range->num; if (npages == 0) return; mtx_lock(&sw_dev_mtx); @@ -1004,11 +1014,12 @@ int swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_pindex_t size) { - daddr_t addr, blk, n_free, s_free; + struct page_range range; + daddr_t addr, blk; vm_pindex_t i, j; int n; - swp_pager_init_freerange(&s_free, &n_free); + swp_pager_init_freerange(&range); VM_OBJECT_WLOCK(object); for (i = 0; i < size; i += n) { n = MIN(size - i, INT_MAX); @@ -1022,11 +1033,10 @@ addr = swp_pager_meta_build(object, start + i + j, blk + j); if (addr != SWAPBLK_NONE) - swp_pager_update_freerange(&s_free, &n_free, - addr); + swp_pager_update_freerange(&range, addr); } } - swp_pager_freeswapspace(s_free, n_free); + swp_pager_freeswapspace(&range); VM_OBJECT_WUNLOCK(object); return (0); } @@ -1195,6 +1205,7 @@ static void swap_pager_unswapped(vm_page_t m) { + struct page_range range; struct swblk *sb; vm_object_t obj; @@ -1233,9 +1244,11 @@ rounddown(m->pindex, SWAP_META_PAGES)); if (sb == NULL) return; - if (sb->d[m->pindex % SWAP_META_PAGES] == SWAPBLK_NONE) + range.start = sb->d[m->pindex % SWAP_META_PAGES]; + if (range.start == SWAPBLK_NONE) return; - swp_pager_freeswapspace(sb->d[m->pindex % SWAP_META_PAGES], 1); + range.num = 1; + swp_pager_freeswapspace(&range); sb->d[m->pindex % SWAP_META_PAGES] = SWAPBLK_NONE; swp_pager_free_empty_swblk(m->object, sb); } @@ -1480,8 +1493,9 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma, int count, int flags, int *rtvals) { + struct page_range range; struct buf *bp; - daddr_t addr, blk, n_free, s_free; + daddr_t addr, blk; vm_page_t mreq; int i, j, n; bool async; @@ -1492,7 +1506,7 @@ VM_OBJECT_WUNLOCK(object); async = curproc == pageproc && (flags & VM_PAGER_PUT_SYNC) == 0; - swp_pager_init_freerange(&s_free, &n_free); + swp_pager_init_freerange(&range); /* * Assign swap blocks and issue I/O. We reallocate swap on the fly. @@ -1530,8 +1544,7 @@ addr = swp_pager_meta_build(mreq->object, mreq->pindex, blk + j); if (addr != SWAPBLK_NONE) - swp_pager_update_freerange(&s_free, &n_free, - addr); + swp_pager_update_freerange(&range, addr); MPASS(mreq->dirty == VM_PAGE_BITS_ALL); mreq->oflags |= VPO_SWAPINPROG; } @@ -1603,7 +1616,7 @@ */ swp_pager_async_iodone(bp); } - swp_pager_freeswapspace(s_free, n_free); + swp_pager_freeswapspace(&range); VM_OBJECT_WLOCK(object); } @@ -2131,9 +2144,9 @@ swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject, vm_pindex_t pindex, vm_pindex_t count, vm_size_t *moved) { + struct page_range range; struct swblk *sb; vm_page_t m; - daddr_t n_free, s_free; vm_pindex_t offset, last; vm_size_t mc; int i, limit, start; @@ -2146,7 +2159,7 @@ if (count == 0 || pctrie_is_empty(&srcobject->un_pager.swp.swp_blks)) goto out; - swp_pager_init_freerange(&s_free, &n_free); + swp_pager_init_freerange(&range); offset = pindex; last = pindex + count; for (;;) { @@ -2163,8 +2176,7 @@ if (dstobject == NULL || !swp_pager_xfer_source(srcobject, dstobject, sb->p + i - offset, sb->d[i])) { - swp_pager_update_freerange(&s_free, &n_free, - sb->d[i]); + swp_pager_update_freerange(&range, sb->d[i]); } if (moved != NULL) { if (m != NULL && m->pindex != pindex + i - 1) @@ -2184,7 +2196,7 @@ uma_zfree(swblk_zone, sb); } } - swp_pager_freeswapspace(s_free, n_free); + swp_pager_freeswapspace(&range); out: if (moved != NULL) *moved = mc; @@ -2207,6 +2219,16 @@ swp_pager_meta_transfer(object, NULL, pindex, count, freed); } +static void +swp_pager_meta_free_block(struct swblk *sb, struct page_range *range) +{ + for (int i = 0; i < SWAP_META_PAGES; i++) { + if (sb->d[i] != SWAPBLK_NONE) + swp_pager_update_freerange(range, sb->d[i]); + } + uma_zfree(swblk_zone, sb); +} + /* * SWP_PAGER_META_FREE_ALL() - destroy all swap metadata associated with object * @@ -2217,28 +2239,19 @@ swp_pager_meta_free_all(vm_object_t object) { struct swblk *sb; - daddr_t n_free, s_free; + struct page_range range; vm_pindex_t pindex; - int i; VM_OBJECT_ASSERT_WLOCKED(object); - if (pctrie_is_empty(&object->un_pager.swp.swp_blks)) - return; - - swp_pager_init_freerange(&s_free, &n_free); + swp_pager_init_freerange(&range); 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) - continue; - swp_pager_update_freerange(&s_free, &n_free, sb->d[i]); - } SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, sb->p); - uma_zfree(swblk_zone, sb); + swp_pager_meta_free_block(sb, &range); } - swp_pager_freeswapspace(s_free, n_free); + swp_pager_freeswapspace(&range); } /*