GFS2: Speed up fiemap function by skipping holes
Subsystems (2)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 GFS2: Speed up fiemap function by skipping holes
Hi,
This is the GFS2 companion patch to the one I previously posted for fiemap.
Patch description:
This patch detects the new want_holesize bit in block_map requests. If a hole is found during fiemap, it calculates the size of the hole based on the current metapath information, then it sets the new buffer_got_holesize bit and returns the hole size in b_size. Since the metapath only represents a section of the file, it can only extrapolate to a certain size based on the current metapath buffers. Therefore, fiemap may call blockmap several times to get the hole size. The hole size is determined by a new function.
Regards,
Bob Peterson
Red Hat File Systems
--- fs/gfs2/bmap.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-)
fs/gfs2/bmap.c +68 -2
@@ -587,6 +587,62 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock, }/** +* hole_size - figure out the size of a hole +* @ip: The inode +* @lblock: The logical starting block number +* @mp: The metapath +* +* Returns: The hole size in bytes +* +*/ +static u64 hole_size (struct inode *inode,sector_t lblock, +struct metapath *mp) +{ +struct gfs2_inode *ip =GFS2_I (inode); +struct gfs2_sbd *sdp =GFS2_SB (inode); +unsigned int end_of_metadata = ip->i_height -1 ; +u64 factor =1 ; +int hgt = end_of_metadata; +u64 holesz =0 , holestep; +const __be64 *first, *end, *ptr; +const struct buffer_head *bh; +u64 isize =i_size_read (inode); +int zeroptrs; +struct metapath mp_eof; + +/* Get a metapath to the very last byte */ +find_metapath (sdp, (isize -1 ) >> inode->i_blkbits, &mp_eof, + ip->i_height); +for (hgt = end_of_metadata; hgt >=0 ; hgt--) { + bh = mp->mp_bh[hgt]; +if (bh) { + zeroptrs =0 ; + first =metapointer (hgt, mp); + end = (const __be64 *)(bh->b_data + bh->b_size); + +for (ptr = first; ptr < end; ptr++) { +if (*ptr) +break ; +else + zeroptrs++; + } + }else { + zeroptrs = sdp->sd_inptrs; + } + holestep =min (factor * zeroptrs, + isize - (lblock + (zeroptrs * holesz))); + holesz += holestep; +if (lblock + holesz >= isize) +return holesz << inode->i_blkbits; + + factor *= sdp->sd_inptrs; +if (hgt && (mp->mp_list[hgt -1 ] < mp_eof.mp_list[hgt -1 ])) + (mp->mp_list[hgt -1 ])++; + } +return holesz << inode->i_blkbits; +} + +/** * gfs2_block_map - Map a block from an inode to a disk block * @inode: The inode * @lblock: The logical block number
@@ -645,11 +701,21 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, ret =lookup_metapath (ip, &mp);if (ret <0 ) goto out; -if (ret != ip->i_height) +if (ret != ip->i_height) { +if (buffer_want_holesize (bh_map)) { + bh_map->b_size =hole_size (inode, lblock, &mp); +set_buffer_got_holesize (bh_map); + } goto do_alloc; + } ptr =metapointer (ip->i_height -1 , &mp); -if (*ptr ==0 ) +if (*ptr ==0 ) { +if (buffer_want_holesize (bh_map)) { + bh_map->b_size =hole_size (inode, lblock, &mp); +set_buffer_got_holesize (bh_map); + } goto do_alloc; + }map_bh (bh_map, inode->i_sb,be64_to_cpu (*ptr)); bh = mp.mp_bh[ip->i_height -1 ]; len =gfs2_extent_length (bh->b_data, bh->b_size, ptr, maxlen, &eob);
Signature · 1 line
1.9.3