cluster: RHEL5 - GFS2: make gfs2_fsck conform to fsck(8) exit codes

Bob Peterson rpeterso@fedoraproject.org
Fri Feb 13 15:01:00 GMT 2009


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=69e844b0921c0b3d0ec0bdf309a4ceb07bbd17b2
Commit:        69e844b0921c0b3d0ec0bdf309a4ceb07bbd17b2
Parent:        4b0686b390a0a9dbc1afe19dd7db3a6fe3e7303a
Author:        Bob Peterson <rpeterso@redhat.com>
AuthorDate:    Tue Feb 10 17:05:35 2009 -0600
Committer:     Bob Peterson <rpeterso@redhat.com>
CommitterDate: Thu Feb 12 16:48:42 2009 -0600

GFS2: make gfs2_fsck conform to fsck(8) exit codes

bz 474705

This patch makes gfs2_fsck use the standard exit codes
documented in the fsck(8) man page.
---
 gfs2/fsck/fsck.h       |   16 ++++++++++-
 gfs2/fsck/initialize.c |   25 ++++++-----------
 gfs2/fsck/main.c       |   71 ++++++++++++++++++++++++++++-------------------
 gfs2/fsck/metawalk.c   |   13 ++++++++-
 gfs2/fsck/pass1.c      |   23 +++++++++------
 gfs2/fsck/pass1b.c     |    8 +++---
 gfs2/fsck/pass1c.c     |    6 ++--
 gfs2/fsck/pass2.c      |   51 +++++++++++++++++++++++++---------
 gfs2/fsck/pass3.c      |   17 +++++++++---
 gfs2/fsck/pass4.c      |   16 ++++++++---
 gfs2/fsck/pass5.c      |   12 +++++---
 gfs2/fsck/rgrepair.c   |    4 +++
 12 files changed, 173 insertions(+), 89 deletions(-)

diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index e36c3b8..e6043ac 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -21,6 +21,19 @@
 
 #define query(opts, fmt, args...) gfs2_query(&fsck_abort, opts, fmt, ##args)
 
+/*
+ * Exit codes used by fsck-type programs
+ * Copied from e2fsck's e2fsck.h
+ */
+#define FSCK_OK          0      /* No errors */
+#define FSCK_NONDESTRUCT 1      /* File system errors corrected */
+#define FSCK_REBOOT      2      /* System should be rebooted */
+#define FSCK_UNCORRECTED 4      /* File system errors left uncorrected */
+#define FSCK_ERROR       8      /* Operational error */
+#define FSCK_USAGE       16     /* Usage or syntax error */
+#define FSCK_CANCELED    32     /* Aborted with a signal or ^C */
+#define FSCK_LIBRARY     128    /* Shared library error */
+
 struct inode_info
 {
         osi_list_t list;
@@ -86,7 +99,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, last_reported_block;
-extern int skip_this_pass, fsck_abort, fsck_query;
+extern int skip_this_pass, fsck_abort;
+extern int errors_found, errors_corrected;
 extern uint64_t last_data_block;
 extern uint64_t first_data_block;
 
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 2685819..107bbd3 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -336,33 +336,33 @@ static int fill_super_block(struct gfs2_sbd *sdp)
 }
 
 /**
- * init_sbp - initialize superblock pointer
+ * initialize - initialize superblock pointer
  *
  */
-static int init_sbp(struct gfs2_sbd *sbp)
+int initialize(struct gfs2_sbd *sbp)
 {
 	if(opts.no) {
 		if ((sbp->device_fd = open(opts.device, O_RDONLY)) < 0) {
 			log_crit("Unable to open device: %s\n", opts.device);
-			return -1;
+			return FSCK_USAGE;
 		}
 	} else {
 		/* read in sb from disk */
 		if ((sbp->device_fd = open(opts.device, O_RDWR)) < 0){
 			log_crit("Unable to open device: %s\n", opts.device);
-			return -1;
+			return FSCK_USAGE;
 		}
 	}
 	if (fill_super_block(sbp)) {
 		stack;
-		return -1;
+		return FSCK_ERROR;
 	}
 
 	/* Change lock protocol to be fsck_* instead of lock_* */
 	if(!opts.no) {
 		if(block_mounters(sbp, 1)) {
 			log_err("Unable to block other mounters\n");
-			return -1;
+			return FSCK_USAGE;
 		}
 	}
 
@@ -372,13 +372,13 @@ static int init_sbp(struct gfs2_sbd *sbp)
 		if(!opts.no)
 			block_mounters(sbp, 0);
 		stack;
-		return -1;
+		return FSCK_ERROR;
 	}
 
 	if (init_system_inodes(sbp))
-		return -1;
+		return FSCK_ERROR;
 
-	return 0;
+	return FSCK_OK;
 }
 
 static void destroy_sbp(struct gfs2_sbd *sbp)
@@ -395,13 +395,6 @@ static void destroy_sbp(struct gfs2_sbd *sbp)
 	close(sbp->device_fd);
 }
 
-int initialize(struct gfs2_sbd *sbp)
-{
-
-	return init_sbp(sbp);
-
-}
-
 void destroy(struct gfs2_sbd *sbp)
 {
 	destroy_sbp(sbp);
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index cff8d58..a3759d2 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -32,6 +32,7 @@ osi_list_t inode_hash[FSCK_HASH_SIZE];
 struct gfs2_block_list *bl;
 uint64_t last_fs_block, last_reported_block = -1;
 int skip_this_pass = FALSE, fsck_abort = FALSE;
+int errors_found = 0, errors_corrected = 0;
 const char *pass = "";
 uint64_t last_data_block;
 uint64_t first_data_block;
@@ -69,7 +70,7 @@ int read_cmdline(int argc, char **argv, struct gfs2_options *opts)
 
 		case 'h':
 			usage(argv[0]);
-			exit(0);
+			exit(FSCK_OK);
 			break;
 		case 'n':
 			opts->no = 1;
@@ -82,7 +83,7 @@ int read_cmdline(int argc, char **argv, struct gfs2_options *opts)
 			break;
 		case 'V':
 			version();
-			exit(0);
+			exit(FSCK_OK);
 			break;
 		case 'y':
 			opts->yes = 1;
@@ -90,13 +91,11 @@ int read_cmdline(int argc, char **argv, struct gfs2_options *opts)
 		case ':':
 		case '?':
 			fprintf(stderr, "Please use '-h' for usage.\n");
-			exit(1);
-			break;
+			return FSCK_USAGE;
 		default:
 			fprintf(stderr, "Bad programmer! You forgot to catch"
 				" the %c flag\n", c);
-			exit(1);
-			break;
+			return FSCK_USAGE;
 
 		}
 	}
@@ -104,11 +103,11 @@ int read_cmdline(int argc, char **argv, struct gfs2_options *opts)
 		opts->device = (argv[optind]);
 		if(!opts->device) {
 			fprintf(stderr, "Please use '-h' for usage.\n");
-			exit(1);
+			return FSCK_USAGE;
 		}
 	} else {
 		fprintf(stderr, "No device specified.  Use '-h' for usage.\n");
-		exit(1);
+		return FSCK_USAGE;
 	}
 	return 0;
 }
@@ -187,8 +186,10 @@ int check_system_inode(struct gfs2_inode *sysinode, const char *filename,
 	 * system inodes before we can do any of that. */
 	if(!sysinode || ds.q.block_type != mark) {
 		log_err("Invalid or missing %s system inode.\n", filename);
-		if (query(&opts, "Create new %s system inode? (y/n) ",
-			  filename)) {
+		errors_found++;
+		if ((errors_corrected +=
+		    query(&opts, "Create new %s system inode? (y/n) ",
+			  filename))) {
 			builder(sysinode->i_sbd);
 			gfs2_block_set(sysinode->i_sbd, bl,
 				       sysinode->i_di.di_num.no_addr,
@@ -262,22 +263,23 @@ int main(int argc, char **argv)
 	struct gfs2_sbd *sbp = &sb;
 	int j;
 	enum update_flags update_sys_files;
+	int error = 0;
 
 	memset(sbp, 0, sizeof(*sbp));
 
-	if(read_cmdline(argc, argv, &opts))
-		return 1;
+	if((error = read_cmdline(argc, argv, &opts)))
+		exit(error);
 	setbuf(stdout, NULL);
 	log_notice("Initializing fsck\n");
-	if (initialize(sbp))
-		return 1;
+	if ((error = initialize(sbp)))
+		exit(error);
 
 	signal(SIGINT, interrupt);
 	log_notice("Starting pass1\n");
 	pass = "pass 1";
 	last_reported_block = 0;
-	if (pass1(sbp))
-		return 1;
+	if ((error = pass1(sbp)))
+		exit(error);
 	if (skip_this_pass || fsck_abort) {
 		skip_this_pass = FALSE;
 		log_notice("Pass1 interrupted   \n");
@@ -292,8 +294,8 @@ int main(int argc, char **argv)
 		last_reported_block = 0;
 		pass = "pass 1b";
 		log_notice("Starting pass1b\n");
-		if(pass1b(sbp))
-			return 1;
+		if((error = pass1b(sbp)))
+			exit(error);
 		if (skip_this_pass || fsck_abort) {
 			skip_this_pass = FALSE;
 			log_notice("Pass1b interrupted   \n");
@@ -305,8 +307,8 @@ int main(int argc, char **argv)
 		last_reported_block = 0;
 		pass = "pass 1c";
 		log_notice("Starting pass1c\n");
-		if(pass1c(sbp))
-			return 1;
+		if((error = pass1c(sbp)))
+			exit(error);
 		if (skip_this_pass || fsck_abort) {
 			skip_this_pass = FALSE;
 			log_notice("Pass1c interrupted   \n");
@@ -318,8 +320,8 @@ int main(int argc, char **argv)
 		last_reported_block = 0;
 		pass = "pass 2";
 		log_notice("Starting pass2\n");
-		if (pass2(sbp))
-			return 1;
+		if ((error = pass2(sbp)))
+			exit(error);
 		if (skip_this_pass || fsck_abort) {
 			skip_this_pass = FALSE;
 			log_notice("Pass2 interrupted   \n");
@@ -331,8 +333,8 @@ int main(int argc, char **argv)
 		last_reported_block = 0;
 		pass = "pass 3";
 		log_notice("Starting pass3\n");
-		if (pass3(sbp))
-			return 1;
+		if ((error = pass3(sbp)))
+			exit(error);
 		if (skip_this_pass || fsck_abort) {
 			skip_this_pass = FALSE;
 			log_notice("Pass3 interrupted   \n");
@@ -344,8 +346,8 @@ int main(int argc, char **argv)
 		last_reported_block = 0;
 		pass = "pass 4";
 		log_notice("Starting pass4\n");
-		if (pass4(sbp))
-			return 1;
+		if ((error = pass4(sbp)))
+			exit(error);
 		if (skip_this_pass || fsck_abort) {
 			skip_this_pass = FALSE;
 			log_notice("Pass4 interrupted   \n");
@@ -357,14 +359,17 @@ int main(int argc, char **argv)
 		last_reported_block = 0;
 		pass = "pass 5";
 		log_notice("Starting pass5\n");
-		if (pass5(sbp))
-			return 1;
+		if ((error = pass5(sbp)))
+			exit(error);
 		if (skip_this_pass || fsck_abort) {
 			skip_this_pass = FALSE;
 			log_notice("Pass5 interrupted   \n");
+			error = FSCK_CANCELED;
 		}
 		else
 			log_notice("Pass5 complete      \n");
+	} else {
+		error = FSCK_CANCELED;
 	}
 	update_sys_files = (opts.no ? not_updated : updated);
 	/* Free up our system inodes */
@@ -388,5 +393,13 @@ int main(int argc, char **argv)
 	destroy(sbp);
 	log_notice("gfs2_fsck complete    \n");
 
-	return 0;
+	if (!error) {
+		if (!errors_found)
+			error = FSCK_OK;
+		else if (errors_found == errors_corrected)
+			error = FSCK_NONDESTRUCT;
+		else
+			error = FSCK_UNCORRECTED;
+	}
+	exit(error);
 }
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 6cc90dd..7c0570e 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -187,12 +187,15 @@ int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
 				bh->b_blocknr, bh->b_blocknr, (*count) + 1,
 				ip->i_di.di_num.no_addr,
 				ip->i_di.di_num.no_addr);
+			errors_found++;
 			if (query(&opts, "Attempt to repair it? (y/n) ")) {
 				if (dirent_repair(ip, bh, &de, dent, type,
 						  first))
 					break;
-				else
+				else {
+					errors_corrected++;
 					*update = updated;
+				}
 			}
 			else {
 				log_err("Corrupt directory entry ignored, "
@@ -269,8 +272,10 @@ void warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
 			PRIx64 ") %s.\n", ip->i_di.di_num.no_addr,
 			ip->i_di.di_num.no_addr, *leaf_no, *leaf_no, msg);
 	}
+	errors_found++;
 	if (*leaf_no == *bad_leaf ||
 	    query(&opts, "Attempt to patch around it? (y/n) ")) {
+		errors_corrected++;
 		gfs2_put_leaf_nr(ip, index, old_leaf);
 	}
 	else
@@ -320,10 +325,12 @@ int check_leaf(struct gfs2_inode *ip, enum update_flags *update,
 					ip->i_di.di_num.no_addr,
 					old_leaf, old_leaf, ref_count,
 					exp_count);
+				errors_found++;
 				if (query(&opts, "Attempt to fix it? (y/n) "))
 				{
 					int factor = 0, divisor = ref_count;
 
+					errors_corrected++;
 					lbh = bread(&sbp->buf_list, old_leaf);
 					while (divisor > 1) {
 						factor++;
@@ -434,7 +441,9 @@ int check_leaf(struct gfs2_inode *ip, enum update_flags *update,
 							" doesn't match number of entries found - is %u, found %u\n",
 							leaf_no, leaf_no, ip->i_di.di_num.no_addr,
 							leaf.lf_entries, count);
+					errors_found++;
 					if(query(&opts, "Update leaf entry count? (y/n) ")) {
+						errors_corrected++;
 						leaf.lf_entries = count;
 						gfs2_leaf_out(&leaf, lbh->b_data);
 						log_warn("Leaf entry count updated\n");
@@ -509,8 +518,10 @@ static int check_eattr_entries(struct gfs2_inode *ip,
 							      ea_hdr_prev,
 							      update_it,
 							      pass->private)) {
+					errors_found++;
 					if (query(&opts, "Repair the bad EA? "
 						  "(y/n) ")) {
+						errors_corrected++;
 						ea_hdr->ea_num_ptrs = i;
 						ea_hdr->ea_data_len =
 							cpu_to_be32(tot_ealen);
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 385d777..329e95f 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -194,7 +194,8 @@ static int clear_eas(struct gfs2_inode *ip, struct block_count *bc,
 		log_err(" at block #%" PRIu64 " (0x%" PRIx64 ")",
 			block, block);
 	log_err(".\n");
-	if (query(&opts, "Clear the bad EA? (y/n) ")) {
+	errors_found++;
+	if ((errors_corrected += query(&opts, "Clear the bad EA? (y/n) "))) {
 		if (block == 0)
 			block = ip->i_di.di_eattr;
 		gfs2_block_clear(sdp, bl, block, gfs2_eattr_block);
@@ -588,8 +589,10 @@ int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
 				"): Bad inode address found: %"	PRIu64 " (0x%" PRIx64 ")\n",
 				block, block, ip->i_di.di_num.no_addr,
 				ip->i_di.di_num.no_addr);
-		if(query(&opts, "Fix address in inode at block #%"
-				 PRIu64 " (0x%" PRIx64 ")? (y/n) ", block, block)) {
+		errors_found++;
+		if((errors_corrected +=
+		    query(&opts, "Fix address in inode at block #%"
+			  PRIu64 " (0x%" PRIx64 ")? (y/n) ", block, block))) {
 			ip->i_di.di_num.no_addr = ip->i_di.di_num.no_formal_ino = block;
 			gfs2_dinode_out(&ip->i_di, ip->i_bh->b_data);
 			f = updated;
@@ -771,7 +774,9 @@ int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
 				ip->i_di.di_num.no_addr, ip->i_di.di_num.no_addr,
 				ip->i_di.di_blocks,
 				1 + bc.indir_count + bc.data_count + bc.ea_count);
-		if(query(&opts, "Fix ondisk block count? (y/n) ")) {
+		errors_found++;
+		if ((errors_corrected +=
+		     query(&opts, "Fix ondisk block count? (y/n) "))) {
 			ip->i_di.di_blocks = 1 + bc.indir_count + bc.data_count +
 				bc.ea_count;
 			gfs2_dinode_out(&ip->i_di, ip->i_bh->b_data);
@@ -869,7 +874,7 @@ int pass1(struct gfs2_sbd *sbp)
 		rgd = osi_list_entry(tmp, struct rgrp_list, list);
 		if(gfs2_rgrp_read(sbp, rgd)){
 			stack;
-			return -1;
+			return FSCK_ERROR;
 		}
 		log_debug("RG at %" PRIu64 " (0x%" PRIx64 ") is %u long\n",
 				  rgd->ri.ri_addr, rgd->ri.ri_addr, rgd->ri.ri_length);
@@ -877,7 +882,7 @@ int pass1(struct gfs2_sbd *sbp)
 			if(gfs2_block_set(sbp, bl, rgd->ri.ri_addr + i,
 					  gfs2_meta_other)){
 				stack;
-				return -1;
+				return FSCK_ERROR;
 			}
 		}
 
@@ -892,7 +897,7 @@ int pass1(struct gfs2_sbd *sbp)
 			warm_fuzzy_stuff(block);
 			if (fsck_abort) { /* if asked to abort */
 				gfs2_rgrp_relse(rgd, not_updated);
-				return 0;
+				return FSCK_OK;
 			}
 			if (skip_this_pass) {
 				printf("Skipping pass 1 is not a good idea.\n");
@@ -905,12 +910,12 @@ int pass1(struct gfs2_sbd *sbp)
 				stack;
 				brelse(bh, not_updated);
 				gfs2_rgrp_relse(rgd, not_updated);
-				return -1;
+				return FSCK_ERROR;
 			}
 			brelse(bh, not_updated);
 			first = 0;
 		}
 		gfs2_rgrp_relse(rgd, not_updated);
 	}
-	return 0;
+	return FSCK_OK;
 }
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index c626eb2..1e4968a 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -473,14 +473,14 @@ int pass1b(struct gfs2_sbd *sbp)
 	osi_list_t *tmp = NULL, *x;
 	struct metawalk_fxns find_dirents = {0};
 	find_dirents.check_dentry = &find_dentry;
-	int rc = 0;
+	int rc = FSCK_OK;
 
 	log_info("Looking for duplicate blocks...\n");
 
 	/* If there were no dups in the bitmap, we don't need to do anymore */
 	if(osi_list_empty(&sbp->dup_blocks.list)) {
 		log_info("No duplicate blocks found\n");
-		return 0;
+		return FSCK_OK;
 	}
 
 	/* Rescan the fs looking for pointers to blocks that are in
@@ -496,7 +496,7 @@ int pass1b(struct gfs2_sbd *sbp)
 				  i, i);
 		if(gfs2_block_check(sbp, bl, i, &q)) {
 			stack;
-			rc = -1;
+			rc = FSCK_ERROR;
 			goto out;
 		}
 		if((q.block_type == gfs2_inode_dir) ||
@@ -510,7 +510,7 @@ int pass1b(struct gfs2_sbd *sbp)
 				b = osi_list_entry(tmp, struct blocks, list);
 				if(find_block_ref(sbp, i, b)) {
 					stack;
-					rc = -1;
+					rc = FSCK_ERROR;
 					goto out;
 				}
 			}
diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c
index 27ce0bb..ac3ed27 100644
--- a/gfs2/fsck/pass1c.c
+++ b/gfs2/fsck/pass1c.c
@@ -254,7 +254,7 @@ int pass1c(struct gfs2_sbd *sbp)
 		block_no = ea_block->block;
 
 		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
-			return 0;
+			return FSCK_OK;
 		bh = bread(&sbp->buf_list, block_no);
 		if (gfs2_check_meta(bh, GFS2_METATYPE_IN)) { /* if a dinode */
 			log_info("EA in inode %"PRIu64" (0x%" PRIx64 ")\n",
@@ -270,7 +270,7 @@ int pass1c(struct gfs2_sbd *sbp)
 			if(error < 0) {
 				stack;
 				brelse(bh, not_updated);
-				return -1;
+				return FSCK_ERROR;
 			}
 
 			fsck_inode_put(ip, want_updated); /* dinode_out,
@@ -279,5 +279,5 @@ int pass1c(struct gfs2_sbd *sbp)
 			brelse(bh, want_updated);
 		}
 	}
-	return 0;
+	return FSCK_OK;
 }
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 301ebac..307b6ff 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -206,8 +206,10 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 			log_err("\tName length found  = %u\n"
 					"\tHash expected      = %u (0x%x)\n",
 					de->de_name_len, calculated_hash, calculated_hash);
+			errors_found++;
 			if(query(&opts, "Fix directory hash for %s? (y/n) ",
 					 filename)) {
+				errors_corrected++;
 				de->de_hash = calculated_hash;
 				gfs2_dirent_out(de, (char *)dent);
 				log_err("Directory entry hash for %s fixed.\n", filename);
@@ -228,8 +230,10 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 	if(gfs2_check_range(ip->i_sbd, entryblock)) {
 		log_err("Block # referenced by directory entry %s is out of range\n",
 				tmp_name);
+		errors_found++;
 		if(query(&opts, 
 				 "Clear directory entry tp out of range block? (y/n) ")) {
+			errors_corrected++;
 			log_err("Clearing %s\n", tmp_name);
 			dirent2_del(ip, bh, prev_de, dent);
 			*update = updated;
@@ -254,8 +258,10 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 		/* Handle bad blocks */
 		log_err("Found a bad directory entry: %s\n", filename);
 
+		errors_found++;
 		if(query(&opts, "Clear entry to inode containing bad blocks? (y/n)")) {
 
+			errors_corrected++;
 			entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 			check_inode_eattr(entry_ip, update, &clear_eattrs);
 			fsck_inode_put(entry_ip, not_updated);
@@ -288,10 +294,11 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 			ip->i_di.di_num.no_addr, ip->i_di.di_num.no_addr,
 			q.block_type);
 
+		errors_found++;
 		if(query(&opts, "Clear directory entry to non-inode block? (y/n) ")) {
 			/* FIXME: make sure all blocks referenced by
 			 * this inode are cleared in the bitmap */
-
+			errors_corrected++;
 			dirent2_del(ip, bh, prev_de, dent);
 			*update = updated;
 			log_warn("Directory entry '%s' cleared\n", tmp_name);
@@ -315,7 +322,9 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 				 de_type_string(de->de_type), tmp_name, 
 				 de->de_inum.no_addr, de->de_inum.no_addr,
 				 block_type_string(&q));
+		errors_found++;
 		if(query(&opts, "Clear stale directory entry? (y/n) ")) {
+			errors_corrected++;
 			entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 			check_inode_eattr(entry_ip, update, &clear_eattrs);
 			fsck_inode_put(entry_ip, not_updated);
@@ -338,8 +347,10 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 			log_err("Already found '.' entry in directory %" PRIu64 " (0x%"
 					PRIx64 ")\n",
 					ip->i_di.di_num.no_addr, ip->i_di.di_num.no_addr);
+			errors_found++;
 			if(query(&opts, "Clear duplicate '.' entry? (y/n) ")) {
 
+				errors_corrected++;
 				entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 				check_inode_eattr(entry_ip, update,
 						  &clear_eattrs);
@@ -371,7 +382,9 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 					" (0x%" PRIx64 ").\n",
 					de->de_inum.no_addr, de->de_inum.no_addr,
 					ip->i_di.di_num.no_addr, ip->i_di.di_num.no_addr);
+			errors_found++;
 			if(query(&opts, "Remove '.' reference? (y/n) ")) {
+				errors_corrected++;
 				entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 				check_inode_eattr(entry_ip, update,
 						  &clear_eattrs);
@@ -405,8 +418,10 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 			log_err("Already found '..' entry in directory %" PRIu64 " (0x%"
 					PRIx64 ")\n",
 					ip->i_di.di_num.no_addr, ip->i_di.di_num.no_addr);
+			errors_found++;
 			if(query(&opts, "Clear duplicate '..' entry? (y/n) ")) {
 
+				errors_corrected++;
 				entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 				check_inode_eattr(entry_ip, update,
 						  &clear_eattrs);
@@ -432,7 +447,9 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 					PRIx64 ") pointing to"
 					" something that's not a directory",
 					ip->i_di.di_num.no_addr, ip->i_di.di_num.no_addr);
+			errors_found++;
 			if(query(&opts, "Clear bad '..' directory entry? (y/n) ")) {
+				errors_corrected++;
 				entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 				check_inode_eattr(entry_ip, update,
 						  &clear_eattrs);
@@ -485,7 +502,9 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 		log_err("%s: Hard link to block %" PRIu64" (0x%" PRIx64
 				") detected.\n", filename, entryblock, entryblock);
 
+		errors_found++;
 		if(query(&opts, "Clear hard link to directory? (y/n) ")) {
+			errors_corrected++;
 			*update = 1;
 
 			dirent2_del(ip, bh, prev_de, dent);
@@ -596,10 +615,12 @@ int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
 			sysinode->i_di.di_num.no_addr,
 			sysinode->i_di.di_num.no_addr,
 			sysinode->i_di.di_entries, ds.entry_count);
+		errors_found++;
 		if(query(&opts, "Fix entries for %s inode %" PRIu64 " (0x%"
 			 PRIx64 ")? (y/n) ", dirname,
 			 sysinode->i_di.di_num.no_addr,
 			 sysinode->i_di.di_num.no_addr)) {
+			errors_corrected++;
 			sysinode->i_di.di_entries = ds.entry_count;
 			log_warn("Entries updated\n");
 			update = 1;
@@ -654,26 +675,26 @@ int pass2(struct gfs2_sbd *sbp)
 	/* Check all the system directory inodes. */
 	if (check_system_dir(sbp->md.jiinode, "jindex", build_jindex)) {
 		stack;
-		return -1;
+		return FSCK_ERROR;
 	}
 	if (check_system_dir(sbp->md.pinode, "per_node", build_per_node)) {
 		stack;
-		return -1;
+		return FSCK_ERROR;
 	}
 	if (check_system_dir(sbp->master_dir, "master", build_master)) {
 		stack;
-		return -1;
+		return FSCK_ERROR;
 	}
 	if (check_system_dir(sbp->md.rooti, "root", build_root)) {
 		stack;
-		return -1;
+		return FSCK_ERROR;
 	}
 	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;
+			return FSCK_OK;
 
 		/* Skip the system inodes - they're checked above */
 		if (is_system_dir(sbp, i))
@@ -682,7 +703,7 @@ int pass2(struct gfs2_sbd *sbp)
 		if(gfs2_block_check(sbp, bl, i, &q)) {
 			log_err("Can't get block %"PRIu64 " (0x%" PRIx64
 					") from block list\n", i, i);
-			return -1;
+			return FSCK_ERROR;
 		}
 
 		if(q.block_type != gfs2_inode_dir)
@@ -700,33 +721,35 @@ int pass2(struct gfs2_sbd *sbp)
 			if(check_metatree(ip, &pass2_fxns)) {
 				stack;
 				free(ip);
-				return -1;
+				return FSCK_ERROR;
 			}
 			fsck_inode_put(ip, not_updated);
 		}
 		error = check_dir(sbp, i, &pass2_fxns);
 		if(error < 0) {
 			stack;
-			return -1;
+			return FSCK_ERROR;
 		}
 		if (error > 0) {
 			struct dir_info *di = NULL;
 			error = find_di(sbp, i, &di);
 			if(error < 0) {
 				stack;
-				return -1;
+				return FSCK_ERROR;
 			}
 			if(error == 0) {
 				/* FIXME: factor */
+				errors_found++;
 				if(query(&opts, "Remove directory entry for bad"
 						 " inode %"PRIu64" (0x%" PRIx64 ") in %"PRIu64
 						 " (0x%" PRIx64 ")? (y/n)", i, i, di->treewalk_parent,
 						 di->treewalk_parent)) {
+					errors_corrected++;
 					error = remove_dentry_from_dir(sbp, di->treewalk_parent,
 												   i);
 					if(error < 0) {
 						stack;
-						return -1;
+						return FSCK_ERROR;
 					}
 					if(error > 0) {
 						log_warn("Unable to find dentry for %"
@@ -749,12 +772,12 @@ int pass2(struct gfs2_sbd *sbp)
 			if(!(filename = malloc(sizeof(char) * filename_len))) {
 				log_err("Unable to allocate name string\n");
 				stack;
-				return -1;
+				return FSCK_ERROR;
 			}
 			if(!memset(filename, 0, sizeof(char) * filename_len)) {
 				log_err("Unable to zero name string\n");
 				stack;
-				return -1;
+				return FSCK_ERROR;
 			}
 			memcpy(filename, tmp_name, filename_len);
 
@@ -779,7 +802,7 @@ int pass2(struct gfs2_sbd *sbp)
 		else
 			fsck_inode_put(ip, not_updated); /* does a brelse */
 	}
-	return 0;
+	return FSCK_OK;
 }
 
 
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index 719d0b1..b61cc8d 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -126,10 +126,13 @@ struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp,
 						 "is bad - reattaching to lost+found");
 
 				/* FIXME: add a dinode for this entry instead? */
+
+				errors_found++;
 				if(query(&opts, "Remove directory entry for bad"
 						 " inode %"PRIu64" (0x%" PRIx64 ") in %"PRIu64
 						 " (0x%" PRIx64 ")? (y/n)", di->dinode, di->dinode,
 						 di->treewalk_parent, di->treewalk_parent)) {
+					errors_corrected++;
 					error = remove_dentry_from_dir(sbp, di->treewalk_parent,
 												   di->dinode);
 					if(error < 0) {
@@ -216,19 +219,21 @@ int pass3(struct gfs2_sbd *sbp)
 			 * failure and put the parent inode in a
 			 * param */
 			if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
-				return 0;
+				return FSCK_OK;
 			tdi = mark_and_return_parent(sbp, di);
 
 			/* FIXME: Factor this ? */
 			if(!tdi) {
 				if(gfs2_block_check(sbp, bl, di->dinode, &q)) {
 					stack;
-					return -1;
+					return FSCK_ERROR;
 				}
 				if(q.bad_block) {
 					log_err("Found unlinked directory containing bad block\n");
+					errors_found++;
 					if(query(&opts,
 					   "Clear unlinked directory with bad blocks? (y/n) ")) {
+						errors_corrected++;
 						gfs2_block_set(sbp, bl,
 							       di->dinode,
 							       gfs2_block_free);
@@ -257,7 +262,9 @@ int pass3(struct gfs2_sbd *sbp)
 				 * with eattrs */
 				if(!ip->i_di.di_size && !ip->i_di.di_eattr){
 					log_err("Unlinked directory has zero size.\n");
+					errors_found++;
 					if(query(&opts, "Remove zero-size unlinked directory? (y/n) ")) {
+						errors_corrected++;
 						gfs2_block_set(sbp, bl,
 							       di->dinode,
 							       gfs2_block_free);
@@ -267,11 +274,13 @@ int pass3(struct gfs2_sbd *sbp)
 						log_err("Zero-size unlinked directory remains\n");
 					}
 				}
+				errors_found++;
 				if(query(&opts, "Add unlinked directory to lost+found? (y/n) ")) {
+					errors_corrected++;
 					if(add_inode_to_lf(ip)) {
 						fsck_inode_put(ip, not_updated);
 						stack;
-						return -1;
+						return FSCK_ERROR;
 					}
 					log_warn("Directory relinked to lost+found\n");
 				} else {
@@ -291,5 +300,5 @@ int pass3(struct gfs2_sbd *sbp)
 	if(lf_dip)
 		log_debug("At end of pass3, lost+found entries is %u\n",
 				  lf_dip->i_di.di_entries);
-	return 0;
+	return FSCK_OK;
 }
diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c
index 583a266..ce0e562 100644
--- a/gfs2/fsck/pass4.c
+++ b/gfs2/fsck/pass4.c
@@ -53,7 +53,7 @@ int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) {
 		f = not_updated;
 		if(!(ii = osi_list_entry(tmp, struct inode_info, list))) {
 			log_crit("osi_list_foreach broken in scan_info_list!!\n");
-			exit(1);
+			exit(FSCK_ERROR);
 		}
 		log_debug("Checking reference count on inode at block %" PRIu64
 				  " (0x%" PRIx64 ")\n", ii->inode, ii->inode);
@@ -66,8 +66,10 @@ int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) {
 			}
 			if(q.bad_block) {
 				log_err("Unlinked inode contains bad blocks\n", ii->inode);
+				errors_found++;
 				if(query(&opts,
 						 "Clear unlinked inode with bad blocks? (y/n) ")) {
+					errors_corrected++;
 					gfs2_block_set(sbp, bl, ii->inode,
 						       gfs2_block_free);
 					continue;
@@ -94,7 +96,9 @@ int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) {
 			 * them. */
 			if(!ip->i_di.di_size && !ip->i_di.di_eattr){
 				log_err("Unlinked inode has zero size\n");
+				errors_found++;
 				if(query(&opts, "Clear zero-size unlinked inode? (y/n) ")) {
+					errors_corrected++;
 					gfs2_block_set(sbp, bl, ii->inode,
 						       gfs2_block_free);
 					fsck_inode_put(ip, not_updated);
@@ -102,7 +106,9 @@ int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) {
 				}
 
 			}
+			errors_found++;
 			if(query(&opts, "Add unlinked inode to lost+found? (y/n)")) {
+				errors_corrected++;
 				f = updated;
 				if(add_inode_to_lf(ip)) {
 					stack;
@@ -123,8 +129,10 @@ int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) {
 					ii->inode, ii->link_count, ii->counted_links);
 			/* Read in the inode, adjust the link count,
 			 * and write it back out */
+			errors_found++;
 			if(query(&opts, "Update link count for inode %"
 				 PRIu64 " (0x%" PRIx64 ") ? (y/n) ", ii->inode, ii->inode)) {
+				errors_corrected++;
 				ip = fsck_load_inode(sbp, ii->inode); /* bread, inode_get */
 				fix_inode_count(sbp, ii, ip);
 				fsck_inode_put(ip, updated); /* out, brelse, free */
@@ -171,16 +179,16 @@ int pass4(struct gfs2_sbd *sbp)
 	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;
+			return FSCK_OK;
 		list = &inode_hash[i];
 		if(scan_inode_list(sbp, list)) {
 			stack;
-			return -1;
+			return FSCK_ERROR;
 		}
 	}
 
 	if(lf_dip)
 		log_debug("At end of pass4, lost+found entries is %u\n",
 				  lf_dip->i_di.di_entries);
-	return 0;
+	return FSCK_OK;
 }
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index 030a82c..27f7251 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -109,8 +109,10 @@ int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int buflen,
 			log_err("Metadata type is %u (%s)\n", q.block_type,
 					block_type_string(&q));
 
+			errors_found++;
 			if(query(&opts, "Fix bitmap for block %"
 					 PRIu64" (0x%" PRIx64 ") ? (y/n) ", block, block)) {
+				errors_corrected++;
 				if(gfs2_set_bitmap(sbp, block, block_status))
 					log_err("Failed.\n");
 				else
@@ -167,10 +169,12 @@ enum update_flags update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp,
 		 * means that the total number of blocks we've counted
 		 * exceeds the blocks in the rg */
 		log_err("Internal fsck error - AAHHH!\n");
-		exit(1);
+		exit(FSCK_ERROR);
 	}
 	if(update) {
+		errors_found++;
 		if(query(&opts, "Update resource group counts? (y/n) ")) {
+			errors_corrected++;
 			log_warn("Resource group counts updated\n");
 			/* write out the rgrp */
 			gfs2_rgrp_out(&rgp->rg, rgp->bh[0]->b_data);
@@ -199,14 +203,14 @@ int pass5(struct gfs2_sbd *sbp)
 		enum update_flags f;
 
 		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
-			return 0;
+			return FSCK_OK;
 		log_info("Verifying Resource Group #%" PRIu64 "\n", rg_count);
 		memset(count, 0, sizeof(count));
 		rgp = osi_list_entry(tmp, struct rgrp_list, list);
 
 		if(gfs2_rgrp_read(sbp, rgp)){
 			stack;
-			return -1;
+			return FSCK_ERROR;
 		}
 		rg_count++;
 		/* Compare the bitmaps and report the differences */
@@ -216,5 +220,5 @@ int pass5(struct gfs2_sbd *sbp)
 	/* Fix up superblock info based on this - don't think there's
 	 * anything to do here... */
 
-	return 0;
+	return FSCK_OK;
 }
diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c
index fe44002..003e9ff 100644
--- a/gfs2/fsck/rgrepair.c
+++ b/gfs2/fsck/rgrepair.c
@@ -385,8 +385,10 @@ int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rg,
 		" GFS2_METATYPE_RB nor GFS2_METATYPE_RG.\n",
 		rg->bh[x]->b_blocknr, rg->bh[x]->b_blocknr,
 		(int)x+1, (int)rg->ri.ri_length);
+	errors_found++;
 	if (query(&opts, "Fix the RG? (y/n)")) {
 
+		errors_corrected++;
 		log_err("Attempting to repair the RG.\n");
 		rg->bh[x] = bread(&sdp->nvbuf_list, rg->ri.ri_addr + x);
 		if (x) {
@@ -517,7 +519,9 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count)
 			   PRIx32);
 		/* If we modified the index, write it back to disk. */
 		if (rindex_modified) {
+			errors_found++;
 			if (query(&opts, "Fix the index? (y/n)")) {
+				errors_corrected++;
 				gfs2_rindex_out(&expected->ri, (char *)&buf);
 				gfs2_writei(sdp->md.riinode, (char *)&buf,
 					    rg * sizeof(struct gfs2_rindex),



More information about the Cluster-cvs mailing list