Hi, This patch introduces file read-ahead to pass1.
Regards, Bob Peterson Red Hat File Systems Signed-off-by: Bob Peterson <rpete...@redhat.com> --- 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 4f1b77a..fec2f64 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,