Gitweb:
http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=1969548a...
Commit: 1969548ae01ee6d848e45e684a5ad90f85e94e99
Parent: fc4eb12affd5282b77ada7739229bb3e54871f3d
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Dec 4 12:15:49 2013 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Jul 22 14:44:01 2014 -0500
fsck.gfs2: File read-ahead
This patch introduces file read-ahead
---
gfs2/fsck/metawalk.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++-
gfs2/fsck/metawalk.h | 1 +
gfs2/fsck/pass1.c | 1 +
3 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 659af4e..8da17c6 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1184,6 +1184,59 @@ static void free_metalist(struct gfs2_inode *ip, osi_list_t *mlp)
}
}
+static void file_ra(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
+ int head_size, int maxptrs, int h)
+{
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ uint64_t *p, sblock = 0, block;
+ int extlen = 0;
+
+ if (h + 2 == ip->i_di.di_height) {
+ p = (uint64_t *)(bh->b_data + head_size);
+ if (*p && *(p + 1)) {
+ sblock = be64_to_cpu(*p);
+ p++;
+ block = be64_to_cpu(*p);
+ extlen = block - sblock;
+ if (extlen > 1 && extlen <= maxptrs) {
+ posix_fadvise(sdp->device_fd,
+ sblock * sdp->bsize,
+ (extlen + 1) * sdp->bsize,
+ POSIX_FADV_WILLNEED);
+ return;
+ }
+ }
+ extlen = 0;
+ }
+ for (p = (uint64_t *)(bh->b_data + head_size);
+ p < (uint64_t *)(bh->b_data + sdp->bsize); p++) {
+ if (*p) {
+ if (!sblock) {
+ sblock = be64_to_cpu(*p);
+ extlen = 1;
+ continue;
+ }
+ block = be64_to_cpu(*p);
+ if (block == sblock + extlen) {
+ extlen++;
+ continue;
+ }
+ }
+ if (extlen && sblock) {
+ if (extlen > 1)
+ extlen--;
+ posix_fadvise(sdp->device_fd, sblock * sdp->bsize,
+ extlen * sdp->bsize,
+ POSIX_FADV_WILLNEED);
+ extlen = 0;
+ p--;
+ }
+ }
+ if (extlen)
+ posix_fadvise(sdp->device_fd, sblock * sdp->bsize,
+ extlen * sdp->bsize, POSIX_FADV_WILLNEED);
+}
+
/**
* build_and_check_metalist - check a bunch of indirect blocks
* This includes hash table blocks for directories
@@ -1204,6 +1257,7 @@ static int build_and_check_metalist(struct gfs2_inode *ip,
osi_list_t *mlp,
int h, head_size, iblk_type;
uint64_t *ptr, block;
int error, was_duplicate, is_valid;
+ int maxptrs;
osi_list_add(&metabh->b_altlist, &mlp[0]);
@@ -1225,13 +1279,18 @@ static int build_and_check_metalist(struct gfs2_inode *ip,
osi_list_t *mlp,
iblk_type = GFS2_METATYPE_JD;
else
iblk_type = GFS2_METATYPE_IN;
- if (ip->i_sbd->gfs1)
+ if (ip->i_sbd->gfs1) {
head_size = sizeof(struct gfs_indirect);
- else
+ maxptrs = (ip->i_sbd->bsize - head_size) /
+ sizeof(uint64_t);
+ } else {
head_size = sizeof(struct gfs2_meta_header);
+ maxptrs = ip->i_sbd->sd_inptrs;
+ }
} else {
iblk_type = GFS2_METATYPE_DI;
head_size = sizeof(struct gfs2_dinode);
+ maxptrs = ip->i_sbd->sd_diptrs;
}
prev_list = &mlp[h - 1];
cur_list = &mlp[h];
@@ -1246,6 +1305,8 @@ static int build_and_check_metalist(struct gfs2_inode *ip,
osi_list_t *mlp,
continue;
}
+ if (pass->readahead)
+ file_ra(ip, bh, head_size, maxptrs, h);
/* Now check the metadata itself */
for (ptr = (uint64_t *)(bh->b_data + head_size);
(char *)ptr < (bh->b_data + ip->i_sbd->bsize);
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index 5e30bfe..a4e0676 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -94,6 +94,7 @@ enum meta_check_rc {
struct metawalk_fxns {
void *private;
int invalid_meta_is_fatal;
+ int readahead;
int (*check_leaf_depth) (struct gfs2_inode *ip, uint64_t leaf_no,
int ref_count, struct gfs2_buffer_head *lbh);
int (*check_leaf) (struct gfs2_inode *ip, uint64_t block,
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index c757922..90ca357 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1055,6 +1055,7 @@ static int rangecheck_eattr_leaf(struct gfs2_inode *ip, uint64_t
block,
struct metawalk_fxns rangecheck_fxns = {
.private = NULL,
+ .readahead = 1,
.check_metalist = rangecheck_metadata,
.check_data = rangecheck_data,
.check_leaf = rangecheck_leaf,