Only find indirect pointer buffers once
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 <[email protected]>
--
.../fs/gfs2/bmap.c | 46 +++++++++++++++++--- 1 files changed, 39 insertions(+), 7 deletions(-)
gfs2-2.6.git.patch8/fs/gfs2/bmap.c renamed from gfs2-2.6.git.patch7/fs/gfs2/bmap.c +39 -7
@@ -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: