set_blocksize: Allow to set a larger block size than PAGE_SIZE set_blocksize is changed to allow to specify a blocksize larger than a page. If that occurs then we switch the device to use compound pages. Signed-off-by: Christoph Lameter --- fs/block_dev.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- fs/buffer.c | 2 +- fs/inode.c | 1 + 3 files changed, 45 insertions(+), 8 deletions(-) Index: vps/fs/block_dev.c =================================================================== --- vps.orig/fs/block_dev.c 2007-06-11 15:56:36.000000000 -0700 +++ vps/fs/block_dev.c 2007-06-12 20:31:53.000000000 -0700 @@ -65,12 +65,41 @@ static void kill_bdev(struct block_devic return; invalidate_bh_lrus(); truncate_inode_pages(bdev->bd_inode->i_mapping, 0); -} +} + +#ifdef CONFIG_LARGE_BLOCKSIZE + +static int page_cache_min_order = 0; +static int page_cache_max_order = 4; /* 64k */ + +static int __init setup_page_cache_min_order(char *str) +{ + get_option (&str, &page_cache_min_order); + return 1; +} + +__setup("page_cache_min_order=", setup_page_cache_min_order); + +static int __init setup_page_cache_max_order(char *str) +{ + get_option (&str, &page_cache_max_order); + return 1; +} + +__setup("page_cache_max_order=", setup_page_cache_max_order); +#else + +#define page_cache_min_order 0 +#define page_cache_max_order 0 + +#endif int set_blocksize(struct block_device *bdev, int size) { - /* Size must be a power of two, and between 512 and PAGE_SIZE */ - if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size)) + if (size < 512 || !is_power_of_2(size)) + return -EINVAL; + + if (!page_cache_valid_blocksize(size)) return -EINVAL; /* Size cannot be smaller than the size supported by the device */ @@ -79,10 +108,15 @@ int set_blocksize(struct block_device *b /* Don't change the size if it is same as current */ if (bdev->bd_block_size != size) { + int bits = blksize_bits(size); + struct address_space *mapping = + bdev->bd_inode->i_mapping; + sync_blockdev(bdev); - bdev->bd_block_size = size; - bdev->bd_inode->i_blkbits = blksize_bits(size); kill_bdev(bdev); + bdev->bd_block_size = size; + bdev->bd_inode->i_blkbits = bits; + set_mapping_bits(mapping, bits); } return 0; } @@ -93,8 +127,10 @@ int sb_set_blocksize(struct super_block { if (set_blocksize(sb->s_bdev, size)) return 0; - /* If we get here, we know size is power of two - * and it's value is between 512 and PAGE_SIZE */ + /* + * If we get here, we know size is power of two + * and it's value is valid for the page cache + */ sb->s_blocksize = size; sb->s_blocksize_bits = blksize_bits(size); return sb->s_blocksize; Index: vps/fs/buffer.c =================================================================== --- vps.orig/fs/buffer.c 2007-06-12 18:59:28.000000000 -0700 +++ vps/fs/buffer.c 2007-06-12 20:26:23.000000000 -0700 @@ -1097,7 +1097,7 @@ __getblk_slow(struct block_device *bdev, { /* Size must be multiple of hard sectorsize */ if (unlikely(size & (bdev_hardsect_size(bdev)-1) || - (size < 512 || size > PAGE_SIZE))) { + !page_cache_valid_blocksize(size))) { printk(KERN_ERR "getblk(): invalid block size %d requested\n", size); printk(KERN_ERR "hardsect size: %d\n", Index: vps/fs/inode.c =================================================================== --- vps.orig/fs/inode.c 2007-06-11 15:56:36.000000000 -0700 +++ vps/fs/inode.c 2007-06-12 20:26:53.000000000 -0700 @@ -146,6 +146,7 @@ static struct inode *alloc_inode(struct mapping->host = inode; mapping->flags = 0; mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE); + set_mapping_bits(mapping, inode->i_blkbits); mapping->assoc_mapping = NULL; mapping->backing_dev_info = &default_backing_dev_info;