Sophie

Sophie

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

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

commit 965554a2d3d18d877bb4ce3f1cf369775b882e7a
Author: Bob Peterson <bob@ganesha.peterson>
Date:   Wed Dec 2 14:42:55 2009 -0600

    fsck.gfs2: make query() count errors_found, errors_fixed
    
    This patch changes the query() function so that it keeps track
    of errors_found and errors_corrected.  This enforces a consistent
    count of errors found and corrected so that the return code from
    fsck.gfs2 is correct and future code changes that require calls
    to query don't have to code it.  It also makes the calls a tiny
    bit faster because they no longer have to pass the opt variable.
    
    rhbz#455300

diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 46a1084..29e7d2e 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -460,9 +460,9 @@ static int gfs2_recover_journal(struct gfs2_inode *ip, int j, int preen,
 				 "without -a or -p.\n"));
 			goto out;
 		}
-		if (!query(&opts, _("\nJournal #%d (\"journal%d\") is "
-				    "corrupt.  Okay to repair it? (y/n)"),
-			   j+1, j)) {
+		if (!query( _("\nJournal #%d (\"journal%d\") is "
+			      "corrupt.  Okay to repair it? (y/n)"),
+			    j+1, j)) {
 			log_err( _("jid=%u: The journal was not repaired.\n"),
 				 j);
 			goto out;
@@ -505,8 +505,8 @@ static int gfs2_recover_journal(struct gfs2_inode *ip, int j, int preen,
 		error = FSCK_ERROR;
 		goto out;
 	}
-	if (query(&opts, _("\nJournal #%d (\"journal%d\") is dirty.  Okay to "
-			   "replay it? (y/n)"), j+1, j)) {
+	if (query( _("\nJournal #%d (\"journal%d\") is dirty.  Okay to "
+		     "replay it? (y/n)"), j+1, j)) {
 		log_info( _("jid=%u: Replaying journal...\n"), j);
 
 		sd_found_jblocks = sd_replayed_jblocks = 0;
@@ -530,7 +530,7 @@ static int gfs2_recover_journal(struct gfs2_inode *ip, int j, int preen,
 		log_err( _("jid=%u: Replayed %u of %u metadata blocks\n"),
 			j, sd_replayed_metablocks, sd_found_metablocks);
 	} else {
-		if (query(&opts, _("Do you want to clear the dirty journal instead? (y/n)"))) {
+		if (query( _("Do you want to clear the dirty journal instead? (y/n)"))) {
 			write_journal(sdp, sdp->md.journal[j], j,
 				      sdp->md.journal[j]->i_di.di_size /
 				      sdp->sd_sb.sb_bsize);
diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index 754b409..6bba989 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -19,7 +19,7 @@
 #define FSCK_HASH_SIZE          (1 << FSCK_HASH_SHIFT)
 #define FSCK_HASH_MASK          (FSCK_HASH_SIZE - 1)
 
-#define query(opts, fmt, args...) gfs2_query(&fsck_abort, opts, fmt, ##args)
+#define query(fmt, args...) fsck_query(fmt, ##args)
 
 /*
  * Exit codes used by fsck-type programs
@@ -87,6 +87,8 @@ int pass3(struct gfs2_sbd *sbp);
 int pass4(struct gfs2_sbd *sbp);
 int pass5(struct gfs2_sbd *sbp);
 int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count);
+int fsck_query(const char *format, ...)
+	__attribute__((format(printf,1,2)));
 
 /* FIXME: Hack to get this going for pass2 - this should be pulled out
  * of pass1 and put somewhere else... */
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index 6af2759..841d351 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -202,10 +202,7 @@ static 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);
-		errors_found++;
-		if (query(&opts, _("Create new %s system inode? (y/n) "),
-			  filename)) {
-			errors_corrected++;
+		if (query(_("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,
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 00d5a4a..5052eb6 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -238,8 +238,7 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
 				(*count) + 1,
 				(unsigned long long)ip->i_di.di_num.no_addr,
 				(unsigned long long)ip->i_di.di_num.no_addr);
-			errors_found++;
-			if (query(&opts, _("Attempt to repair it? (y/n) "))) {
+			if (query( _("Attempt to repair it? (y/n) "))) {
 				if (dirent_repair(ip, bh, &de, dent, type,
 						  first)) {
 					if (first) /* make a new sentinel */
@@ -254,7 +253,6 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
 				} else {
 					log_err( _("Corrupt directory entry "
 						   "repaired.\n"));
-					errors_corrected++;
 					bmodified(bh);
 					/* keep looping through dentries */
 				}
@@ -277,8 +275,7 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
 					(unsigned long long)bh->b_blocknr,
 					(unsigned long long)ip->i_di.di_num.no_addr,
 					(unsigned long long)ip->i_di.di_num.no_addr);
-				if (query(&opts,
-					  _("Attempt to remove it? (y/n) "))) {
+				if (query(_("Attempt to remove it? (y/n) "))) {
 					dirblk_truncate(ip, prev, bh);
 					log_err(_("The corrupt directory "
 						  "entry was removed.\n"));
@@ -344,10 +341,8 @@ static void warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
 			(unsigned long long)*leaf_no,
 			(unsigned long long)*leaf_no, msg);
 	}
-	errors_found++;
 	if (*leaf_no == *bad_leaf ||
-	    query(&opts, _("Attempt to patch around it? (y/n) "))) {
-		errors_corrected++;
+	    query( _("Attempt to patch around it? (y/n) "))) {
 		if (gfs2_check_range(ip->i_sbd, old_leaf) == 0)
 			gfs2_put_leaf_nr(ip, pindex, old_leaf);
 		else
@@ -425,11 +420,9 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
 				 (unsigned long long)old_leaf,
 				 (unsigned long long)old_leaf,
 				 ref_count, exp_count);
-			errors_found++;
-			if (query(&opts, _("Attempt to fix it? (y/n) "))) {
+			if (query( _("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++;
@@ -550,9 +543,7 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
 						(unsigned long long)
 						ip->i_di.di_num.no_addr,
 						leaf.lf_entries, count);
-					errors_found++;
-					if(query(&opts, _("Update leaf entry count? (y/n) "))) {
-						errors_corrected++;
+					if(query( _("Update leaf entry count? (y/n) "))) {
 						leaf.lf_entries = count;
 						gfs2_leaf_out(&leaf, lbh->b_data);
 						log_warn( _("Leaf entry count updated\n"));
@@ -628,11 +619,8 @@ static int check_eattr_entries(struct gfs2_inode *ip,
 							      bh, ea_hdr,
 							      ea_hdr_prev,
 							      pass->private)) {
-					errors_found++;
-					if (query(&opts, _("Repair the bad "
-							 "Extended Attribute? "
-							   "(y/n) "))) {
-						errors_corrected++;
+					if (query( _("Repair the bad Extended "
+						     "Attribute? (y/n) "))) {
 						ea_hdr->ea_num_ptrs = i;
 						ea_hdr->ea_data_len =
 							cpu_to_be32(tot_ealen);
@@ -748,13 +736,9 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect,
 			error = check_leaf_eattr(ip, block, indirect, pass);
 			if (error) {
 				leaf_pointer_errors++;
-				errors_found++;
-				if (query(&opts, _("Fix the indirect "
-						   "block too? (y/n) "))) {
-					bmodified(indirect_buf);
-					errors_corrected++;
+				if (query( _("Fix the indirect "
+					     "block too? (y/n) ")))
 					*ea_leaf_ptr = 0;
-				}
 			}
 			/* If the first eattr lead is bad, we can't have
 			   a hole, so we have to treat this as an unrecoverable
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 3b73048..f61164c 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -219,12 +219,10 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private)
 		const char *allocdesc[] = {"free space", "data", "unlinked",
 					   "metadata", "reserved"};
 
-		errors_found++;
 		log_err( _("Block %llu (0x%llx) seems to be data, but is "
 			   "marked as %s.\n"), (unsigned long long)block,
 			   (unsigned long long)block, allocdesc[btype]);
-		if(query(&opts, _("Okay to mark it as 'data'? (y/n)"))) {
-			errors_corrected++;
+		if(query( _("Okay to mark it as 'data'? (y/n)"))) {
 			gfs2_set_bitmap(ip->i_sbd, block, GFS2_BLKST_USED);
 			log_err( _("The block was reassigned as data.\n"));
 		} else {
@@ -258,12 +256,10 @@ static int ask_remove_inode_eattr(struct gfs2_inode *ip,
 	log_err( _("Inode %lld (0x%llx) has unrecoverable Extended Attribute "
 		   "errors.\n"), (unsigned long long)ip->i_di.di_num.no_addr,
 		 (unsigned long long)ip->i_di.di_num.no_addr);
-	errors_found++;
-	if (query(&opts, _("Clear all Extended Attributes from the "
-			   "inode? (y/n) "))) {
+	if (query( _("Clear all Extended Attributes from the "
+		     "inode? (y/n) "))) {
 		struct gfs2_block_query q;
 
-		errors_corrected++;
 		if(gfs2_block_check(ip->i_sbd, bl, ip->i_di.di_eattr, &q)) {
 			stack;
 			return -1;
@@ -298,9 +294,7 @@ static int clear_eas(struct gfs2_inode *ip, struct block_count *bc,
 		(unsigned long long)ip->i_di.di_num.no_addr, emsg);
 	log_err( _(" at block #%lld (0x%llx).\n"),
 		 (unsigned long long)block, (unsigned long long)block);
-	errors_found++;
-	if (query(&opts, _("Clear the bad Extended Attribute? (y/n) "))) {
-		errors_corrected++;
+	if (query( _("Clear the bad Extended Attribute? (y/n) "))) {
 		if (block == ip->i_di.di_eattr) {
 			remove_inode_eattr(ip, bc, duplicate);
 			log_err( _("The bad extended attribute was "
@@ -405,10 +399,7 @@ static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
 		   "Extended Attribute errors.\n"),
 		   (unsigned long long)ip->i_di.di_num.no_addr,
 		   (unsigned long long)ip->i_di.di_num.no_addr);
-	errors_found++;
-	if (query(&opts, _("Okay to fix the block count for the inode? "
-			   "(y/n) "))) {
-		errors_corrected++;
+	if (query( _("Okay to fix the block count for the inode? (y/n) "))) {
 		ip->i_di.di_blocks = 1 + bc->indir_count +
 			bc->data_count + bc->ea_count;
 		bmodified(ip->i_bh);
@@ -697,11 +688,9 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
 			(unsigned long long)block,
 			(unsigned long long)ip->i_di.di_num.no_addr,
 			(unsigned long long)ip->i_di.di_num.no_addr);
-		errors_found++;
-		if(query(&opts, _("Fix address in inode at block #%"
-				  PRIu64 " (0x%" PRIx64 ")? (y/n) "),
+		if(query( _("Fix address in inode at block #%"
+			    PRIu64 " (0x%" PRIx64 ")? (y/n) "),
 			 block, block)) {
-			errors_corrected++;
 			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);
 			bmodified(ip->i_bh);
@@ -897,9 +886,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
 			  (unsigned long long)bc.indir_count,
 			  (unsigned long long)bc.data_count,
 			  (unsigned long long)bc.ea_count);
-		errors_found++;
-		if (query(&opts, _("Fix ondisk block count? (y/n) "))) {
-			errors_corrected++;
+		if (query( _("Fix ondisk block count? (y/n) "))) {
 			ip->i_di.di_blocks = 1 + bc.indir_count + bc.data_count +
 				bc.ea_count;
 			bmodified(ip->i_bh);
@@ -919,8 +906,6 @@ static int scan_meta(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
 			  uint64_t block)
 {
 	if (gfs2_check_meta(bh, 0)) {
-		errors_found++;
-
 		log_info( _("Found invalid metadata at #%llu (0x%llx)\n"),
 			  (unsigned long long)block,
 			  (unsigned long long)block);
@@ -928,8 +913,7 @@ static int scan_meta(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
 			stack;
 			return -1;
 		}
-		if(query(&opts, _("Okay to free the invalid block? (y/n)"))) {
-			errors_corrected++;
+		if(query( _("Okay to free the invalid block? (y/n)"))) {
 			gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE);
 			log_err( _("The invalid block was freed.\n"));
 		} else {
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index 6eb40f5..e0b7ab3 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -430,9 +430,7 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blocks *b)
 				  (unsigned long long)id->block_no,
 				  (unsigned long long)b->block_no,
 				  (unsigned long long)b->block_no);
-			errors_found++;
-			if (query(&opts, _("Clear the inode? (y/n) "))) {
-				errors_corrected++;
+			if (query( _("Clear the inode? (y/n) "))) {
 				log_warn( _("Clearing inode %lld (0x%llx)...\n"),
 					 (unsigned long long)id->block_no,
 					 (unsigned long long)id->block_no);
@@ -470,18 +468,15 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blocks *b)
 	}
 	osi_list_foreach(tmp, &b->ref_inode_list) {
 		id = osi_list_entry(tmp, struct inode_with_dups, list);
-		errors_found++;
-		if (!(query(&opts, _("Okay to clear inode %lld (0x%llx)? "
-				     "(y/n) "),
-				     (unsigned long long)id->block_no,
-				     (unsigned long long)id->block_no))) {
+		if (!(query( _("Okay to clear inode %lld (0x%llx)? (y/n) "),
+			     (unsigned long long)id->block_no,
+			     (unsigned long long)id->block_no))) {
 			log_warn( _("The bad inode was not cleared...\n"));
 			continue;
 		}
-		errors_corrected++;
-		    log_warn( _("Clearing inode %lld (0x%llx)...\n"),
-			 (unsigned long long)id->block_no,
-			 (unsigned long long)id->block_no);
+		log_warn( _("Clearing inode %lld (0x%llx)...\n"),
+			  (unsigned long long)id->block_no,
+			  (unsigned long long)id->block_no);
 		ip = fsck_load_inode(sbp, id->block_no);
 		dh.b = b;
 		dh.id = id;
diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c
index 4cf2c44..a00ce2d 100644
--- a/gfs2/fsck/pass1c.c
+++ b/gfs2/fsck/pass1c.c
@@ -50,10 +50,7 @@ static int ask_remove_eattr_entry(struct gfs2_sbd *sdp,
 				  struct gfs2_ea_header *prev,
 				  int fix_curr, int fix_curr_len)
 {
-	errors_found++;
-	if (query(&opts, _("Remove the bad Extended Attribute entry? "
-			   "(y/n) "))) {
-		errors_corrected++;
+	if (query( _("Remove the bad Extended Attribute entry? (y/n) "))) {
 		if (fix_curr)
 			curr->ea_flags |= GFS2_EAFLAG_LAST;
 		if (fix_curr_len) {
@@ -74,9 +71,7 @@ static int ask_remove_eattr_entry(struct gfs2_sbd *sdp,
 
 static int ask_remove_eattr(struct gfs2_inode *ip)
 {
-	errors_found++;
-	if (query(&opts, _("Remove the bad Extended Attribute? (y/n) "))) {
-		errors_corrected++;
+	if (query( _("Remove the bad Extended Attribute? (y/n) "))) {
 		ip->i_di.di_eattr = 0;
 		bmodified(ip->i_bh);
 		log_err( _("Bad Extended Attribute removed.\n"));
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 1827c67..6509171 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -213,10 +213,8 @@ static 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++;
+			if(query( _("Fix directory hash for %s? (y/n) "),
+				  filename)) {
 				de->de_hash = calculated_hash;
 				gfs2_dirent_out(de, (char *)dent);
 				log_err( _("Directory entry hash for %s fixed.\n"), filename);
@@ -237,10 +235,7 @@ static 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++;
+		if(query( _("Clear directory entry tp out of range block? (y/n) "))) {
 			log_err( _("Clearing %s\n"), tmp_name);
 			dirent2_del(ip, bh, prev_de, dent);
 			bmodified(bh);
@@ -263,9 +258,7 @@ static 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, _("Delete inode containing bad blocks? (y/n)"))) {
-			errors_corrected++;
+		if(query( _("Delete inode containing bad blocks? (y/n)"))) {
 			entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 			check_inode_eattr(entry_ip, &pass2_fxns_delete);
 			check_metatree(entry_ip, &pass2_fxns_delete);
@@ -301,12 +294,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 			 _("previously marked invalid") :
 			 _("is not an inode"));
 
-		errors_found++;
-		if(query(&opts, _("Clear directory entry to non-inode block? "
-				  "(y/n) "))) {
+		if(query( _("Clear directory entry to non-inode block? "
+			    "(y/n) "))) {
 			struct gfs2_buffer_head *bhi;
 
-			errors_corrected++;
 			dirent2_del(ip, bh, prev_de, dent);
 			bmodified(bh);
 			log_warn( _("Directory entry '%s' cleared\n"), tmp_name);
@@ -353,9 +344,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 			 (unsigned long long)de->de_inum.no_addr,
 			 (unsigned long long)de->de_inum.no_addr,
 			 block_type_string(&q));
-		errors_found++;
-		if(query(&opts, _("Clear stale directory entry? (y/n) "))) {
-			errors_corrected++;
+		if(query( _("Clear stale directory entry? (y/n) "))) {
 			entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 			check_inode_eattr(entry_ip, &clear_eattrs);
 			fsck_inode_put(entry_ip);
@@ -380,10 +369,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 				" (0x%llx)\n"),
 				(unsigned long long)ip->i_di.di_num.no_addr,
 				(unsigned long long)ip->i_di.di_num.no_addr);
-			errors_found++;
-			if(query(&opts, _("Clear duplicate '.' entry? (y/n) "))) {
-
-				errors_corrected++;
+			if(query( _("Clear duplicate '.' entry? (y/n) "))) {
 				entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 				check_inode_eattr(entry_ip, &clear_eattrs);
 				fsck_inode_put(entry_ip);
@@ -418,9 +404,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 				(unsigned long long)de->de_inum.no_addr,
 				(unsigned long long)ip->i_di.di_num.no_addr,
 				(unsigned long long)ip->i_di.di_num.no_addr);
-			errors_found++;
-			if(query(&opts, _("Remove '.' reference? (y/n) "))) {
-				errors_corrected++;
+			if(query( _("Remove '.' reference? (y/n) "))) {
 				entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 				check_inode_eattr(entry_ip, &clear_eattrs);
 				fsck_inode_put(entry_ip);
@@ -454,10 +438,8 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 				"(0x%llx)\n"),
 				(unsigned long long)ip->i_di.di_num.no_addr,
 				(unsigned long long)ip->i_di.di_num.no_addr);
-			errors_found++;
-			if(query(&opts, _("Clear duplicate '..' entry? (y/n) "))) {
+			if(query( _("Clear duplicate '..' entry? (y/n) "))) {
 
-				errors_corrected++;
 				entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 				check_inode_eattr(entry_ip, &clear_eattrs);
 				fsck_inode_put(entry_ip);
@@ -482,9 +464,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
 				"pointing to something that's not a directory"),
 				(unsigned long long)ip->i_di.di_num.no_addr,
 				(unsigned long long)ip->i_di.di_num.no_addr);
-			errors_found++;
-			if(query(&opts, _("Clear bad '..' directory entry? (y/n) "))) {
-				errors_corrected++;
+			if(query( _("Clear bad '..' directory entry? (y/n) "))) {
 				entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr);
 				check_inode_eattr(entry_ip, &clear_eattrs);
 				fsck_inode_put(entry_ip);
@@ -534,9 +514,7 @@ static 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++;
+		if(query( _("Clear hard link to directory? (y/n) "))) {
 			bmodified(bh);
 			dirent2_del(ip, bh, prev_de, dent);
 			log_warn( _("Directory entry %s cleared\n"), filename);
@@ -616,9 +594,7 @@ int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
 	}
 	if(!ds.dotdir) {
 		log_err( _("No '.' entry found for %s directory.\n"), dirname);
-		errors_found++;
-		if (query(&opts, _("Is it okay to add '.' entry? (y/n) "))) {
-			errors_corrected++;
+		if (query( _("Is it okay to add '.' entry? (y/n) "))) {
 			sprintf(tmp_name, ".");
 			filename_len = strlen(tmp_name); /* no trailing NULL */
 			if(!(filename = malloc(sizeof(char) * filename_len))) {
@@ -650,12 +626,10 @@ int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
 			(unsigned long long)sysinode->i_di.di_num.no_addr,
 			(unsigned long long)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 %llu (0x%llx"
-			 ")? (y/n) "), dirname,
-			 (unsigned long long)sysinode->i_di.di_num.no_addr,
-			 (unsigned long long)sysinode->i_di.di_num.no_addr)) {
-			errors_corrected++;
+		if(query( _("Fix entries for %s inode %llu (0x%llx)? (y/n) "),
+			  dirname,
+			  (unsigned long long)sysinode->i_di.di_num.no_addr,
+			  (unsigned long long)sysinode->i_di.di_num.no_addr)) {
 			sysinode->i_di.di_entries = ds.entry_count;
 			bmodified(sysinode->i_bh);
 			log_warn( _("Entries updated\n"));
@@ -779,12 +753,10 @@ int pass2(struct gfs2_sbd *sbp)
 			}
 			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++;
+				if(query( _("Remove directory entry for bad"
+					    " inode %"PRIu64" (0x%" PRIx64 ") in %"PRIu64
+					    " (0x%" PRIx64 ")? (y/n)"), i, i, di->treewalk_parent,
+					  di->treewalk_parent)) {
 					error = remove_dentry_from_dir(sbp, di->treewalk_parent,
 												   i);
 					if(error < 0) {
@@ -809,10 +781,7 @@ int pass2(struct gfs2_sbd *sbp)
 			log_err(_("No '.' entry found for directory inode at "
 				  "block %"PRIu64" (0x%" PRIx64 ")\n"), i, i);
 
-			errors_found++;
-			if (query(&opts,
-				  _("Is it okay to add '.' entry? (y/n) "))) {
-				errors_corrected++;
+			if (query( _("Is it okay to add '.' entry? (y/n) "))) {
 				sprintf(tmp_name, ".");
 				filename_len = strlen(tmp_name); /* no trailing
 								    NULL */
@@ -849,10 +818,7 @@ int pass2(struct gfs2_sbd *sbp)
 				ip->i_di.di_entries, ds.entry_count,
 				(unsigned long long)ip->i_di.di_num.no_addr,
 				(unsigned long long)ip->i_di.di_num.no_addr);
-			errors_found++;
-			if (query(&opts,
-				  _("Fix the entry count? (y/n) "))) {
-				errors_corrected++;
+			if (query( _("Fix the entry count? (y/n) "))) {
 				ip->i_di.di_entries = ds.entry_count;
 				bmodified(ip->i_bh);
 			} else {
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index 64da3a9..910ecf3 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -131,12 +131,10 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp,
 
 				/* 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++;
+				if(query( _("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)) {
 					error = remove_dentry_from_dir(sbp, di->treewalk_parent,
 												   di->dinode);
 					if(error < 0) {
@@ -234,10 +232,8 @@ int pass3(struct gfs2_sbd *sbp)
 				}
 				if(q.block_type == gfs2_bad_block) {
 					log_err( _("Found unlinked directory containing bad block\n"));
-					errors_found++;
-					if(query(&opts,
+					if(query(
 					   _("Clear unlinked directory with bad blocks? (y/n) "))) {
-						errors_corrected++;
 						gfs2_block_set(sbp, bl,
 							       di->dinode,
 							       gfs2_block_free);
@@ -266,9 +262,7 @@ 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++;
+					if(query( _("Remove zero-size unlinked directory? (y/n) "))) {
 						gfs2_block_set(sbp, bl,
 							       di->dinode,
 							       gfs2_block_free);
@@ -278,9 +272,8 @@ 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(query( _("Add unlinked directory to "
+					    "lost+found? (y/n) "))) {
 					if(add_inode_to_lf(ip)) {
 						fsck_inode_put(ip);
 						stack;
diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c
index d7dd16d..0d590d5 100644
--- a/gfs2/fsck/pass4.c
+++ b/gfs2/fsck/pass4.c
@@ -81,10 +81,8 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) {
 					"bad blocks\n"),
 					(unsigned long long)ii->inode,
 					(unsigned long long)ii->inode);
-				errors_found++;
-				if(query(&opts,
-						 _("Delete unlinked inode with bad blocks? (y/n) "))) {
-					errors_corrected++;
+				if(query(  _("Delete unlinked inode with bad "
+					     "blocks? (y/n) "))) {
 					ip = fsck_load_inode(sbp, ii->inode);
 					check_inode_eattr(ip,
 							  &pass4_fxns_delete);
@@ -108,8 +106,7 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) {
 					   "not an inode (%d)\n"),
 					 q.block_type);
 				ip = fsck_load_inode(sbp, ii->inode);
-				if(query(&opts, _("Delete unlinked inode "
-						  "? (y/n) "))) {
+				if(query(_("Delete unlinked inode? (y/n) "))) {
 					check_inode_eattr(ip,
 							  &pass4_fxns_delete);
 					check_metatree(ip, &pass4_fxns_delete);
@@ -131,9 +128,7 @@ static 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++;
+				if(query( _("Clear zero-size unlinked inode? (y/n) "))) {
 					gfs2_block_set(sbp, bl, ii->inode,
 						       gfs2_block_free);
 					fsck_inode_put(ip);
@@ -141,9 +136,7 @@ static 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++;
+			if(query( _("Add unlinked inode to lost+found? (y/n)"))) {
 				bmodified(ip->i_bh);
 				if(add_inode_to_lf(ip)) {
 					stack;
@@ -164,10 +157,9 @@ static 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++;
+			if(query( _("Update link count for inode %" PRIu64
+				    " (0x%" PRIx64 ") ? (y/n) "),
+				  ii->inode, ii->inode)) {
 				ip = fsck_load_inode(sbp, ii->inode); /* bread, inode_get */
 				fix_inode_count(sbp, ii, ip);
 				bmodified(ip->i_bh);
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index a65483f..f36eb7d 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -94,15 +94,14 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b
 		   So we ignore it. */
 		if (rg_status == GFS2_BLKST_UNLINKED &&
 		    block_status == GFS2_BLKST_FREE) {
-			errors_found++;
 			if (free_unlinked == -1) {
 				log_err( _("Unlinked inode block found at "
 					   "block %llu (0x%llx).\n"),
 					 (unsigned long long)block,
 					 (unsigned long long)block);
-				if(query(&opts, _("Do you want me to fix the "
-						  "bitmap for all unlinked "
-						  "blocks? (y/n) ")))
+				if(query( _("Do you want me to fix the "
+					    "bitmap for all unlinked "
+					    "blocks? (y/n) ")))
 					free_unlinked = 1;
 				else
 					free_unlinked = 0;
@@ -114,13 +113,11 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b
 						  "\n"),
 						(unsigned long long)block,
 						(unsigned long long)block);
-				else {
+				else
 					log_err(_("Unlinked block %llu "
 						  "(0x%llx) bitmap fixed.\n"),
 						(unsigned long long)block,
 						(unsigned long long)block);
-					errors_corrected++;
-				}
 			} else {
 				log_info( _("Unlinked block found at block %"
 					    PRIu64" (0x%" PRIx64 "), left "
@@ -138,10 +135,9 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b
 			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(query( _("Fix bitmap for block %" PRIu64
+				    " (0x%" PRIx64 ") ? (y/n) "),
+				  block, block)) {
 				if(gfs2_set_bitmap(sbp, block, block_status))
 					log_err( _("Failed.\n"));
 				else
@@ -204,9 +200,7 @@ static void update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp,
 		exit(FSCK_ERROR);
 	}
 	if(update) {
-		errors_found++;
-		if(query(&opts, _("Update resource group counts? (y/n) "))) {
-			errors_corrected++;
+		if(query( _("Update resource group counts? (y/n) "))) {
 			log_warn( _("Resource group counts updated\n"));
 			/* write out the rgrp */
 			gfs2_rgrp_out(rg, rgbh[0]->b_data);
diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c
index e3aebda..06603b1 100644
--- a/gfs2/fsck/rgrepair.c
+++ b/gfs2/fsck/rgrepair.c
@@ -388,10 +388,7 @@ static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
 		" GFS2_METATYPE_RB nor GFS2_METATYPE_RG.\n"),
 		rgbh[x]->b_blocknr, rgbh[x]->b_blocknr,
 		(int)x+1, (int)rgd->ri.ri_length);
-	errors_found++;
-	if (query(&opts, "Fix the RG? (y/n)")) {
-
-		errors_corrected++;
+	if (query( _("Fix the RG? (y/n)"))) {
 		log_err( _("Attempting to repair the RG.\n"));
 		rgbh[x] = bread(&sdp->buf_list, rgd->ri.ri_addr + x);
 		if (x) {
@@ -524,9 +521,7 @@ 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++;
+			if (query( _("Fix the index? (y/n)"))) {
 				gfs2_rindex_out(&expected->ri, (char *)&buf);
 				gfs2_writei(sdp->md.riinode, (char *)&buf,
 					    rg * sizeof(struct gfs2_rindex),
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index e396b85..3d3707c 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -13,6 +13,7 @@
 
 #include <inttypes.h>
 #include <linux_endian.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -117,6 +118,7 @@ void warm_fuzzy_stuff(uint64_t block)
 			if (last_fs_block) {
 				percent = (block * 100) / last_fs_block;
 				log_notice( _("\r%" PRIu64 " percent complete.\r"), percent);
+				fflush(stdout);
 			}
 		}
 	}
@@ -133,3 +135,63 @@ const char *block_type_string(struct gfs2_block_query *q)
 		return (blktyp[q->block_type]);
 	return blktyp[15];
 }
+
+/* fsck_query: Same as gfs2_query except it adjusts errors_found and
+   errors_corrected. */
+int fsck_query(const char *format, ...)
+{
+	va_list args;
+	const char *transform;
+	char response;
+	int ret = 0;
+
+	errors_found++;
+	fsck_abort = 0;
+	if(opts.yes) {
+		errors_corrected++;
+		return 1;
+	}
+	if(opts.no)
+		return 0;
+
+	opts.query = TRUE;
+	while (1) {
+		va_start(args, format);
+		transform = _(format);
+		vprintf(transform, args);
+		va_end(args);
+
+		/* Make sure query is printed out */
+		fflush(NULL);
+		response = gfs2_getch();
+
+		printf("\n");
+		fflush(NULL);
+		if (response == 0x3) { /* if interrupted, by ctrl-c */
+			response = generic_interrupt("Question", "response",
+						     NULL,
+						     "Do you want to abort " \
+						     "or continue (a/c)?",
+						     "ac");
+			if (response == 'a') {
+				ret = 0;
+				fsck_abort = 1;
+				break;
+			}
+			printf("Continuing.\n");
+		} else if(tolower(response) == 'y') {
+			errors_corrected++;
+                        ret = 1;
+                        break;
+ 		} else if (tolower(response) == 'n') {
+			ret = 0;
+			break;
+		} else {
+			printf("Bad response %d, please type 'y' or 'n'.\n",
+			       response);
+		}
+	}
+
+	opts.query = FALSE;
+	return ret;
+}
diff --git a/gfs2/libgfs2/gfs2_log.c b/gfs2/libgfs2/gfs2_log.c
index f9f61b2..fbb30e0 100644
--- a/gfs2/libgfs2/gfs2_log.c
+++ b/gfs2/libgfs2/gfs2_log.c
@@ -83,7 +83,7 @@ void print_fsck_log(int iif, int priority, const char *file, int line,
 	va_end(args);
 }
 
-static char gfs2_getch(void)
+char gfs2_getch(void)
 {
 	struct termios termattr, savetermattr;
 	char ch;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index a5ef41c..16bd1db 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -616,10 +616,18 @@ do { print_log(1, MSG_ERROR, format); } while(0)
 #define log_at_crit(format...) \
 do { print_log(1, MSG_CRITICAL, format); } while(0)
 
-void increase_verbosity(void);
-void decrease_verbosity(void);
-void print_fsck_log(int iif, int priority, const char *file, int line,
-					const char *format, ...);
+extern char gfs2_getch(void);
+extern void increase_verbosity(void);
+extern void decrease_verbosity(void);
+extern void print_fsck_log(int iif, int priority, const char *file, int line,
+			   const char *format, ...)
+	__attribute__((format(printf,5,6)));
+extern char generic_interrupt(const char *caller, const char *where,
+			      const char *progress, const char *question,
+			      const char *answers);
+extern int gfs2_query(int *setonabort, struct gfs2_options *opts,
+		      const char *format, ...)
+	__attribute__((format(printf,3,4)));
 
 char generic_interrupt(const char *caller, const char *where,
 		       const char *progress, const char *question,