Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 9383e745e23602bc45f9c92184feea59 > files > 3

gfs2-utils-0.1.62-28.el5.src.rpm

commit bf0822c4fd7bd701f36ddaef045fb8d587b47f96
Author: Bob Peterson <bob@ganesha.peterson>
Date:   Mon Nov 30 16:03:10 2009 -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

diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index 6c8eed1..754b409 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -98,6 +98,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 756487f..6af2759 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -34,6 +34,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 19e187e..00d5a4a 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -27,6 +27,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)
 {
@@ -945,6 +947,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)
@@ -968,6 +971,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);
@@ -996,9 +1001,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 ac609cb..e396b85 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -19,6 +19,7 @@
 #include <sys/time.h>
 #include <stdio.h>
 #include <libintl.h>
+#include <ctype.h>
 #define _(String) gettext(String)
 
 #include "libgfs2.h"
@@ -56,6 +57,44 @@ int compute_height(struct gfs2_sbd *sdp, uint64_t sz)
 	return height;
 }
 
+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 c112b60..ffbe975 100644
--- a/gfs2/fsck/util.h
+++ b/gfs2/fsck/util.h
@@ -21,6 +21,7 @@
 
 int compute_height(struct gfs2_sbd *sdp, uint64_t sz);
 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);