From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4699 invoked by alias); 13 Feb 2009 15:01:35 -0000 Received: (qmail 4407 invoked by alias); 13 Feb 2009 15:01:34 -0000 X-SWARE-Spam-Status: No, hits=2.6 required=5.0 tests=AWL,BAYES_50,J_CHICKENPOX_25,J_CHICKENPOX_31,J_CHICKENPOX_43,J_CHICKENPOX_45,J_CHICKENPOX_54,J_CHICKENPOX_62,J_CHICKENPOX_63,J_CHICKENPOX_65,J_CHICKENPOX_66,SPF_HELO_PASS X-Spam-Status: No, hits=2.6 required=5.0 tests=AWL,BAYES_50,J_CHICKENPOX_25,J_CHICKENPOX_31,J_CHICKENPOX_43,J_CHICKENPOX_45,J_CHICKENPOX_54,J_CHICKENPOX_62,J_CHICKENPOX_63,J_CHICKENPOX_65,J_CHICKENPOX_66,SPF_HELO_PASS X-Spam-Check-By: sourceware.org X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on bastion.fedora.phx.redhat.com Subject: cluster: RHEL5 - GFS2: make gfs2_fsck conform to fsck(8) exit codes To: cluster-cvs-relay@redhat.com X-Project: Cluster Project X-Git-Module: cluster.git X-Git-Refname: refs/heads/RHEL5 X-Git-Reftype: branch X-Git-Oldrev: 4b0686b390a0a9dbc1afe19dd7db3a6fe3e7303a X-Git-Newrev: 69e844b0921c0b3d0ec0bdf309a4ceb07bbd17b2 From: Bob Peterson Message-Id: <20090212224941.A43141201D2@lists.fedorahosted.org> Date: Fri, 13 Feb 2009 15:01:00 -0000 X-Scanned-By: MIMEDefang 2.58 on 172.16.52.254 Mailing-List: contact cluster-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: cluster-cvs-owner@sourceware.org X-SW-Source: 2009-q1/txt/msg00449.txt.bz2 Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=69e844b0921c0b3d0ec0bdf309a4ceb07bbd17b2 Commit: 69e844b0921c0b3d0ec0bdf309a4ceb07bbd17b2 Parent: 4b0686b390a0a9dbc1afe19dd7db3a6fe3e7303a Author: Bob Peterson AuthorDate: Tue Feb 10 17:05:35 2009 -0600 Committer: Bob Peterson 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),