Hi,

On 10/07/14 17:54, Bob Peterson wrote:
Hi,

This patch introduces file read-ahead to pass1.
Why not the other passes too? Is that just because they are not checking all the indirect data?

Steve.

Regards,

Bob Peterson
Red Hat File Systems

Signed-off-by: Bob Peterson <[email protected]>
---
  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,


Reply via email to