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 | 21 ++++++++++++++------- fs/buffer.c | 2 +- fs/inode.c | 7 +++++++ 3 files changed, 22 insertions(+), 8 deletions(-) Index: linux-2.6.21-rc7-mm1/fs/block_dev.c =================================================================== --- linux-2.6.21-rc7-mm1.orig/fs/block_dev.c 2007-04-24 13:19:10.000000000 -0700 +++ linux-2.6.21-rc7-mm1/fs/block_dev.c 2007-04-25 08:08:54.000000000 -0700 @@ -65,12 +65,11 @@ static void kill_bdev(struct block_devic return; invalidate_bh_lrus(); truncate_inode_pages(bdev->bd_inode->i_mapping, 0); -} +} 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; /* Size cannot be smaller than the size supported by the device */ @@ -79,10 +78,16 @@ 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_order(mapping, + bits < PAGE_SHIFT ? 0 : bits - PAGE_SHIFT); } return 0; } @@ -93,8 +98,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 larger than 512 + */ sb->s_blocksize = size; sb->s_blocksize_bits = blksize_bits(size); return sb->s_blocksize; Index: linux-2.6.21-rc7-mm1/fs/buffer.c =================================================================== --- linux-2.6.21-rc7-mm1.orig/fs/buffer.c 2007-04-25 07:57:35.000000000 -0700 +++ linux-2.6.21-rc7-mm1/fs/buffer.c 2007-04-25 08:06:50.000000000 -0700 @@ -1086,7 +1086,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))) { + size < 512)) { printk(KERN_ERR "getblk(): invalid block size %d requested\n", size); printk(KERN_ERR "hardsect size: %d\n", Index: linux-2.6.21-rc7-mm1/fs/inode.c =================================================================== --- linux-2.6.21-rc7-mm1.orig/fs/inode.c 2007-04-24 13:19:10.000000000 -0700 +++ linux-2.6.21-rc7-mm1/fs/inode.c 2007-04-25 08:08:01.000000000 -0700 @@ -155,6 +155,13 @@ static struct inode *alloc_inode(struct mapping->host = inode; mapping->flags = 0; mapping_set_gfp_mask(mapping, GFP_HIGH_MOVABLE); + + if (inode->i_blkbits > PAGE_SHIFT) + set_mapping_order(mapping, + inode->i_blkbits - PAGE_SHIFT); + else + set_mapping_order(mapping, 0); + mapping->assoc_mapping = NULL; mapping->backing_dev_info = &default_backing_dev_info;