Commit e40df2d9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] buffer_boundary() for ext3

Implement buffer_boundary() for ext3.

buffer_boundary() is an I/O scheduling hint which the filesystem's
get_block() function passes up to the BIO assembly code.  It is
described in fs/mpage.c

The time to read 1,000 52 kbyte files goes from 8.6 seconds down to 2.9
seconds.  52 kbytes is the worst-case size.
parent 7e7382fd
...@@ -306,6 +306,8 @@ static inline int verify_chain(Indirect *from, Indirect *to) ...@@ -306,6 +306,8 @@ static inline int verify_chain(Indirect *from, Indirect *to)
* @inode: inode in question (we are only interested in its superblock) * @inode: inode in question (we are only interested in its superblock)
* @i_block: block number to be parsed * @i_block: block number to be parsed
* @offsets: array to store the offsets in * @offsets: array to store the offsets in
* @boundary: set this non-zero if the referred-to block is likely to be
* followed (on disk) by an indirect block.
* *
* To store the locations of file's data ext3 uses a data structure common * To store the locations of file's data ext3 uses a data structure common
* for UNIX filesystems - tree of pointers anchored in the inode, with * for UNIX filesystems - tree of pointers anchored in the inode, with
...@@ -330,7 +332,8 @@ static inline int verify_chain(Indirect *from, Indirect *to) ...@@ -330,7 +332,8 @@ static inline int verify_chain(Indirect *from, Indirect *to)
* get there at all. * get there at all.
*/ */
static int ext3_block_to_path(struct inode *inode, long i_block, int offsets[4]) static int ext3_block_to_path(struct inode *inode,
long i_block, int offsets[4], int *boundary)
{ {
int ptrs = EXT3_ADDR_PER_BLOCK(inode->i_sb); int ptrs = EXT3_ADDR_PER_BLOCK(inode->i_sb);
int ptrs_bits = EXT3_ADDR_PER_BLOCK_BITS(inode->i_sb); int ptrs_bits = EXT3_ADDR_PER_BLOCK_BITS(inode->i_sb);
...@@ -338,26 +341,33 @@ static int ext3_block_to_path(struct inode *inode, long i_block, int offsets[4]) ...@@ -338,26 +341,33 @@ static int ext3_block_to_path(struct inode *inode, long i_block, int offsets[4])
indirect_blocks = ptrs, indirect_blocks = ptrs,
double_blocks = (1 << (ptrs_bits * 2)); double_blocks = (1 << (ptrs_bits * 2));
int n = 0; int n = 0;
int final = 0;
if (i_block < 0) { if (i_block < 0) {
ext3_warning (inode->i_sb, "ext3_block_to_path", "block < 0"); ext3_warning (inode->i_sb, "ext3_block_to_path", "block < 0");
} else if (i_block < direct_blocks) { } else if (i_block < direct_blocks) {
offsets[n++] = i_block; offsets[n++] = i_block;
final = direct_blocks;
} else if ( (i_block -= direct_blocks) < indirect_blocks) { } else if ( (i_block -= direct_blocks) < indirect_blocks) {
offsets[n++] = EXT3_IND_BLOCK; offsets[n++] = EXT3_IND_BLOCK;
offsets[n++] = i_block; offsets[n++] = i_block;
final = ptrs;
} else if ((i_block -= indirect_blocks) < double_blocks) { } else if ((i_block -= indirect_blocks) < double_blocks) {
offsets[n++] = EXT3_DIND_BLOCK; offsets[n++] = EXT3_DIND_BLOCK;
offsets[n++] = i_block >> ptrs_bits; offsets[n++] = i_block >> ptrs_bits;
offsets[n++] = i_block & (ptrs - 1); offsets[n++] = i_block & (ptrs - 1);
final = ptrs;
} else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
offsets[n++] = EXT3_TIND_BLOCK; offsets[n++] = EXT3_TIND_BLOCK;
offsets[n++] = i_block >> (ptrs_bits * 2); offsets[n++] = i_block >> (ptrs_bits * 2);
offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1); offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
offsets[n++] = i_block & (ptrs - 1); offsets[n++] = i_block & (ptrs - 1);
final = ptrs;
} else { } else {
ext3_warning (inode->i_sb, "ext3_block_to_path", "block > big"); ext3_warning (inode->i_sb, "ext3_block_to_path", "block > big");
} }
if (boundary)
*boundary = (i_block & (ptrs - 1)) == (final - 1);
return n; return n;
} }
...@@ -734,7 +744,8 @@ static int ext3_get_block_handle(handle_t *handle, struct inode *inode, ...@@ -734,7 +744,8 @@ static int ext3_get_block_handle(handle_t *handle, struct inode *inode,
Indirect *partial; Indirect *partial;
unsigned long goal; unsigned long goal;
int left; int left;
int depth = ext3_block_to_path(inode, iblock, offsets); int boundary = 0;
int depth = ext3_block_to_path(inode, iblock, offsets, &boundary);
struct ext3_inode_info *ei = EXT3_I(inode); struct ext3_inode_info *ei = EXT3_I(inode);
loff_t new_size; loff_t new_size;
...@@ -752,6 +763,8 @@ static int ext3_get_block_handle(handle_t *handle, struct inode *inode, ...@@ -752,6 +763,8 @@ static int ext3_get_block_handle(handle_t *handle, struct inode *inode,
clear_buffer_new(bh_result); clear_buffer_new(bh_result);
got_it: got_it:
map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
if (boundary)
set_buffer_boundary(bh_result);
/* Clean up and exit */ /* Clean up and exit */
partial = chain+depth-1; /* the whole chain */ partial = chain+depth-1; /* the whole chain */
goto cleanup; goto cleanup;
...@@ -1875,7 +1888,7 @@ void ext3_truncate(struct inode * inode) ...@@ -1875,7 +1888,7 @@ void ext3_truncate(struct inode * inode)
ext3_block_truncate_page(handle, inode->i_mapping, inode->i_size); ext3_block_truncate_page(handle, inode->i_mapping, inode->i_size);
n = ext3_block_to_path(inode, last_block, offsets); n = ext3_block_to_path(inode, last_block, offsets, NULL);
if (n == 0) if (n == 0)
goto out_stop; /* error */ goto out_stop; /* error */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment