Messages in this thread Patch in this message |  | | Subject | [patch] 2.4.10: hardcoded BUFFERED_BLOCKSIZE breaks S/390 with 4k hardsect_size | From | "Holger Smolinski" <> | Date | Wed, 26 Sep 2001 10:16:40 +0200 |
| |
Folks, with S/390, which usually has 4k hardsect size, and a device driver which is unable to gather multiple bhs into one block, the 2.4.10 approach to BUFFERED_BLOCKSIZE breaks blkdev_readpage, which is dividing the requested page into bhs of BUFFERED_BLOCKSIZE each.
My understanding is, that the intention of BUFFERED_BLOCKSIZE is, to divide any page in the page cache into bhs of an appropriate size to be handled by the upper layer (e.g. FS), right. As a consquence it should be dependent on the blocksize of the upper layer as represented by the inode->i_sb->s_blocksize.
Please review the attached patch for incompatibilities to other architectures or contradictionary effects to the intended purpose of introducing BUFFERED_BLOCKSIZE and consider to apply.
happy hacking, Holger
diff -ur linux-2.3/fs/block_dev.c linux-2.3.HSM/fs/block_dev.c --- linux-2.3/fs/block_dev.c Tue Sep 25 13:49:56 2001 +++ linux-2.3.HSM/fs/block_dev.c Tue Sep 25 18:24:43 2001 @@ -27,9 +27,9 @@ int err;
err = -EIO; - if (iblock >= buffered_blk_size(inode->i_rdev) >> (BUFFERED_BLOCKSIZE_BITS - BLOCK_SIZE_BITS)) + if (iblock >= buffered_blk_size(inode->i_rdev,BUFFERED_BLOCKSIZE(inode)) * (BUFFERED_BLOCKSIZE(inode) >> BLOCK_SIZE_BITS)) goto out; - + bh_result->b_blocknr = iblock; bh_result->b_state |= 1UL << BH_Mapped; err = 0; @@ -42,11 +42,12 @@ { int i, nr_blocks, retval, dev = inode->i_rdev; unsigned long * blocks = iobuf->blocks; + unsigned long buffered_blocksize = BUFFERED_BLOCKSIZE(inode);
- if (blocksize != BUFFERED_BLOCKSIZE) + if (blocksize != buffered_blocksize) BUG();
- nr_blocks = iobuf->length >> BUFFERED_BLOCKSIZE_BITS; + nr_blocks = iobuf->length / buffered_blocksize; /* build the blocklist */ for (i = 0; i < nr_blocks; i++, blocknr++) { struct buffer_head bh; @@ -75,10 +76,10 @@ BUG();
if (!page->buffers) - create_empty_buffers(page, inode->i_rdev, BUFFERED_BLOCKSIZE); + create_empty_buffers(page, inode->i_rdev, BUFFERED_BLOCKSIZE(inode)); head = page->buffers;
- block = page->index << (PAGE_CACHE_SHIFT - BUFFERED_BLOCKSIZE_BITS); + block = (page->index << (PAGE_CACHE_SHIFT)) / BUFFERED_BLOCKSIZE(inode);
bh = head; i = 0; @@ -132,19 +133,19 @@ struct inode *inode = page->mapping->host; kdev_t dev = inode->i_rdev; unsigned long iblock, lblock; - struct buffer_head *bh, *head, *arr[1 << (PAGE_CACHE_SHIFT - BUFFERED_BLOCKSIZE_BITS)]; + struct buffer_head *bh, *head, *arr[(1 << PAGE_CACHE_SHIFT ) / BUFFERED_BLOCKSIZE(inode)]; unsigned int blocks; int nr, i;
if (!PageLocked(page)) PAGE_BUG(page); if (!page->buffers) - create_empty_buffers(page, dev, BUFFERED_BLOCKSIZE); + create_empty_buffers(page, dev, BUFFERED_BLOCKSIZE(inode)); head = page->buffers;
- blocks = PAGE_CACHE_SIZE >> BUFFERED_BLOCKSIZE_BITS; - iblock = page->index << (PAGE_CACHE_SHIFT - BUFFERED_BLOCKSIZE_BITS); - lblock = buffered_blk_size(dev) >> (BUFFERED_BLOCKSIZE_BITS - BLOCK_SIZE_BITS); + blocks = PAGE_CACHE_SIZE / BUFFERED_BLOCKSIZE(inode); + iblock = (page->index << PAGE_CACHE_SHIFT) / BUFFERED_BLOCKSIZE(inode); + lblock = buffered_blk_size(dev,BUFFERED_BLOCKSIZE(inode)) / (BUFFERED_BLOCKSIZE(inode) >> BLOCK_SIZE_BITS); bh = head; nr = 0; i = 0; @@ -159,7 +160,7 @@ continue; } if (!buffer_mapped(bh)) { - memset(kmap(page) + i * BUFFERED_BLOCKSIZE, 0, BUFFERED_BLOCKSIZE); + memset(kmap(page) + i * BUFFERED_BLOCKSIZE(inode), 0, BUFFERED_BLOCKSIZE(inode)); flush_dcache_page(page); kunmap(page); set_bit(BH_Uptodate, &bh->b_state); @@ -209,16 +210,16 @@ kmap(page);
if (!page->buffers) - create_empty_buffers(page, dev, BUFFERED_BLOCKSIZE); + create_empty_buffers(page, dev, BUFFERED_BLOCKSIZE(inode)); head = page->buffers;
- block = page->index << (PAGE_CACHE_SHIFT - BUFFERED_BLOCKSIZE_BITS); + block = (page->index << PAGE_CACHE_SHIFT) / BUFFERED_BLOCKSIZE(inode);
for(bh = head, block_start = 0; bh != head || !block_start; block++, block_start=block_end, bh = bh->b_this_page) { if (!bh) BUG(); - block_end = block_start + BUFFERED_BLOCKSIZE; + block_end = block_start + BUFFERED_BLOCKSIZE(inode); if (block_end <= from) continue; if (block_start >= to) @@ -273,7 +274,7 @@ for(bh = head = page->buffers, block_start = 0; bh != head || !block_start; block_start=block_end, bh = bh->b_this_page) { - block_end = block_start + BUFFERED_BLOCKSIZE; + block_end = block_start + BUFFERED_BLOCKSIZE(inode); if (block_end <= from || block_start >= to) { if (!buffer_uptodate(bh)) partial = 1; @@ -378,7 +379,7 @@ root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; root->i_uid = root->i_gid = 0; root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME; - sb->s_blocksize = 1024; - sb->s_blocksize_bits = 10; + sb->s_blocksize = PAGE_SIZE; + sb->s_blocksize_bits = PAGE_SHIFT; sb->s_magic = 0x62646576; sb->s_op = &sops; diff -ur linux-2.3/include/linux/blkdev.h linux-2.3.HSM/include/linux/blkdev.h --- linux-2.3/include/linux/blkdev.h Tue Sep 25 13:49:56 2001 +++ linux-2.3.HSM/include/linux/blkdev.h Tue Sep 25 18:08:24 2001 @@ -203,14 +203,14 @@ #define blk_finished_io(nsects) do { } while (0) #define blk_started_io(nsects) do { } while (0)
-static inline int buffered_blk_size(kdev_t dev) +static inline int buffered_blk_size(kdev_t dev, int buffered_size) { int ret = INT_MAX; int major = MAJOR(dev); - + int rval = (buffered_size >> BLOCK_SIZE_BITS) - 1; if (blk_size[major]) - ret = blk_size[major][MINOR(dev)] + ((BUFFERED_BLOCKSIZE-1) >> BLOCK_SIZE_BITS); - + ret = (blk_size[major][MINOR(dev)] + rval) & ~rval; + return ret; }
diff -ur linux-2.3/include/linux/fs.h linux-2.3.HSM/include/linux/fs.h --- linux-2.3/include/linux/fs.h Tue Sep 25 13:49:56 2001 +++ linux-2.3.HSM/include/linux/fs.h Tue Sep 25 18:00:38 2001 @@ -47,8 +47,7 @@ #define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
/* buffer header fixed size for the blkdev I/O through pagecache */ -#define BUFFERED_BLOCKSIZE_BITS 10 -#define BUFFERED_BLOCKSIZE (1 << BUFFERED_BLOCKSIZE_BITS) +#define BUFFERED_BLOCKSIZE(inode) (inode->i_sb->s_blocksize)
/* And dynamically-tunable limits and defaults: */ struct files_stat_struct { diff -ur linux-2.3/mm/filemap.c linux-2.3.HSM/mm/filemap.c --- linux-2.3/mm/filemap.c Tue Sep 25 13:49:56 2001 +++ linux-2.3.HSM/mm/filemap.c Tue Sep 25 18:27:30 2001 @@ -963,7 +963,7 @@ if (!S_ISBLK(inode->i_mode)) end_index = inode->i_size >> PAGE_CACHE_SHIFT; else - end_index = buffered_blk_size(inode->i_rdev) >> (PAGE_CACHE_SHIFT - BLOCK_SIZE_BITS); + end_index = buffered_blk_size(inode->i_rdev,BUFFERED_BLOCKSIZE(inode)) >> (PAGE_CACHE_SHIFT - BLOCK_SIZE_BITS);
return end_index; } @@ -975,7 +975,7 @@ if (!S_ISBLK(inode->i_mode)) rsize = inode->i_size; else - rsize = (loff_t) buffered_blk_size(inode->i_rdev) << BLOCK_SIZE_BITS; + rsize = (loff_t) buffered_blk_size(inode->i_rdev,BUFFERED_BLOCKSIZE(inode)) << BLOCK_SIZE_BITS;
return rsize; } @@ -1339,11 +1339,11 @@
if (!S_ISBLK(inode->i_mode)) { blocksize = inode->i_sb->s_blocksize; - blocksize_bits = inode->i_sb->s_blocksize_bits; } else { - blocksize = BUFFERED_BLOCKSIZE; - blocksize_bits = BUFFERED_BLOCKSIZE_BITS; + kdev_t kdev = inode->i_rdev; + blocksize = blksize_size[MAJOR(kdev)][MINOR(kdev)]; } + for (blocksize_bits = BLOCK_SIZE_BITS; blocksize >> (blocksize_bits+1); blocksize_bits ++); blocksize_mask = blocksize - 1; chunk_size = KIO_MAX_ATOMIC_IO << 10;
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|  |