Hi, Function gfs2_block_map was re-reading blocks used to store indirect block pointers on every call. This patch tries to find the buffers associated with those blocks in the le_list and, if found, re-uses them instead of re-reading them every time. The buffers are only used for block lookups (not modified) so I don't think this should impact anything, except being a bit faster.
There's also a slight optimization in function find_metapath, which is used a lot. Regards, Bob Peterson Red Hat GFS Signed-off-by: Bob Peterson <[EMAIL PROTECTED]> -- .../fs/gfs2/bmap.c | 46 +++++++++++++++++--- 1 files changed, 39 insertions(+), 7 deletions(-) diff --git a/gfs2-2.6.git.patch7/fs/gfs2/bmap.c b/gfs2-2.6.git.patch8/fs/gfs2/bmap.c index 0974912..9b6e871 100644 --- a/gfs2-2.6.git.patch7/fs/gfs2/bmap.c +++ b/gfs2-2.6.git.patch8/fs/gfs2/bmap.c @@ -342,11 +342,10 @@ static void find_metapath(struct gfs2_inode *ip, u64 block, struct metapath *mp) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - u64 b = block; unsigned int i; for (i = ip->i_di.di_height; i--;) - mp->mp_list[i] = do_div(b, sdp->sd_inptrs); + mp->mp_list[i] = do_div(block, sdp->sd_inptrs); } @@ -441,6 +440,31 @@ static inline void bmap_unlock(struct inode *inode, int create) } /** + * find_bh - Try to locate a buffer head for a given data block + * @sdp: the filesystem + * @lblock: The logical block number + * @bhp: Pointer to a pointer to a buffer head to contain the one found + * + * Returns: 1 if a bh was found for dblock, or 0 if dblock was not found + */ +static int find_bh(struct gfs2_sbd *sdp, u64 dblock, struct buffer_head **bhp) +{ + struct gfs2_bufdata *bd = NULL; + struct buffer_head *bh; + int ret = 0; + + list_for_each_entry(bd, &sdp->sd_log_le_buf, bd_le.le_list) { + bh = bd->bd_bh; + if (bh && buffer_mapped(bh) && bh->b_blocknr == dblock) { + *bhp = bh; + ret = 1; + break; + } + } + return ret; +} + +/** * gfs2_block_map - Map a block from an inode to a disk block * @inode: The inode * @lblock: The logical block number @@ -470,6 +494,7 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, struct metapath mp; u64 size; struct buffer_head *dibh = NULL; + int existing_bh; BUG_ON(maxlen == 0); @@ -502,16 +527,22 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, goto out_fail; dibh = bh; get_bh(dibh); + existing_bh = 0; for (x = 0; x < end_of_metadata; x++) { lookup_block(ip, bh, x, &mp, create, &new, &dblock); - brelse(bh); + if (!existing_bh) + brelse(bh); if (!dblock) goto out_ok; - error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh); - if (error) - goto out_fail; + existing_bh = new ? 0 : find_bh(sdp, dblock, &bh); + if (!existing_bh) { + error = gfs2_meta_indirect_buffer(ip, x+1, dblock, + new, &bh); + if (error) + goto out_fail; + } } boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock); @@ -538,7 +569,8 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, } } out_brelse: - brelse(bh); + if (!existing_bh) + brelse(bh); out_ok: error = 0; out_fail: