Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=e6c... Commit: e6c22884192ff33724b8fd17bf1a040f6210f666 Parent: bba9068b91f737b8f88cd26581eed5884f443bae Author: Bob Peterson rpeterso@redhat.com AuthorDate: Thu Jun 17 11:16:30 2010 -0500 Committer: Bob Peterson rpeterso@redhat.com CommitterDate: Thu Jun 17 11:16:30 2010 -0500
NFS over GFS problem - invalid metadata block
This patch fixes a problem whereby GFS read-ahead was interfering with GFS write requests by continuously re-trying the read-aheads. The patch reduces the extra read-aheads so that the read-ahead for each block is only done once for any given write request.
rhbz#515267 --- gfs-kernel/src/gfs/dio.c | 12 ++++++++---- gfs-kernel/src/gfs/dio.h | 2 +- gfs-kernel/src/gfs/file.c | 12 +++++++++--- 3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/gfs-kernel/src/gfs/dio.c b/gfs-kernel/src/gfs/dio.c index 595ad57..ddf9df2 100644 --- a/gfs-kernel/src/gfs/dio.c +++ b/gfs-kernel/src/gfs/dio.c @@ -1186,21 +1186,22 @@ gfs_get_data_buffer(struct gfs_inode *ip, uint64_t block, int new, * @dblock: the starting disk block * @extlen: the number of blocks in the extent * + * returns: number of blocks for which it submitted read requests. */
-void +int gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen) { struct gfs_sbd *sdp = gl->gl_sbd; struct inode *aspace = gl->gl_aspace; struct buffer_head *first_bh, *bh; uint32_t max_ra = gfs_tune_get(sdp, gt_max_readahead) >> sdp->sd_sb.sb_bsize_shift; - int error; + int error, submitted = 0;
if (!extlen) - return; + return 0; if (!max_ra) - return; + return 0; if (extlen > max_ra) extlen = max_ra;
@@ -1210,6 +1211,7 @@ gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen) goto out; if (!buffer_locked(first_bh)) { error = gfs_dreread(sdp, first_bh, DIO_START); + submitted++; if (error) goto out; } @@ -1222,6 +1224,7 @@ gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen)
if (!buffer_uptodate(bh) && !buffer_locked(bh)) { error = gfs_dreread(sdp, bh, DIO_START); + submitted++; brelse(bh); if (error) goto out; @@ -1237,4 +1240,5 @@ gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen)
out: brelse(first_bh); + return submitted; } diff --git a/gfs-kernel/src/gfs/dio.h b/gfs-kernel/src/gfs/dio.h index 3836d3a..d5d0beb 100644 --- a/gfs-kernel/src/gfs/dio.h +++ b/gfs-kernel/src/gfs/dio.h @@ -75,7 +75,7 @@ int gfs_get_meta_buffer(struct gfs_inode *ip, int height, uint64_t num, int new, struct buffer_head **bhp); int gfs_get_data_buffer(struct gfs_inode *ip, uint64_t block, int new, struct buffer_head **bhp); -void gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen); +int gfs_start_ra(struct gfs_glock *gl, uint64_t dblock, uint32_t extlen);
static __inline__ int gfs_get_inode_buffer(struct gfs_inode *ip, struct buffer_head **bhp) diff --git a/gfs-kernel/src/gfs/file.c b/gfs-kernel/src/gfs/file.c index baec849..925a814 100644 --- a/gfs-kernel/src/gfs/file.c +++ b/gfs-kernel/src/gfs/file.c @@ -313,7 +313,7 @@ gfs_writei(struct gfs_inode *ip, void *buf, struct buffer_head *dibh, *bh; uint64_t lblock, dblock; unsigned int o; - uint32_t extlen = 0; + uint32_t extlen = 0, blocks_ra = 0; unsigned int amount; int new; int journaled = gfs_is_jdata(ip); @@ -355,6 +355,7 @@ gfs_writei(struct gfs_inode *ip, void *buf, error = gfs_block_map(ip, lblock, &new, &dblock, &extlen); if (error) goto fail; + blocks_ra = 0; } else { new = FALSE; dblock = ip->i_num.no_addr; @@ -362,8 +363,13 @@ gfs_writei(struct gfs_inode *ip, void *buf, } }
- if (journaled && extlen > 1) - gfs_start_ra(ip->i_gl, dblock, extlen); + if (journaled && extlen > 1) { + if (!blocks_ra) + blocks_ra = gfs_start_ra(ip->i_gl, dblock, + extlen); + if (blocks_ra) + blocks_ra--; + }
error = gfs_get_data_buffer(ip, dblock, (amount == sdp->sd_sb.sb_bsize) ? TRUE : new,