From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4559 invoked by alias); 13 Feb 2009 15:01:35 -0000 Received: (qmail 4391 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: gfs2-utils: master - GFS2: make gfs2_fsck conform to fsck(8) exit codes To: cluster-cvs-relay@redhat.com X-Project: Cluster Project X-Git-Module: gfs2-utils.git X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: e5c5a6a2aba62f56f7ba6722c189ffc2b9d13f46 X-Git-Newrev: 84eafcf2d6646ddabb55dd21877d55619e90f037 From: Bob Peterson Message-Id: <20090212222918.759761201D2@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/msg00448.txt.bz2 Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=84eafcf2d6646ddabb55dd21877d55619e90f037 Commit: 84eafcf2d6646ddabb55dd21877d55619e90f037 Parent: e5c5a6a2aba62f56f7ba6722c189ffc2b9d13f46 Author: Bob Peterson AuthorDate: Thu Feb 12 16:26:10 2009 -0600 Committer: Bob Peterson CommitterDate: Thu Feb 12 16:26:10 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 | 30 ++++++++------------ 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, 176 insertions(+), 91 deletions(-) diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index 3bf618c..ac04593 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -9,6 +9,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; @@ -74,7 +87,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 67806f9..e17f3d2 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -146,7 +146,7 @@ static int set_block_ranges(struct gfs2_sbd *sdp) last_fs_block = rmax; if (last_fs_block > 0xffffffff && sizeof(unsigned long) <= 4) { log_crit("This file system is too big for this computer to handle.\n"); - log_crit("Last fs block = 0x%llx, but sizeof(unsigned long) is %lu bytes.\n", + log_crit("Last fs block = 0x%llx, but sizeof(unsigned long) is %u bytes.\n", (unsigned long long)last_fs_block, sizeof(unsigned long)); goto fail; @@ -267,7 +267,8 @@ static int init_system_inodes(struct gfs2_sbd *sdp) bl = gfs2_block_list_create(sdp, last_fs_block+1, &addl_mem_needed); if (!bl) { log_crit("This system doesn't have enough memory + swap space to fsck this file system.\n"); - log_crit("Additional memory needed is approximately: %ldMB\n", addl_mem_needed / 1048576); + log_crit("Additional memory needed is approximately: %lluMB\n", + (unsigned long long)(addl_mem_needed / 1048576ULL)); log_crit("Please increase your swap space by that amount and run gfs2_fsck again.\n"); goto fail; } @@ -323,33 +324,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; } } @@ -359,13 +360,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) @@ -382,13 +383,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 203dfa7..3481b4f 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -20,6 +20,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; @@ -57,7 +58,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; @@ -70,7 +71,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; @@ -78,13 +79,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; } } @@ -92,11 +91,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; } @@ -175,8 +174,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, @@ -250,22 +251,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"); @@ -280,8 +282,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"); @@ -293,8 +295,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"); @@ -306,8 +308,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"); @@ -319,8 +321,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"); @@ -332,8 +334,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"); @@ -345,14 +347,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 */ @@ -376,5 +381,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 a1b9184..bb5dbd5 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -180,12 +180,15 @@ 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 (dirent_repair(ip, bh, &de, dent, type, first)) break; - else + else { + errors_corrected++; *update = updated; + } } else { log_err("Corrupt directory entry ignored, " @@ -267,8 +270,10 @@ 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++; gfs2_put_leaf_nr(ip, index, old_leaf); } else @@ -319,10 +324,12 @@ int check_leaf(struct gfs2_inode *ip, enum update_flags *update, (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) ")) { int factor = 0, divisor = ref_count; + errors_corrected++; lbh = bread(&sbp->buf_list, old_leaf); while (divisor > 1) { factor++; @@ -447,7 +454,9 @@ int check_leaf(struct gfs2_inode *ip, enum update_flags *update, (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++; leaf.lf_entries = count; gfs2_leaf_out(&leaf, lbh->b_data); log_warn("Leaf entry count updated\n"); @@ -522,8 +531,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 e199fb4..6a63338 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -181,7 +181,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); @@ -579,8 +580,10 @@ 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); - 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; @@ -768,7 +771,9 @@ int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, (unsigned long long)ip->i_di.di_blocks, (unsigned long long)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); @@ -867,7 +872,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 %llu (0x%llx) is %u long\n", (unsigned long long)rgd->ri.ri_addr, @@ -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 dcb8dbe..bcef089 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 62f4d7d..9fd21db 100644 --- a/gfs2/fsck/pass1c.c +++ b/gfs2/fsck/pass1c.c @@ -247,7 +247,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", @@ -264,7 +264,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, @@ -273,5 +273,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 791c07d..6047408 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -193,8 +193,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); @@ -215,8 +217,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; @@ -241,8 +245,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); @@ -277,10 +283,11 @@ int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, (unsigned long long)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); @@ -305,7 +312,9 @@ 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++; 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); @@ -329,8 +338,10 @@ 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++; entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); check_inode_eattr(entry_ip, update, &clear_eattrs); @@ -366,7 +377,9 @@ 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++; entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); check_inode_eattr(entry_ip, update, &clear_eattrs); @@ -401,8 +414,10 @@ 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++; entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); check_inode_eattr(entry_ip, update, &clear_eattrs); @@ -428,7 +443,9 @@ 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++; entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); check_inode_eattr(entry_ip, update, &clear_eattrs); @@ -481,7 +498,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); @@ -592,10 +611,12 @@ 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++; sysinode->i_di.di_entries = ds.entry_count; log_warn("Entries updated\n"); update = 1; @@ -652,26 +673,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)) @@ -680,7 +701,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) @@ -698,33 +719,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 %" @@ -747,12 +770,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); @@ -778,7 +801,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 aa8d007..a5c0202 100644 --- a/gfs2/fsck/pass3.c +++ b/gfs2/fsck/pass3.c @@ -113,10 +113,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) { @@ -203,19 +206,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); @@ -244,7 +249,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); @@ -254,11 +261,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 { @@ -278,5 +287,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 aa1a222..38cff40 100644 --- a/gfs2/fsck/pass4.c +++ b/gfs2/fsck/pass4.c @@ -42,7 +42,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); @@ -58,8 +58,10 @@ 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, "Clear unlinked inode with bad blocks? (y/n) ")) { + errors_corrected++; gfs2_block_set(sbp, bl, ii->inode, gfs2_block_free); continue; @@ -86,7 +88,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); @@ -94,7 +98,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; @@ -115,8 +121,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 */ @@ -163,16 +171,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 61600de..aa63f11 100644 --- a/gfs2/fsck/pass5.c +++ b/gfs2/fsck/pass5.c @@ -96,8 +96,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 @@ -156,10 +158,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); @@ -188,14 +192,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 */ @@ -205,5 +209,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 4d0e420..4ddd740 100644 --- a/gfs2/fsck/rgrepair.c +++ b/gfs2/fsck/rgrepair.c @@ -378,8 +378,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) { @@ -509,7 +511,9 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count) ri_compare(rg, actual->ri, expected->ri, ri_bitbytes, 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),