]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ext2: preread inode backing blocks
authorAndrew Morton <akpm@zip.com.au>
Sun, 19 May 2002 09:22:37 +0000 (02:22 -0700)
committerArnaldo Carvalho de Melo <acme@conectiva.com.br>
Sun, 19 May 2002 09:22:37 +0000 (02:22 -0700)
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.

fs/ext2/ialloc.c

index bfe4804c95496b8b82321dbaec3f5371d258ad24..aa2f3ad28fe49a4556ee1402fa51e115d1397c65 100644 (file)
@@ -217,6 +217,44 @@ error_return:
        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
  * a directory, then a forward search is made for a block group with both
@@ -417,6 +455,7 @@ repeat:
                return ERR_PTR(-EDQUOT);
        }
        ext2_debug ("allocating inode %lu\n", inode->i_ino);
+       ext2_preread_inode(inode);
        return inode;
 
 fail2: