cluster: STABLE3 - fsck.gfs2: give comfort when processing lots of data blocks

Bob Peterson rpeterso at fedoraproject.org
Tue Jan 26 21:19:08 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=98c92b66e11138e325165cb5e42d21abfc76e8f9
Commit:        98c92b66e11138e325165cb5e42d21abfc76e8f9
Parent:        1b47697dc8905507cd7ad50fd249ca6c86942b82
Author:        Bob Peterson <bob at ganesha.peterson>
AuthorDate:    Mon Nov 30 16:03:10 2009 -0600
Committer:     Bob Peterson <rpeterso at redhat.com>
CommitterDate: Tue Jan 26 14:39:27 2010 -0600

fsck.gfs2: give comfort when processing lots of data blocks

When fsck.gfs2 is running, it can seem to silently hang when it is
processing a large number of data blocks.  This is noticeable when
files get over 20GB in size.  This patch periodically prints
status messages when big files are being checked so customers
know it's still doing something valid.

rhbz#455300
---
 gfs2/fsck/fsck.h     |    1 +
 gfs2/fsck/main.c     |    1 +
 gfs2/fsck/metawalk.c |   17 +++++++++++++++++
 gfs2/fsck/util.c     |   39 +++++++++++++++++++++++++++++++++++++++
 gfs2/fsck/util.h     |    1 +
 5 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index 9c9a3fe..840a526 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -86,6 +86,7 @@ extern osi_list_t dir_hash[FSCK_HASH_SIZE];
 extern osi_list_t inode_hash[FSCK_HASH_SIZE];
 extern struct gfs2_bmap *bl;
 extern uint64_t last_fs_block, last_reported_block;
+extern int64_t last_reported_fblock;
 extern int skip_this_pass, fsck_abort;
 extern int errors_found, errors_corrected;
 extern uint64_t last_data_block;
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index 1ef2cba..82655d8 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -22,6 +22,7 @@ osi_list_t dir_hash[FSCK_HASH_SIZE];
 osi_list_t inode_hash[FSCK_HASH_SIZE];
 struct gfs2_bmap *bl = NULL;
 uint64_t last_fs_block, last_reported_block = -1;
+int64_t last_reported_fblock = -1000000;
 int skip_this_pass = FALSE, fsck_abort = FALSE;
 int errors_found = 0, errors_corrected = 0;
 const char *pass = "";
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 42235be..43dd766 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -14,6 +14,8 @@
 #include "metawalk.h"
 #include "hash.h"
 
+#define COMFORTABLE_BLKS 5242880 /* 20GB in 4K blocks */
+
 static struct gfs2_inode *get_system_inode(struct gfs2_sbd *sbp,
 					   uint64_t block)
 {
@@ -937,6 +939,7 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
 	uint64_t block, *ptr;
 	uint32_t height = ip->i_di.di_height;
 	int  i, head_size;
+	uint64_t blks_checked = 0;
 	int error = 0;
 
 	if (!height)
@@ -960,6 +963,8 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
 
 	/* check data blocks */
 	list = &metalist[height - 1];
+	if (ip->i_di.di_blocks > COMFORTABLE_BLKS)
+		last_reported_fblock = -10000000;
 
 	for (tmp = list->next; tmp != list; tmp = tmp->next) {
 		bh = osi_list_entry(tmp, struct gfs2_buffer_head, b_altlist);
@@ -988,9 +993,21 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
 				stack;
 				return -1;
 			}
+			blks_checked++;
+			if (ip->i_di.di_blocks > COMFORTABLE_BLKS)
+				big_file_comfort(ip, blks_checked);
 		}
 	}
 
+	if (ip->i_di.di_blocks > COMFORTABLE_BLKS) {
+		log_notice( _("\rLarge file at %lld (0x%llx) - 100 percent "
+			      "complete.                                   "
+			      "\n"),
+			    (unsigned long long)ip->i_di.di_num.no_addr,
+			    (unsigned long long)ip->i_di.di_num.no_addr);
+		fflush(stdout);
+	}
+
 	/* free metalists */
 	for (i = 0; i < GFS2_MAX_META_HEIGHT; i++)
 	{
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index eac0e1b..7cdcdc9 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -5,12 +5,51 @@
 #include <sys/time.h>
 #include <stdio.h>
 #include <libintl.h>
+#include <ctype.h>
 #define _(String) gettext(String)
 
 #include "libgfs2.h"
 #include "fs_bits.h"
 #include "util.h"
 
+void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked)
+{
+	static struct timeval tv;
+	static uint32_t seconds = 0;
+	static uint64_t percent, fsize, chksize;
+	uint64_t one_percent = 0;
+	int i, cs;
+	const char *human_abbrev = " KMGTPE";
+
+	one_percent = ip->i_di.di_blocks / 100;
+	if (blks_checked - last_reported_fblock < one_percent)
+		return;
+
+	last_reported_block = blks_checked;
+	gettimeofday(&tv, NULL);
+	if (!seconds)
+		seconds = tv.tv_sec;
+	if (tv.tv_sec == seconds)
+		return;
+
+	fsize = ip->i_di.di_size;
+	for (i = 0; i < 6 && fsize > 1024; i++)
+		fsize /= 1024;
+	chksize = blks_checked * ip->i_sbd->bsize;
+	for (cs = 0; cs < 6 && chksize > 1024; cs++)
+		chksize /= 1024;
+	seconds = tv.tv_sec;
+	percent = (blks_checked * 100) / ip->i_di.di_blocks;
+	log_notice( _("\rChecking %lld%c of %lld%c of file at %lld (0x%llx)"
+		      "- %llu percent complete.                   \r"),
+		    (long long)chksize, human_abbrev[cs],
+		    (unsigned long long)fsize, human_abbrev[i],
+		    (unsigned long long)ip->i_di.di_num.no_addr,
+		    (unsigned long long)ip->i_di.di_num.no_addr,
+		    (unsigned long long)percent);
+	fflush(stdout);
+}
+
 /* Put out a warm, fuzzy message every second so the user     */
 /* doesn't think we hung.  (This may take a long time).       */
 void warm_fuzzy_stuff(uint64_t block)
diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h
index f84ab41..fa18506 100644
--- a/gfs2/fsck/util.h
+++ b/gfs2/fsck/util.h
@@ -7,6 +7,7 @@
   ((lseek((fd), (off), SEEK_SET) == (off)) ? 0 : -1)
 
 struct di_info *search_list(osi_list_t *list, uint64_t addr);
+void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked);
 void warm_fuzzy_stuff(uint64_t block);
 const char *block_type_string(struct gfs2_block_query *q);
 


More information about the cluster-commits mailing list