Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: e6c22884192ff33724b8fd17bf1a040f6210f666
Parent: bba9068b91f737b8f88cd26581eed5884f443bae
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Jun 17 11:16:30 2010 -0500
Committer: Bob Peterson <rpeterso(a)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,