LBS: Changes to swap Initialize new fields of swapper space. Adjust setup_swap_extents so as not to assume that PAGE_SIZE is a multiple of its swapfile blocksize: blocksize might now be a multiple of PAGE_SIZE. Not vital to support this, but LTP in ext2 -b 32768 /tmp was failing before. Signed-off-by: Hugh Dickins --- mm/swap_state.c | 4 ++++ mm/swapfile.c | 27 ++++++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) Index: linux-2.6/mm/swap_state.c =================================================================== --- linux-2.6.orig/mm/swap_state.c 2007-08-20 14:28:38.000000000 -0700 +++ linux-2.6/mm/swap_state.c 2007-09-25 01:26:04.000000000 -0700 @@ -42,6 +42,10 @@ struct address_space swapper_space = { .a_ops = &swap_aops, .i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear), .backing_dev_info = &swap_backing_dev_info, +#ifdef CONFIG_LARGE_BLOCKSIZE + .shift = PAGE_SHIFT, + .offset_mask = PAGE_SIZE - 1, +#endif }; #define INC_CACHE_INFO(x) do { swap_cache_info.x++; } while (0) Index: linux-2.6/mm/swapfile.c =================================================================== --- linux-2.6.orig/mm/swapfile.c 2007-09-16 19:30:30.000000000 -0700 +++ linux-2.6/mm/swapfile.c 2007-09-25 01:26:14.000000000 -0700 @@ -1057,6 +1057,7 @@ static int setup_swap_extents(struct swa { struct inode *inode; unsigned blocks_per_page; + unsigned pages_per_block; unsigned long page_no; unsigned blkbits; sector_t probe_block; @@ -1074,7 +1075,13 @@ static int setup_swap_extents(struct swa } blkbits = inode->i_blkbits; - blocks_per_page = PAGE_SIZE >> blkbits; + if (blkbits <= PAGE_SHIFT) { + blocks_per_page = 1 << (PAGE_SHIFT - blkbits); + pages_per_block = 1; + } else { + blocks_per_page = 1; + pages_per_block = 1 << (blkbits - PAGE_SHIFT); + } /* * Map all the blocks into the extent list. This code doesn't try @@ -1114,28 +1121,34 @@ static int setup_swap_extents(struct swa } } - first_block >>= (PAGE_SHIFT - blkbits); + if (blkbits <= PAGE_SHIFT) + first_block >>= (PAGE_SHIFT - blkbits); + else { + first_block <<= (blkbits - PAGE_SHIFT); + if (page_no + pages_per_block > sis->max) + pages_per_block = sis->max - page_no; + } if (page_no) { /* exclude the header page */ if (first_block < lowest_block) lowest_block = first_block; - if (first_block > highest_block) - highest_block = first_block; + if (first_block >= highest_block) + highest_block = first_block + pages_per_block; } /* * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks */ - ret = add_swap_extent(sis, page_no, 1, first_block); + ret = add_swap_extent(sis,page_no,pages_per_block,first_block); if (ret < 0) goto out; nr_extents += ret; - page_no++; + page_no += pages_per_block; probe_block += blocks_per_page; reprobe: continue; } ret = nr_extents; - *span = 1 + highest_block - lowest_block; + *span = highest_block - lowest_block; if (page_no == 0) page_no = 1; /* force Empty message */ sis->max = page_no;