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 | 53 ++++++++++++++++++++++++++++++++++++++++++++++------- fs/buffer.c | 12 +++++------- fs/inode.c | 1 + 3 files changed, 52 insertions(+), 14 deletions(-) Index: linux-2.6.21-rc7-mm2/fs/block_dev.c =================================================================== --- linux-2.6.21-rc7-mm2.orig/fs/block_dev.c 2007-04-27 22:51:27.000000000 -0700 +++ linux-2.6.21-rc7-mm2/fs/block_dev.c 2007-05-01 15:59:28.000000000 -0700 @@ -65,12 +65,44 @@ static void kill_bdev(struct block_devic return; invalidate_bh_lrus(); truncate_inode_pages(bdev->bd_inode->i_mapping, 0); -} +} + +#if 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 + +#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 +111,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 +130,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: linux-2.6.21-rc7-mm2/fs/buffer.c =================================================================== --- linux-2.6.21-rc7-mm2.orig/fs/buffer.c 2007-05-01 15:46:40.000000000 -0700 +++ linux-2.6.21-rc7-mm2/fs/buffer.c 2007-05-01 15:48:24.000000000 -0700 @@ -1085,7 +1085,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", @@ -2100,20 +2100,18 @@ int cont_prepare_write(struct page *page page_cache_release(new_page); continue; } - zerofrom = page_cache_offset(*bytes); + zerofrom = page_cache_offset(mapping, *bytes); if (zerofrom & (blocksize-1)) { *bytes |= (blocksize-1); (*bytes)++; } status = __block_prepare_write(inode, new_page, zerofrom, - page_cache_size(mapping), get_block); + page_size, get_block); if (status) goto out_unmap; zero_user_page(page, zerofrom, - page_cache_size(mapping) - zerofrom, - KM_USER0); - generic_commit_write(NULL, new_page, zerofrom, - page_cache_size(mapping)); + page_size - zerofrom, KM_USER0); + generic_commit_write(NULL, new_page, zerofrom, page_size); unlock_page(new_page); page_cache_release(new_page); } Index: linux-2.6.21-rc7-mm2/fs/inode.c =================================================================== --- linux-2.6.21-rc7-mm2.orig/fs/inode.c 2007-04-27 22:51:27.000000000 -0700 +++ linux-2.6.21-rc7-mm2/fs/inode.c 2007-05-01 16:14:43.000000000 -0700 @@ -155,6 +155,7 @@ static struct inode *alloc_inode(struct mapping->host = inode; mapping->flags = 0; mapping_set_gfp_mask(mapping, GFP_HIGH_MOVABLE); + set_mapping_bits(mapping, inode->i_blkbits); mapping->assoc_mapping = NULL; mapping->backing_dev_info = &default_backing_dev_info;