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

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


Gitweb:        http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=28f8b8791be9330a5d31aad46cefa886670e9162
Commit:        28f8b8791be9330a5d31aad46cefa886670e9162
Parent:        214e9cc0c2d37eced8ee9c58f4fd3334969d43b4
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 15:09:41 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 b630f7c..df1b7f5 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -24,6 +24,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 833424c..c05cfe2 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -16,6 +16,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)
 {
@@ -939,6 +941,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)
@@ -962,6 +965,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);
@@ -990,9 +995,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 e6bb6af..7e21b04 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -7,12 +7,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