Commit a9f525e6 authored by Andrew Morton's avatar Andrew Morton Committed by Arnaldo Carvalho de Melo

[PATCH] ext2: preread inode backing blocks

When ext2 creates a new inode, perform an asynchronous preread against
its backing block.

Without this patch, many-file writeout gets stalled by having to read
many individual inode table blocks in the middle of writeback.

It's worth about a 20% gain in writeback bandwidth for the many-file
writeback case.

ext3 already reads the inode's backing block in
ext3_new_inode->ext3_mark_inode_dirty, so no change is needed there.

A backport to 2.4 would make sense.
parent acb5f6f9
...@@ -217,6 +217,44 @@ void ext2_free_inode (struct inode * inode) ...@@ -217,6 +217,44 @@ void ext2_free_inode (struct inode * inode)
unlock_super (sb); unlock_super (sb);
} }
/*
* We perform asynchronous prereading of the new inode's inode block when
* we create the inode, in the expectation that the inode will be written
* back soon. There are two reasons:
*
* - When creating a large number of files, the async prereads will be
* nicely merged into large reads
* - When writing out a large number of inodes, we don't need to keep on
* stalling the writes while we read the inode block.
*
* FIXME: ext2_get_group_desc() needs to be simplified.
*/
static void ext2_preread_inode(struct inode *inode)
{
unsigned long block_group;
unsigned long offset;
unsigned long block;
struct buffer_head *bh;
struct ext2_group_desc * gdp;
block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
gdp = ext2_get_group_desc(inode->i_sb, block_group, &bh);
if (gdp == NULL)
return;
/*
* Figure out the offset within the block group inode table
*/
offset = ((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) *
EXT2_INODE_SIZE(inode->i_sb);
block = le32_to_cpu(gdp->bg_inode_table) +
(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
bh = sb_getblk(inode->i_sb, block);
if (!buffer_uptodate(bh) && !buffer_locked(bh))
ll_rw_block(READA, 1, &bh);
__brelse(bh);
}
/* /*
* There are two policies for allocating an inode. If the new inode is * There are two policies for allocating an inode. If the new inode is
* a directory, then a forward search is made for a block group with both * a directory, then a forward search is made for a block group with both
...@@ -417,6 +455,7 @@ struct inode * ext2_new_inode(struct inode * dir, int mode) ...@@ -417,6 +455,7 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
return ERR_PTR(-EDQUOT); return ERR_PTR(-EDQUOT);
} }
ext2_debug ("allocating inode %lu\n", inode->i_ino); ext2_debug ("allocating inode %lu\n", inode->i_ino);
ext2_preread_inode(inode);
return inode; return inode;
fail2: fail2:
......
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