diff options
-rw-r--r-- | sys/vm/swap_pager.c | 2 | ||||
-rw-r--r-- | sys/vm/swap_pager.h | 9 | ||||
-rw-r--r-- | sys/vm/vm_swap.c | 20 |
3 files changed, 21 insertions, 10 deletions
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 31b632a..b1f4802 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -172,7 +172,7 @@ static void waitchainbuf(struct bio *bp, int count, int done); /* * dmmax is in page-sized chunks with the new swap system. It was - * dev-bsized chunks in the old. + * dev-bsized chunks in the old. dmmax is always a power of 2. * * swap_*() routines are externally accessible. swp_*() routines are * internal. diff --git a/sys/vm/swap_pager.h b/sys/vm/swap_pager.h index b239952..ea57132 100644 --- a/sys/vm/swap_pager.h +++ b/sys/vm/swap_pager.h @@ -48,12 +48,9 @@ #define _SWAP_PAGER_ 1 /* - * SWB_NPAGES can be set to any value from 1 to 16 pages per allocation, - * however, due to the allocation spilling into non-swap pager backed memory, - * suggest keeping SWB_NPAGES small (1-4). If high performance is mandatory - * perhaps up to 8 pages might be in order???? - * Above problem has been fixed, now we support 16 pages per block. Unused - * space is recovered by the swap pager now... + * SWB_NPAGES must be a power of 2. It may be set to 1, 2, 4, 8, or 16 + * pages per allocation. We recommend you stick with the default of 8. + * The 16-page limit is due to the radix code (kern/subr_blist.c). */ #if !defined(SWB_NPAGES) #define SWB_NPAGES 8 diff --git a/sys/vm/vm_swap.c b/sys/vm/vm_swap.c index cf5cf4b..8691c22 100644 --- a/sys/vm/vm_swap.c +++ b/sys/vm/vm_swap.c @@ -237,6 +237,7 @@ swaponvp(p, vp, dev, nblks) register long blk; swblk_t dvbase; int error; + u_long aligned_nblks; if (!swapdev_vp) { error = getnewvnode(VT_NON, NULL, swapdev_vnodeop_p, @@ -271,6 +272,17 @@ swaponvp(p, vp, dev, nblks) (void) VOP_CLOSE(vp, FREAD | FWRITE, p->p_ucred, p); return (ENXIO); } + + /* + * If we go beyond this, we get overflows in the radix + * tree bitmap code. + */ + if (nblks > 0x40000000 / BLIST_META_RADIX / nswdev) { + printf("exceeded maximum of %d blocks per swap unit\n", + 0x40000000 / BLIST_META_RADIX / nswdev); + (void) VOP_CLOSE(vp, FREAD | FWRITE, p->p_ucred, p); + return (ENXIO); + } /* * nblks is in DEV_BSIZE'd chunks, convert to PAGE_SIZE'd chunks. * First chop nblks off to page-align it, then convert. @@ -288,11 +300,13 @@ swaponvp(p, vp, dev, nblks) /* * nblks, nswap, and dmmax are PAGE_SIZE'd parameters now, not - * DEV_BSIZE'd. + * DEV_BSIZE'd. aligned_nblks is used to calculate the + * size of the swap bitmap, taking into account the stripe size. */ + aligned_nblks = (nblks + (dmmax - 1)) & ~(u_long)(dmmax - 1); - if (nblks * nswdev > nswap) - nswap = (nblks+1) * nswdev; + if (aligned_nblks * nswdev > nswap) + nswap = aligned_nblks * nswdev; if (swapblist == NULL) swapblist = blist_create(nswap); |