gfs2-utils: master - GFS2: make gfs2_fsck conform to fsck(8) exit codes
Bob Peterson
rpeterso@fedoraproject.org
Fri Feb 13 15:01:00 GMT 2009
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=84eafcf2d6646ddabb55dd21877d55619e90f037
Commit: 84eafcf2d6646ddabb55dd21877d55619e90f037
Parent: e5c5a6a2aba62f56f7ba6722c189ffc2b9d13f46
Author: Bob Peterson <rpeterso@redhat.com>
AuthorDate: Thu Feb 12 16:26:10 2009 -0600
Committer: Bob Peterson <rpeterso@redhat.com>
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),
More information about the Cluster-cvs
mailing list