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:


Reply via email to