[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] [GFS2] [Patch 8/10] Only find indirect pointer buffers once



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 <rpeterso redhat com> 
--
 .../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:



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]