[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] [gfs2-utils PATCH] fsck.gfs2: File read-ahead



Hi,

This patch introduces file read-ahead to pass1.

Regards,

Bob Peterson
Red Hat File Systems

Signed-off-by: Bob Peterson <rpeterso 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,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]