All of lore.kernel.org
 help / color / mirror / Atom feed
From: rpeterso@sourceware.org <rpeterso@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] cluster/gfs2 fsck/fsck.h fsck/initialize.c fsc ...
Date: 23 Jan 2007 19:30:21 -0000	[thread overview]
Message-ID: <20070123193021.26271.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL5
Changes by:	rpeterso at sourceware.org	2007-01-23 19:30:19

Modified files:
	gfs2/fsck      : fsck.h initialize.c main.c pass1.c pass1b.c 
	                 pass1c.c pass2.c pass3.c pass4.c pass5.c util.c 
	gfs2/libgfs2   : gfs2_log.c libgfs2.h 

Log message:
	Resolves: bz 223506: gfs2_fsck: fatal: invalid metadata block
	This is a crosswrite from gfs1.
	1. Fix a memory leak in pass1b.
	2. Improve performance of pass1b by combining loops through fs.
	3. Give an error message and abort if file system > 16TB and node
	architecture is 32-bits.
	4. Give users an "Abort" "Continue" and "Skip" if they interrupt
	with ctrl-c.  Also, report progress for that pass on interrupt.
	5. Added more "percent complete" messages for other passes.
	
	See bz comments for more details.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/fsck.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/initialize.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6&r2=1.6.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/main.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass1.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass1b.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass1c.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass2.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass3.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass4.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/pass5.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/util.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/gfs2_log.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/libgfs2.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.7.2.1&r2=1.7.2.2

--- cluster/gfs2/fsck/fsck.h	2006/06/12 20:41:43	1.3
+++ cluster/gfs2/fsck/fsck.h	2007/01/23 19:30:19	1.3.2.1
@@ -58,7 +58,8 @@
 extern osi_list_t dir_hash[FSCK_HASH_SIZE];
 extern osi_list_t inode_hash[FSCK_HASH_SIZE];
 extern struct gfs2_block_list *bl;
-extern uint64_t last_fs_block;
+extern uint64_t last_fs_block, last_reported_block;
+extern int skip_this_pass, fsck_abort, fsck_query;
 extern uint64_t last_data_block;
 extern uint64_t first_data_block;
 extern osi_list_t dup_list;
--- cluster/gfs2/fsck/initialize.c	2006/09/20 16:43:25	1.6
+++ cluster/gfs2/fsck/initialize.c	2007/01/23 19:30:19	1.6.2.1
@@ -95,6 +95,7 @@
 {
 	uint32_t i;
 
+	log_info("Freeing buffers.\n");
 	while(!osi_list_empty(&sdp->rglist)){
 		struct rgrp_list *rgd;
 
@@ -157,6 +158,12 @@
 	}
 
 	last_fs_block = rmax;
+	if (last_fs_block > 0xffffffff && sizeof(unsigned long) <= 4) {
+		log_crit("This file system is too big for this computer to handle.\n");
+		log_crit("Last fs block = 0x%llx, but sizeof(unsigned long) is %d bytes.\n",
+				 last_fs_block, sizeof(unsigned long));
+		goto fail;
+	}
 
 	last_data_block = rmax;
 	first_data_block = rmin;
--- cluster/gfs2/fsck/main.c	2006/06/15 18:48:45	1.4
+++ cluster/gfs2/fsck/main.c	2007/01/23 19:30:19	1.4.2.1
@@ -17,6 +17,8 @@
 #include <libgen.h>
 #include <string.h>
 #include <stdarg.h>
+#include <ctype.h>
+#include <signal.h>
 
 #include "copyright.cf"
 #include "libgfs2.h"
@@ -28,7 +30,9 @@
 osi_list_t dir_hash[FSCK_HASH_SIZE];
 osi_list_t inode_hash[FSCK_HASH_SIZE];
 struct gfs2_block_list *bl;
-uint64_t last_fs_block;
+uint64_t last_fs_block, last_reported_block = -1;
+int skip_this_pass = FALSE, fsck_abort = FALSE;
+const char *pass = "";
 uint64_t last_data_block;
 uint64_t first_data_block;
 osi_list_t dup_list;
@@ -133,6 +137,61 @@
 	return 0;
 }
 
+void interrupt(int sig)
+{
+	fd_set rfds;
+	struct timeval tv;
+	char response;
+	int err;
+
+	if (opts.query) /* if we're asking them a question */
+		return;     /* ignore the interrupt signal */
+	FD_ZERO(&rfds);
+	FD_SET(STDIN_FILENO, &rfds);
+
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+	/* Make sure there isn't extraneous input before asking the
+	 * user the question */
+	while((err = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv))) {
+		if(err < 0) {
+			log_debug("Error in select() on stdin\n");
+			break;
+		}
+		read(STDIN_FILENO, &response, sizeof(char));
+	}
+	while (TRUE) {
+		printf("\ngfs_fsck interrupted in %s:  ", pass);
+		if (!last_reported_block || last_reported_block == last_fs_block)
+			printf("progress unknown.\n");
+		else
+			printf("processing block %" PRIu64 " out of %" PRIu64 "\n",
+				   last_reported_block, last_fs_block);
+		printf("Do you want to abort gfs_fsck, skip the rest of %s or continue (a/s/c)?", pass);
+
+		/* Make sure query is printed out */
+		fflush(stdout);
+		read(STDIN_FILENO, &response, sizeof(char));
+
+		if(tolower(response) == 's') {
+			skip_this_pass = TRUE;
+			return;
+		}
+		else if (tolower(response) == 'a') {
+			fsck_abort = TRUE;
+			return;
+		}
+		else if (tolower(response) == 'c')
+			return;
+        else {
+			while(response != '\n')
+				read(STDIN_FILENO, &response, sizeof(char));
+			printf("Bad response, please type 'c', 'a' or 's'.\n");
+			continue;
+        }
+	}
+}
+
 int main(int argc, char **argv)
 {
 	struct gfs2_sbd sb;
@@ -148,41 +207,97 @@
 	if (initialize(sbp))
 		return 1;
 
+	signal(SIGINT, interrupt);
 	log_notice("Starting pass1\n");
+	pass = "pass 1";
+	last_reported_block = 0;
 	if (pass1(sbp))
 		return 1;
-	log_notice("Pass1 complete      \n");
-
-	log_notice("Starting pass1b\n");
-	if(pass1b(sbp))
-		return 1;
-	log_notice("Pass1b complete\n");
-
-	log_notice("Starting pass1c\n");
-	if(pass1c(sbp))
-		return 1;
-	log_notice("Pass1c complete\n");
-
-	log_notice("Starting pass2\n");
-	if (pass2(sbp))
-		return 1;
-	log_notice("Pass2 complete      \n");
-
-	log_notice("Starting pass3\n");
-	if (pass3(sbp))
-		return 1;
-	log_notice("Pass3 complete      \n");
-
-	log_notice("Starting pass4\n");
-	if (pass4(sbp))
-		return 1;
-	log_notice("Pass4 complete      \n");
-
-	log_notice("Starting pass5\n");
-	if (pass5(sbp))
-		return 1;
-	log_notice("Pass5 complete      \n");
+	if (skip_this_pass || fsck_abort) {
+		skip_this_pass = FALSE;
+		log_notice("Pass1 interrupted   \n");
+	}
+	else
+		log_notice("Pass1 complete      \n");
 
+	if (!fsck_abort) {
+		last_reported_block = 0;
+		pass = "pass 1b";
+		log_notice("Starting pass1b\n");
+		if(pass1b(sbp))
+			return 1;
+		if (skip_this_pass || fsck_abort) {
+			skip_this_pass = FALSE;
+			log_notice("Pass1b interrupted   \n");
+		}
+		else
+			log_notice("Pass1b complete\n");
+	}
+	if (!fsck_abort) {
+		last_reported_block = 0;
+		pass = "pass 1c";
+		log_notice("Starting pass1c\n");
+		if(pass1c(sbp))
+			return 1;
+		if (skip_this_pass || fsck_abort) {
+			skip_this_pass = FALSE;
+			log_notice("Pass1c interrupted   \n");
+		}
+		else
+			log_notice("Pass1c complete\n");
+	}
+	if (!fsck_abort) {
+		last_reported_block = 0;
+		pass = "pass 2";
+		log_notice("Starting pass2\n");
+		if (pass2(sbp))
+			return 1;
+		if (skip_this_pass || fsck_abort) {
+			skip_this_pass = FALSE;
+			log_notice("Pass2 interrupted   \n");
+		}
+		else
+			log_notice("Pass2 complete      \n");
+	}
+	if (!fsck_abort) {
+		last_reported_block = 0;
+		pass = "pass 3";
+		log_notice("Starting pass3\n");
+		if (pass3(sbp))
+			return 1;
+		if (skip_this_pass || fsck_abort) {
+			skip_this_pass = FALSE;
+			log_notice("Pass3 interrupted   \n");
+		}
+		else
+			log_notice("Pass3 complete      \n");
+	}
+	if (!fsck_abort) {
+		last_reported_block = 0;
+		pass = "pass 4";
+		log_notice("Starting pass4\n");
+		if (pass4(sbp))
+			return 1;
+		if (skip_this_pass || fsck_abort) {
+			skip_this_pass = FALSE;
+			log_notice("Pass4 interrupted   \n");
+		}
+		else
+			log_notice("Pass4 complete      \n");
+	}
+	if (!fsck_abort) {
+		last_reported_block = 0;
+		pass = "pass 5";
+		log_notice("Starting pass5\n");
+		if (pass5(sbp))
+			return 1;
+		if (skip_this_pass || fsck_abort) {
+			skip_this_pass = FALSE;
+			log_notice("Pass5 interrupted   \n");
+		}
+		else
+			log_notice("Pass5 complete      \n");
+	}
 	/* Free up our system inodes */
 	inode_put(sbp->md.inum, updated);
 	inode_put(sbp->md.statfs, updated);
--- cluster/gfs2/fsck/pass1.c	2006/06/20 18:30:55	1.4
+++ cluster/gfs2/fsck/pass1.c	2007/01/23 19:30:19	1.4.2.1
@@ -801,6 +801,13 @@
 			if (gfs2_next_rg_meta(rgd, &block, first))
 				break;
 			warm_fuzzy_stuff(block);
+			if (fsck_abort) /* if asked to abort */
+				return 0;
+			if (skip_this_pass) {
+				printf("Skipping pass 1 is not a good idea.\n");
+				skip_this_pass = FALSE;
+				fflush(stdout);
+			}
 			bh = bread(sbp, block);
 
 			if (scan_meta(sbp, bh, block)) {
--- cluster/gfs2/fsck/pass1b.c	2006/06/12 20:41:43	1.3
+++ cluster/gfs2/fsck/pass1b.c	2007/01/23 19:30:19	1.3.2.1
@@ -466,6 +466,7 @@
 	osi_list_t *tmp;
 	struct metawalk_fxns find_dirents = {0};
 	find_dirents.check_dentry = &find_dentry;
+	int rc = 0;
 
 	osi_list_init(&dup_list);
 	/* Shove all blocks marked as duplicated into a list */
@@ -484,11 +485,15 @@
 	log_debug("Filesystem has %"PRIu64" (0x%" PRIx64 ") blocks total\n",
 			  last_fs_block, last_fs_block);
 	for(i = 0; i < last_fs_block; i += 1) {
+		warm_fuzzy_stuff(i);
+		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+			goto out;
 		log_debug("Scanning block %" PRIu64 " (0x%" PRIx64 ") for inodes\n",
 				  i, i);
 		if(gfs2_block_check(bl, i, &q)) {
 			stack;
-			return -1;
+			rc = -1;
+			goto out;
 		}
 		if((q.block_type == gfs2_inode_dir) ||
 		   (q.block_type == gfs2_inode_file) ||
@@ -501,33 +506,26 @@
 				b = osi_list_entry(tmp, struct blocks, list);
 				if(find_block_ref(sbp, i, b)) {
 					stack;
-					return -1;
+					rc = -1;
+					goto out;
 				}
 			}
 		}
-	}
-
-	/* Rescan the fs looking for directory entries to the inodes
-	 * with duplicate blocks - might need this to deal with the
-	 * inode correctly */
-	log_info("Looking through directory entries for inodes with duplicate blocks...\n");
-	for(i = 0; i < last_fs_block; i++) {
-		if(gfs2_block_check(bl, i, &q)) {
-			stack;
-			return 0;
-		}
 		if(q.block_type == gfs2_inode_dir) {
 			check_dir(sbp, i, &find_dirents);
 		}
 	}
 
-
 	/* Fix dups here - it's going to slow things down a lot to fix
 	 * it later */
 	log_info("Handling duplicate blocks\n");
-	osi_list_foreach(tmp, &dup_list) {
+out:
+	while (!osi_list_empty(&dup_list)) {
 		b = osi_list_entry(tmp, struct blocks, list);
-		handle_dup_blk(sbp, b);
+		if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */
+			handle_dup_blk(sbp, b);
+		osi_list_del(&b->list);
+		free(b);
 	}
-	return 0;
+	return rc;
 }
--- cluster/gfs2/fsck/pass1c.c	2006/06/20 18:30:55	1.4
+++ cluster/gfs2/fsck/pass1c.c	2007/01/23 19:30:19	1.4.2.1
@@ -235,6 +235,8 @@
 	log_info("Looking for inodes containing ea blocks...\n");
 	while (!gfs2_find_next_block_type(bl, gfs2_eattr_block, &block_no)) {
 
+		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+			return 0;
 		log_info("EA in inode %"PRIu64" (0x%" PRIx64 ")\n", block_no,
 				 block_no);
 		bh = bread(sbp, block_no);
--- cluster/gfs2/fsck/pass2.c	2006/06/15 18:48:45	1.4
+++ cluster/gfs2/fsck/pass2.c	2007/01/23 19:30:19	1.4.2.1
@@ -757,8 +757,13 @@
 		stack;
 		return -1;
 	}
+	log_info("Checking directory inodes.\n");
 	/* Grab each directory inode, and run checks on it */
 	for(i = 0; i < last_fs_block; i++) {
+		warm_fuzzy_stuff(i);
+		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+			return 0;
+
 		/* Skip the root inode - it's checked above */
 		if(i == sbp->md.rooti->i_di.di_num.no_addr)
 			continue;
--- cluster/gfs2/fsck/pass3.c	2006/06/15 18:48:45	1.4
+++ cluster/gfs2/fsck/pass3.c	2007/01/23 19:30:19	1.4.2.1
@@ -214,6 +214,8 @@
 			/* FIXME: Change this so it returns success or
 			 * failure and put the parent inode in a
 			 * param */
+			if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+				return 0;
 			tdi = mark_and_return_parent(sbp, di);
 
 			/* FIXME: Factor this ? */
--- cluster/gfs2/fsck/pass4.c	2006/06/15 18:48:45	1.4
+++ cluster/gfs2/fsck/pass4.c	2007/01/23 19:30:19	1.4.2.1
@@ -48,6 +48,8 @@
 	/* FIXME: should probably factor this out into a generic
 	 * scanning fxn */
 	osi_list_foreach(tmp, list) {
+		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+			return 0;
 		f = not_updated;
 		if(!(ii = osi_list_entry(tmp, struct inode_info, list))) {
 			log_crit("osi_list_foreach broken in scan_info_list!!\n");
@@ -165,6 +167,8 @@
 				  lf_dip->i_di.di_entries);
 	log_info("Checking inode reference counts.\n");
 	for (i = 0; i < FSCK_HASH_SIZE; i++) {
+		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+			return 0;
 		list = &inode_hash[i];
 		if(scan_inode_list(sbp, list)) {
 			stack;
--- cluster/gfs2/fsck/pass5.c	2006/06/12 20:41:43	1.3
+++ cluster/gfs2/fsck/pass5.c	2007/01/23 19:30:19	1.3.2.1
@@ -77,7 +77,10 @@
 	while(byte < end) {
 		rg_status = ((*byte >> bit) & GFS2_BIT_MASK);
 		block = rg_data + *rg_block;
+		log_debug("Checking block %" PRIu64 "\n", block);
 		warm_fuzzy_stuff(block);
+		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+			return 0;
 		gfs2_block_check(bl, block, &q);
 
 		block_status = convert_mark(q.block_type, count);
@@ -128,6 +131,8 @@
 		/* update the bitmaps */
 		check_block_status(sbp, rgp->bh[i]->b_data + bits->bi_offset,
 						   bits->bi_len, &rg_block, rgp->ri.ri_data0, count);
+		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+			return 0;
 	}
 
 	/* actually adjust counters and write out to disk */
@@ -180,6 +185,8 @@
 	for(tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next){
 		enum update_flags f;
 
+		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
+			return 0;
 		log_info("Verifying Resource Group #%" PRIu64 "\n", rg_count);
 		memset(count, 0, sizeof(count));
 		rgp = osi_list_entry(tmp, struct rgrp_list, list);
--- cluster/gfs2/fsck/util.c	2006/06/15 18:48:45	1.4
+++ cluster/gfs2/fsck/util.c	2007/01/23 19:30:19	1.4.2.1
@@ -60,16 +60,19 @@
 {
 	static struct timeval tv;
 	static uint32_t seconds = 0;
-
+	
+	last_reported_block = block;
 	gettimeofday(&tv, NULL);
 	if (!seconds)
-        seconds = tv.tv_sec;
+		seconds = tv.tv_sec;
 	if (tv.tv_sec - seconds) {
 		uint64_t percent;
 
 		seconds = tv.tv_sec;
-		percent = (block * 100) / last_fs_block;
-		log_notice("\r%" PRIu64 " percent complete.\r", percent);
+		if (last_fs_block) {
+			percent = (block * 100) / last_fs_block;
+			log_notice("\r%" PRIu64 " percent complete.\r", percent);
+		}
 	}
 }
 
--- cluster/gfs2/libgfs2/gfs2_log.c	2006/06/15 18:45:22	1.2
+++ cluster/gfs2/libgfs2/gfs2_log.c	2007/01/23 19:30:19	1.2.2.1
@@ -103,6 +103,7 @@
 	if(opts->no)
 		return 0;
 
+	opts->query = TRUE;
 	/* Watch stdin (fd 0) to see when it has input. */
 	FD_ZERO(&rfds);
 	FD_SET(STDIN_FILENO, &rfds);
@@ -150,5 +151,6 @@
 		read(STDIN_FILENO, &response, sizeof(char));
 	}
 
+	opts->query = FALSE;
 	return ret;
 }
--- cluster/gfs2/libgfs2/libgfs2.h	2006/11/30 15:29:48	1.7.2.1
+++ cluster/gfs2/libgfs2/libgfs2.h	2007/01/23 19:30:19	1.7.2.2
@@ -437,6 +437,7 @@
 	char *device;
 	int yes:1;
 	int no:1;
+	int query:1;
 };
 
 #define MSG_DEBUG       7



                 reply	other threads:[~2007-01-23 19:30 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070123193021.26271.qmail@sourceware.org \
    --to=rpeterso@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.