cluster: RHEL55 - gfs_fsck -n always returns 0 even if error is found
Bob Peterson
rpeterso at fedoraproject.org
Thu Oct 8 16:19:27 UTC 2009
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=ec11819220efbdb9e0bf395a92ea50294b5b21bc
Commit: ec11819220efbdb9e0bf395a92ea50294b5b21bc
Parent: e5c8d340f5a1ab76eb7940b11d4b594ec743ef6b
Author: Bob Peterson <rpeterso at redhat.com>
AuthorDate: Thu Oct 8 11:20:19 2009 -0500
Committer: Bob Peterson <rpeterso at redhat.com>
CommitterDate: Thu Oct 8 11:20:57 2009 -0500
gfs_fsck -n always returns 0 even if error is found
This patch makes gfs_fsck conform to the rules in the fsck(8)
man page regarding the fsck return code: (0=no errors, 1=file
system errors corrected, 4=errors left uncorrected, etc.)
rhbz#508978
---
gfs/gfs_fsck/file.c | 2 +-
gfs/gfs_fsck/fs_bits.c | 2 +-
gfs/gfs_fsck/fs_bmap.c | 2 +-
gfs/gfs_fsck/fs_dir.c | 14 +++++-----
gfs/gfs_fsck/fs_inode.c | 4 ++-
gfs/gfs_fsck/fsck.h | 14 +++++++++
gfs/gfs_fsck/initialize.c | 25 ++++++-----------
gfs/gfs_fsck/inode.c | 2 +-
gfs/gfs_fsck/main.c | 67 ++++++++++++++++++++++++++-------------------
gfs/gfs_fsck/metawalk.c | 17 +++++++++++-
gfs/gfs_fsck/pass1.c | 38 +++++++++++++++++++-------
gfs/gfs_fsck/pass1b.c | 12 +++++---
gfs/gfs_fsck/pass1c.c | 17 +++++++----
gfs/gfs_fsck/pass2.c | 65 +++++++++++++++++++++++++++++++++-----------
gfs/gfs_fsck/pass3.c | 16 ++++++++---
gfs/gfs_fsck/pass4.c | 31 ++++++++++++++++-----
gfs/gfs_fsck/pass5.c | 17 ++++++++---
gfs/gfs_fsck/rgrp.c | 4 ++-
gfs/gfs_fsck/super.c | 8 +++++-
gfs/gfs_fsck/util.c | 8 +++---
20 files changed, 250 insertions(+), 115 deletions(-)
diff --git a/gfs/gfs_fsck/file.c b/gfs/gfs_fsck/file.c
index e274894..5217e92 100644
--- a/gfs/gfs_fsck/file.c
+++ b/gfs/gfs_fsck/file.c
@@ -180,7 +180,7 @@ int writei(struct fsck_inode *ip, void *buf, uint64_t offset, unsigned int size)
log_crit("fs_writei: "
"Unable to map logical block to real block.\n");
log_crit("Uncircumventable error.\n");
- exit(EXIT_FAILURE);
+ exit(FSCK_ERROR);
}
}
diff --git a/gfs/gfs_fsck/fs_bits.c b/gfs/gfs_fsck/fs_bits.c
index 8162e5e..fce646a 100644
--- a/gfs/gfs_fsck/fs_bits.c
+++ b/gfs/gfs_fsck/fs_bits.c
@@ -37,7 +37,7 @@ static void fs_setbit(unsigned char *buffer, unsigned int buflen,
if(byte >= end){
log_err("fs_setbit: byte >= end\n");
- exit(1);
+ exit(FSCK_ERROR);
}
cur_state = (*byte >> bit) & GFS_BIT_MASK;
diff --git a/gfs/gfs_fsck/fs_bmap.c b/gfs/gfs_fsck/fs_bmap.c
index e7d1fc9..e5243ef 100644
--- a/gfs/gfs_fsck/fs_bmap.c
+++ b/gfs/gfs_fsck/fs_bmap.c
@@ -236,7 +236,7 @@ static int build_height(struct fsck_inode *ip, int height)
dibh, sizeof(struct gfs_dinode));
*/
log_err("ATTENTION -- Not doing copy_tail...\n");
- exit(1);
+ exit(FSCK_ERROR);
error = -1;
goto fail_drelse;
if((error = write_buf(sdp, bh, 0))){
diff --git a/gfs/gfs_fsck/fs_dir.c b/gfs/gfs_fsck/fs_dir.c
index 9286c72..3dcfcea 100644
--- a/gfs/gfs_fsck/fs_dir.c
+++ b/gfs/gfs_fsck/fs_dir.c
@@ -346,7 +346,7 @@ static int leaf_search(osi_buf_t *bh, identifier_t *id,
} while (dirent_next(bh, &dent) == 0);
} else {
log_err("leaf_search: Invalid type for identifier.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
return -ENOENT;
@@ -448,7 +448,7 @@ static int linked_leaf_search(struct fsck_inode *dip, identifier_t *id,
}
} else {
log_err("linked_leaf_search: Invalid type for identifier.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
return error;
}
@@ -476,7 +476,7 @@ static int dir_e_search(struct fsck_inode *dip, identifier_t *id, unsigned int *
if(id->type == ID_FILENAME){
if(id->inum){
log_err("dir_e_search: Illegal parameter. inum must be NULL.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
if(!(id->inum = (struct gfs_inum *)malloc(sizeof(struct gfs_inum)))) {
log_err("Unable to allocate inum structure\n");
@@ -491,7 +491,7 @@ static int dir_e_search(struct fsck_inode *dip, identifier_t *id, unsigned int *
} else {
if(id->filename){
log_err("dir_e_search: Illegal parameter. name must be NULL.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
if(!(id->filename = (osi_filename_t *)malloc(sizeof(osi_filename_t)))) {
log_err("Unable to allocate osi_filename structure\n");
@@ -559,7 +559,7 @@ static int dir_l_search(struct fsck_inode *dip, identifier_t *id, unsigned int *
if(id->type == ID_FILENAME){
if(id->inum){
log_err("dir_l_search: Illegal parameter. inum must be NULL.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
id->inum = (struct gfs_inum *)malloc(sizeof(struct gfs_inum));
memset(id->inum, 0, sizeof(struct gfs_inum));
@@ -568,7 +568,7 @@ static int dir_l_search(struct fsck_inode *dip, identifier_t *id, unsigned int *
} else {
if(id->filename){
log_err("dir_l_search: Illegal parameter. name must be NULL.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
id->filename = (osi_filename_t *)malloc(sizeof(osi_filename_t));
memset(id->filename, 0, sizeof(osi_filename_t));
@@ -1350,7 +1350,7 @@ static int dir_e_add(struct fsck_inode *dip, osi_filename_t *filename,
if (fs_dirent_alloc(dip, nbh, filename->len, &dent)){
log_err("dir_e_add: Uncircumventible error!\n");
- exit(EXIT_FAILURE);
+ exit(FSCK_ERROR);
}
dip->i_di.di_blocks++;
diff --git a/gfs/gfs_fsck/fs_inode.c b/gfs/gfs_fsck/fs_inode.c
index 7d97c11..fadc073 100644
--- a/gfs/gfs_fsck/fs_inode.c
+++ b/gfs/gfs_fsck/fs_inode.c
@@ -166,6 +166,7 @@ static int make_dinode(struct fsck_inode *dip, struct gfs_inum *inum,
if(check_meta(dibh, 0)){
log_err("make_dinode: Buffer #%"PRIu64" has no meta header.\n",
BH_BLKNO(dibh));
+ errors_found++;
if(query(dip->i_sbd, "Add header? (y/n) ")){
struct gfs_meta_header mh;
memset(&mh, 0, sizeof(struct gfs_meta_header));
@@ -173,6 +174,7 @@ static int make_dinode(struct fsck_inode *dip, struct gfs_inum *inum,
mh.mh_type = GFS_METATYPE_NONE;
gfs_meta_header_out(&mh, BH_DATA(dibh));
log_warn("meta header added.\n");
+ errors_corrected++;
} else {
log_err("meta header not added. Failing make_dinode.\n");
relse_buf(sdp, dibh);
@@ -213,7 +215,7 @@ static int make_dinode(struct fsck_inode *dip, struct gfs_inum *inum,
rgd = fs_blk2rgrpd(sdp, inum->no_addr);
if(!rgd){
log_err( "Unable to map block #%"PRIu64" to rgrp\n", inum->no_addr);
- exit(1);
+ exit(FSCK_ERROR);
}
di.di_rgrp = rgd->rd_ri.ri_addr;
diff --git a/gfs/gfs_fsck/fsck.h b/gfs/gfs_fsck/fsck.h
index f1dbbe5..8901902 100644
--- a/gfs/gfs_fsck/fsck.h
+++ b/gfs/gfs_fsck/fsck.h
@@ -17,6 +17,19 @@
#include "fsck_incore.h"
#include "log.h"
+/*
+ * 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 gfs_sb;
struct fsck_sb;
@@ -28,6 +41,7 @@ struct options {
extern uint64_t last_fs_block, last_reported_block;
extern int skip_this_pass, fsck_abort, fsck_query;
+extern int errors_found, errors_corrected;
int initialize(struct fsck_sb *sbp);
void destroy(struct fsck_sb *sbp);
diff --git a/gfs/gfs_fsck/initialize.c b/gfs/gfs_fsck/initialize.c
index 316a485..8d029b8 100644
--- a/gfs/gfs_fsck/initialize.c
+++ b/gfs/gfs_fsck/initialize.c
@@ -361,35 +361,35 @@ static int fill_super_block(struct fsck_sb *sdp)
}
/**
- * init_sbp - initialize superblock pointer
+ * initialize - initialize superblock pointer
*
*/
-static int init_sbp(struct fsck_sb *sbp)
+int initialize(struct fsck_sb *sbp)
{
if(sbp->opts->no) {
if ((sbp->diskfd = open(sbp->opts->device, O_RDONLY)) < 0) {
log_crit("Unable to open device: %s\n", sbp->opts->device);
- return -1;
+ return FSCK_USAGE;
}
} else {
/* read in sb from disk */
if ((sbp->diskfd = open(sbp->opts->device, O_RDWR)) < 0){
log_crit("Unable to open device: %s\n", sbp->opts->device);
- return -1;
+ return FSCK_USAGE;
}
}
/* initialize lists and read in the sb */
if(read_super_block(sbp)) {
stack;
- return -1;
+ return FSCK_ERROR;
}
/* Change lock protocol to be fsck_* instead of lock_* */
if(!sbp->opts->no) {
if(block_mounters(sbp, 1)) {
log_err("Unable to block other mounters\n");
- return -1;
+ return FSCK_ERROR;
}
}
@@ -398,7 +398,7 @@ static int init_sbp(struct fsck_sb *sbp)
if(!sbp->opts->no)
block_mounters(sbp, 0);
stack;
- return -1;
+ return FSCK_ERROR;
}
/* verify various things */
@@ -407,10 +407,10 @@ static int init_sbp(struct fsck_sb *sbp)
if(!sbp->opts->no)
block_mounters(sbp, 0);
stack;
- return -1;
+ return FSCK_ERROR;
}
- return 0;
+ return FSCK_OK;
}
static void destroy_sbp(struct fsck_sb *sbp)
@@ -427,13 +427,6 @@ static void destroy_sbp(struct fsck_sb *sbp)
close(sbp->diskfd);
}
-int initialize(struct fsck_sb *sbp)
-{
-
- return init_sbp(sbp);
-
-}
-
void destroy(struct fsck_sb *sbp)
{
destroy_sbp(sbp);
diff --git a/gfs/gfs_fsck/inode.c b/gfs/gfs_fsck/inode.c
index f4ca0f1..e180ba0 100644
--- a/gfs/gfs_fsck/inode.c
+++ b/gfs/gfs_fsck/inode.c
@@ -224,7 +224,7 @@ static int make_dinode(struct fsck_inode *dip, struct fsck_sb *sdp,
rgd = fs_blk2rgrpd(sdp, inum->no_addr);
if(!rgd){
log_crit("Unable to map block #%"PRIu64" to rgrp\n", inum->no_addr);
- exit(1);
+ exit(FSCK_ERROR);
}
di.di_rgrp = rgd->rd_ri.ri_addr;
diff --git a/gfs/gfs_fsck/main.c b/gfs/gfs_fsck/main.c
index c1c47bf..9414cca 100644
--- a/gfs/gfs_fsck/main.c
+++ b/gfs/gfs_fsck/main.c
@@ -24,6 +24,7 @@
uint64_t last_fs_block, last_reported_block = -1;
int skip_this_pass = FALSE, fsck_abort = FALSE, fsck_query = FALSE;
+int errors_found = 0, errors_corrected = 0;
const char *pass = "";
void print_map(struct block_list *il, int count)
@@ -70,7 +71,7 @@ int read_cmdline(int argc, char **argv, struct options *opts)
case 'h':
usage(argv[0]);
- exit(0);
+ exit(FSCK_OK);
break;
case 'n':
opts->no = 1;
@@ -83,7 +84,7 @@ int read_cmdline(int argc, char **argv, struct options *opts)
break;
case 'V':
version();
- exit(0);
+ exit(FSCK_OK);
break;
case 'y':
opts->yes = 1;
@@ -91,12 +92,12 @@ int read_cmdline(int argc, char **argv, struct options *opts)
case ':':
case '?':
fprintf(stderr, "Please use '-h' for usage.\n");
- exit(1);
+ exit(FSCK_USAGE);
break;
default:
fprintf(stderr, "Bad programmer! You forgot to catch"
" the %c flag\n", c);
- exit(1);
+ exit(FSCK_USAGE);
break;
}
@@ -105,11 +106,11 @@ int read_cmdline(int argc, char **argv, struct options *opts)
opts->device = (argv[optind]);
if(!opts->device) {
fprintf(stderr, "Please use '-h' for usage.\n");
- exit(1);
+ exit(FSCK_USAGE);
}
} else {
fprintf(stderr, "No device specified. Use '-h' for usage.\n");
- exit(1);
+ exit(FSCK_USAGE);
}
return 0;
}
@@ -173,25 +174,25 @@ int main(int argc, char **argv)
{
struct fsck_sb sb;
struct options opts = {0};
-
struct fsck_sb *sbp = &sb;
- memset(sbp, 0, sizeof(*sbp));
+ int error = 0;
+ memset(sbp, 0, sizeof(*sbp));
sbp->opts = &opts;
- 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");
@@ -203,8 +204,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");
@@ -216,8 +217,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");
@@ -229,8 +230,8 @@ int main(int argc, char **argv)
last_reported_block = 0;
pass = "pass 2";
log_notice("Starting pass2\n");
- if (pass2(sbp, &opts))
- return 1;
+ if ((error = pass2(sbp, &opts)))
+ exit(error);
if (skip_this_pass || fsck_abort) {
skip_this_pass = FALSE;
log_notice("Pass2 interrupted \n");
@@ -242,8 +243,8 @@ int main(int argc, char **argv)
last_reported_block = 0;
pass = "pass 3";
log_notice("Starting pass3\n");
- if (pass3(sbp, &opts))
- return 1;
+ if ((error = pass3(sbp, &opts)))
+ exit(error);
if (skip_this_pass || fsck_abort) {
skip_this_pass = FALSE;
log_notice("Pass3 interrupted \n");
@@ -255,8 +256,8 @@ int main(int argc, char **argv)
last_reported_block = 0;
pass = "pass 4";
log_notice("Starting pass4\n");
- if (pass4(sbp, &opts))
- return 1;
+ if ((error = pass4(sbp, &opts)))
+ exit(error);
if (skip_this_pass || fsck_abort) {
skip_this_pass = FALSE;
log_notice("Pass4 interrupted \n");
@@ -268,8 +269,8 @@ int main(int argc, char **argv)
last_reported_block = 0;
pass = "pass 5";
log_notice("Starting pass5\n");
- if (pass5(sbp, &opts))
- return 1;
+ if ((error = pass5(sbp, &opts)))
+ exit(error);
if (skip_this_pass || fsck_abort) {
skip_this_pass = FALSE;
log_notice("Pass5 interrupted \n");
@@ -277,10 +278,20 @@ int main(int argc, char **argv)
else
log_notice("Pass5 complete \n");
log_notice("Writing changes to disk\n");
+ } else {
+ error = FSCK_CANCELED;
}
- destroy(sbp);
- return 0;
+ destroy(sbp);
+ 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/gfs/gfs_fsck/metawalk.c b/gfs/gfs_fsck/metawalk.c
index ce39b7a..3475bb9 100644
--- a/gfs/gfs_fsck/metawalk.c
+++ b/gfs/gfs_fsck/metawalk.c
@@ -68,7 +68,7 @@ static int check_entries(struct fsck_inode *ip, osi_buf_t *bh, int type,
while(1) {
if (skip_this_pass || fsck_abort)
- return 0;
+ return FSCK_OK;
memset(&de, 0, sizeof(struct gfs_dirent));
gfs_dirent_in(&de, (char *)dent);
filename = (char *)dent + sizeof(struct gfs_dirent);
@@ -80,6 +80,7 @@ static int check_entries(struct fsck_inode *ip, osi_buf_t *bh, int type,
PRIu64 ", entry %d of directory %"
PRIu64 " is corrupt.\n", BH_BLKNO(bh),
(*count) + 1, ip->i_di.di_num.no_addr);
+ errors_found++;
if (query(ip->i_sbd, "Attempt to repair it? (y/n) ")) {
if (dirent_repair(ip, bh, &de, dent, type,
first)) {
@@ -91,10 +92,12 @@ static int check_entries(struct fsck_inode *ip, osi_buf_t *bh, int type,
log_err("Unable to repair corrupt "
"directory entry; the entry "
"was removed instead.\n");
+ errors_corrected++;
return 0;
} else {
log_err("Corrupt directory entry "
"repaired.\n");
+ errors_corrected++;
*update = 1;
/* keep looping through dentries */
}
@@ -114,12 +117,14 @@ static int check_entries(struct fsck_inode *ip, osi_buf_t *bh, int type,
"zero in leaf %"PRIu64" of directory "
"%"PRIu64"!\n", BH_BLKNO(bh),
ip->i_di.di_num.no_addr);
+ errors_found++;
if (query(ip->i_sbd,
"Attempt to remove it? (y/n) ")) {
dirblk_truncate(ip, prev, bh);
*update = 1;
log_err("The corrupt directory entry "
"was removed.\n");
+ errors_corrected++;
} else {
log_err("Corrupt directory entry "
"ignored, stopped after "
@@ -169,8 +174,10 @@ static void warn_and_patch(struct fsck_inode *ip, uint64_t *leaf_no,
PRIu64 " %s.\n", ip->i_di.di_num.no_addr, *leaf_no,
msg);
}
+ errors_found++;
if (*leaf_no == *bad_leaf ||
query(ip->i_sbd, "Attempt to patch around it? (y/n) ")) {
+ errors_corrected++;
if (check_range(ip->i_sbd, old_leaf) == 0)
put_leaf_nr(ip, lindex, old_leaf);
else
@@ -250,9 +257,11 @@ static int check_leaf_blks(struct fsck_inode *ip, int *update,
"\tFound: %u, Expected: %u\n",
ip->i_num.no_addr, old_leaf, ref_count,
exp_count);
+ errors_found++;
if (query(ip->i_sbd, "Attempt to fix it? (y/n) ")) {
int factor = 0, divisor = ref_count;
+ errors_corrected++;
get_and_read_buf(sbp, old_leaf, &lbh, 0);
while (divisor > 1) {
factor++;
@@ -355,7 +364,9 @@ static int check_leaf_blks(struct fsck_inode *ip, int *update,
gfs_leaf_in(&leaf, BH_DATA(lbh));
log_err("Leaf(%"PRIu64") entry count in directory %"PRIu64" doesn't match number of entries found - is %u, found %u\n", leaf_no, ip->i_num.no_addr, leaf.lf_entries, count);
+ errors_found++;
if(query(sbp, "Update leaf entry count? (y/n) ")) {
+ errors_corrected++;
leaf.lf_entries = count;
gfs_leaf_out(&leaf, BH_DATA(lbh));
write_buf(sbp, lbh, 0);
@@ -431,9 +442,11 @@ static int check_eattr_entries(struct fsck_inode *ip, osi_buf_t *bh,
bh, ea_hdr,
ea_hdr_prev,
pass->private)) {
+ errors_found++;
if (query(ip->i_sbd,
"Repair the bad Extended "
"Attribute? (y/n) ")) {
+ errors_corrected++;
ea_hdr->ea_num_ptrs = i;
ea_hdr->ea_data_len =
cpu_to_be32(tot_ealen);
@@ -547,9 +560,11 @@ static int check_indirect_eattr(struct fsck_inode *ip, uint64_t indirect,
if (error) {
leaf_pointer_errors++;
if (!update_indir_block) {
+ errors_found++;
if (query(sdp, "Fix the indirect "
"block too? (y/n) ")) {
update_indir_block = 1;
+ errors_corrected++;
*ea_leaf_ptr = 0;
}
} else
diff --git a/gfs/gfs_fsck/pass1.c b/gfs/gfs_fsck/pass1.c
index 016f587..caa7660 100644
--- a/gfs/gfs_fsck/pass1.c
+++ b/gfs/gfs_fsck/pass1.c
@@ -261,8 +261,10 @@ static int check_data(struct fsck_inode *ip, uint64_t block, void *private)
log_err("Block #%llu seems to be journaled data, but "
"is marked as %s.\n",
(unsigned long long)block, allocdesc[btype]);
+ errors_found++;
if(query(sdp, "Okay to mark it as 'journaled data'? "
"(y/n)")) {
+ errors_corrected++;
fs_set_bitmap(sdp, block, GFS_BLKST_USEDMETA);
log_err("The block was reassigned as "
"journaled data.\n");
@@ -273,8 +275,10 @@ static int check_data(struct fsck_inode *ip, uint64_t block, void *private)
log_err("Block #%llu seems to be data, but "
"is marked as %s.\n",
(unsigned long long)block, allocdesc[btype]);
+ errors_found++;
if(query(sdp, "Okay to mark it as 'data'? "
"(y/n)")) {
+ errors_corrected++;
fs_set_bitmap(sdp, block, GFS_BLKST_USED);
log_err("The block was reassigned as "
"journaled data.\n");
@@ -324,6 +328,7 @@ static int ask_remove_inode_eattr(struct fsck_inode *ip,
{
log_err("Inode %lld has unrecoverable Extended Attribute "
"errors.\n", (unsigned long long)ip->i_di.di_num.no_addr);
+ errors_found++;
if (query(ip->i_sbd, "Clear all Extended Attributes from the "
"inode? (y/n) ")) {
struct block_query q;
@@ -332,9 +337,10 @@ static int ask_remove_inode_eattr(struct fsck_inode *ip,
stack;
return -1;
}
- if (!remove_inode_eattr(ip, bc, q.dup_block))
+ if (!remove_inode_eattr(ip, bc, q.dup_block)) {
+ errors_corrected++;
log_err("Extended attributes were removed.\n");
- else
+ } else
log_err("Unable to remove inode eattr pointer; "
"the error remains.\n");
} else {
@@ -360,6 +366,7 @@ static int clear_eas(struct fsck_inode *ip, struct block_count *bc,
log_err("Inode #%" PRIu64 " (0x%" PRIx64 "): %s",
ip->i_di.di_num.no_addr, ip->i_di.di_num.no_addr, emsg);
log_err(" at block #%" PRIu64 ".\n", block);
+ errors_found++;
if (query(sdp, "Clear the bad Extended Attribute? (y/n) ")) {
if (block == ip->i_di.di_eattr) {
remove_inode_eattr(ip, bc, duplicate);
@@ -370,6 +377,7 @@ static int clear_eas(struct fsck_inode *ip, struct block_count *bc,
log_err("The bad Extended Attribute was "
"removed.\n");
}
+ errors_corrected++;
return 1;
} else {
log_err("The bad Extended Attribute was not fixed.\n");
@@ -460,10 +468,12 @@ static int finish_eattr_indir(struct fsck_inode *ip, int leaf_pointers,
log_err("Inode %lld has recoverable indirect "
"Extended Attribute errors.\n",
(unsigned long long)ip->i_di.di_num.no_addr);
+ errors_found++;
if (query(ip->i_sbd, "Okay to fix the block count for the inode? "
"(y/n) ")) {
ip->i_di.di_blocks = 1 + bc->indir_count +
bc->data_count + bc->ea_count;
+ errors_corrected++;
log_err("Block count fixed.\n");
return 1;
}
@@ -747,12 +757,14 @@ static int handle_di(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfr
goto success;
} else {
log_err("Found unused inode marked in-use\n");
+ errors_found++;
if(query(sdp, "Clear unused inode at block %"
PRIu64"? (y/n) ", block)) {
if(block_set(sdp->bl, block, meta_inval)) {
stack;
goto fail;
}
+ errors_corrected++;
goto success;
} else {
log_err("Unused inode still marked in-use\n");
@@ -774,6 +786,7 @@ static int handle_di(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfr
"Found %"PRIu64", "
"Expected %"PRIu64"\n",
ip->i_di.di_num.no_addr, block);
+ errors_found++;
if(query(sdp, "Fix address in inode at block %"
PRIu64"? (y/n) ", block)) {
ip->i_di.di_num.no_addr =
@@ -783,6 +796,7 @@ static int handle_di(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfr
log_crit("Bad dinode address can not be reset.\n");
goto fail;
} else {
+ errors_corrected++;
log_err("Bad dinode address reset.\n");
}
} else {
@@ -938,6 +952,7 @@ static int handle_di(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfr
"%lld + data: %lld + ea: %lld\n",
ip->i_di.di_blocks, bc.indir_count, bc.data_count,
bc.ea_count);
+ errors_found++;
if(query(sdp, "Fix ondisk block count? (y/n) ")) {
ip->i_di.di_blocks = 1 + bc.indir_count +
bc.data_count + bc.ea_count;
@@ -951,7 +966,8 @@ static int handle_di(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfr
stack;
log_crit("Bad block count remains\n");
} else {
- log_warn("Bad block count fixed\n");
+ errors_corrected++;
+ log_err("Bad block count fixed\n");
}
relse_buf(sdp, di_bh);
}
@@ -975,12 +991,14 @@ static int handle_di(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfr
static int scan_meta(struct fsck_sb *sdp, osi_buf_t *bh, uint64_t block, int mfree)
{
if (check_meta(bh, 0)) {
+ errors_found++;
log_err("Found invalid metadata block at %"PRIu64"\n", block);
if(block_set(sdp->bl, block, meta_inval)) {
stack;
return -1;
}
if(query(sdp, "Okay to free the invalid block? (y/n)")) {
+ errors_corrected++;
fs_set_bitmap(sdp, block, GFS_BLKST_FREE);
log_err("The invalid block was freed.\n");
} else {
@@ -1044,7 +1062,7 @@ int pass1(struct fsck_sb *sbp)
j++) {
if(block_set(sbp->bl, j, journal_blk)) {
stack;
- return -1;
+ return FSCK_ERROR;
}
}
}
@@ -1067,7 +1085,7 @@ int pass1(struct fsck_sb *sbp)
rgd = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
if(fs_rgrp_read(rgd, FALSE)){
stack;
- return -1;
+ return FSCK_ERROR;
}
log_debug("RG at %"PRIu64" is %u long\n", rgd->rd_ri.ri_addr,
rgd->rd_ri.ri_length);
@@ -1075,7 +1093,7 @@ int pass1(struct fsck_sb *sbp)
if(block_set(sbp->bl, rgd->rd_ri.ri_addr + i,
meta_other)){
stack;
- return -1;
+ return FSCK_ERROR;
}
}
@@ -1089,7 +1107,7 @@ int pass1(struct fsck_sb *sbp)
break;
warm_fuzzy_stuff(block);
if (fsck_abort) /* if asked to abort */
- return 0;
+ return FSCK_OK;
if (skip_this_pass) {
printf("Skipping pass 1 is not a good idea.\n");
skip_this_pass = FALSE;
@@ -1100,14 +1118,14 @@ int pass1(struct fsck_sb *sbp)
log_crit("Unable to retrieve block %"PRIu64
"\n", block);
fs_rgrp_relse(rgd);
- return -1;
+ return FSCK_ERROR;
}
if(scan_meta(sbp, bh, block, mfree)) {
stack;
relse_buf(sbp, bh);
fs_rgrp_relse(rgd);
- return -1;
+ return FSCK_ERROR;
}
relse_buf(sbp, bh);
first = 0;
@@ -1115,5 +1133,5 @@ int pass1(struct fsck_sb *sbp)
fs_rgrp_relse(rgd);
}
- return 0;
+ return FSCK_OK;
}
diff --git a/gfs/gfs_fsck/pass1b.c b/gfs/gfs_fsck/pass1b.c
index f00148b..9a348ed 100644
--- a/gfs/gfs_fsck/pass1b.c
+++ b/gfs/gfs_fsck/pass1b.c
@@ -435,7 +435,9 @@ static int handle_dup_blk(struct fsck_sb *sbp, struct blocks *b)
"data block %"PRIu64", but "
"the block is really metadata.\n",
id->name, id->block_no, b->block_no);
+ errors_found++;
if (query(sbp, "Clear the inode? (y/n) ")) {
+ errors_corrected++;
log_warn("Clearing inode %lld...\n",
id->block_no);
load_inode(sbp, id->block_no, &ip);
@@ -465,12 +467,14 @@ static int handle_dup_blk(struct fsck_sb *sbp, struct blocks *b)
}
osi_list_foreach(tmp, &b->ref_inode_list) {
id = osi_list_entry(tmp, struct inode_with_dups, list);
+ errors_found++;
if (!query(sbp, "Okay to clear inode %lld? (y/n) ",
id->block_no)) {
log_warn("The inode %lld was not cleared...\n",
id->block_no);
continue;
}
+ errors_corrected++;
log_warn("Clearing inode %lld...\n", id->block_no);
load_inode(sbp, id->block_no, &ip);
dh.b = b;
@@ -506,7 +510,7 @@ int pass1b(struct fsck_sb *sbp)
struct block_query q;
osi_list_t *tmp = NULL, *x;
struct metawalk_fxns find_dirents = {0};
- int rc = 0;
+ int rc = FSCK_OK;
find_dirents.check_dentry = &find_dentry;
@@ -518,7 +522,7 @@ int pass1b(struct fsck_sb *sbp)
/* If there were no dups in the bitmap, we don't need to do anymore */
if(osi_list_empty(&sbp->dup_list)) {
log_info("No duplicate blocks found\n");
- return 0;
+ return FSCK_OK;
}
/* Rescan the fs looking for pointers to blocks that are in
@@ -532,7 +536,7 @@ int pass1b(struct fsck_sb *sbp)
log_debug("Scanning block %"PRIu64" for inodes\n", i);
if(block_check(sbp->bl, i, &q)) {
stack;
- rc = -1;
+ rc = FSCK_ERROR;
goto out;
}
if((q.block_type == inode_dir) ||
@@ -546,7 +550,7 @@ int pass1b(struct fsck_sb *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/gfs/gfs_fsck/pass1c.c b/gfs/gfs_fsck/pass1c.c
index a0d18a5..6bec08d 100644
--- a/gfs/gfs_fsck/pass1c.c
+++ b/gfs/gfs_fsck/pass1c.c
@@ -47,6 +47,7 @@ static int ask_remove_eattr_entry(struct fsck_sb *sdp, osi_buf_t *leaf_bh,
struct gfs_ea_header *prev,
int fix_curr, int fix_curr_len)
{
+ errors_found++;
if (query(sdp, "Remove the bad Extended Attribute? (y/n) ")) {
if (fix_curr)
curr->ea_flags |= GFS_EAFLAG_LAST;
@@ -60,6 +61,7 @@ static int ask_remove_eattr_entry(struct fsck_sb *sdp, osi_buf_t *leaf_bh,
stack;
return -1;
}
+ errors_corrected++;
} else {
log_err("Bad Extended Attribute not removed.\n");
}
@@ -68,13 +70,16 @@ static int ask_remove_eattr_entry(struct fsck_sb *sdp, osi_buf_t *leaf_bh,
static int ask_remove_eattr(struct fsck_inode *ip)
{
+ errors_found++;
if (query(ip->i_sbd, "Remove the bad Extended Attribute? (y/n) ")) {
ip->i_di.di_eattr = 0;
if (fs_copyout_dinode(ip))
log_err("Bad Extended Attribute could not be "
"removed.\n");
- else
+ else {
+ errors_corrected++;
log_err("Bad Extended Attribute removed.\n");
+ }
} else
log_err("Bad Extended Attribute not removed.\n");
return 1;
@@ -263,15 +268,15 @@ int pass1c(struct fsck_sb *sbp)
while (!find_next_block_type(sbp->bl, eattr_block, &block_no)) {
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return 0;
+ return FSCK_OK;
log_info("EA in inode %"PRIu64"\n", block_no);
if(get_and_read_buf(sbp, block_no, &bh, 0)) {
stack;
- return -1;
+ return FSCK_ERROR;
}
if(copyin_inode(sbp, bh, &ip)) {
stack;
- return -1;
+ return FSCK_ERROR;
}
block_unmark(sbp->bl, block_no, eattr_block);
@@ -280,7 +285,7 @@ int pass1c(struct fsck_sb *sbp)
error = check_inode_eattr(ip, &pass1c_fxns);
if(error < 0) {
stack;
- return -1;
+ return FSCK_ERROR;
}
if(update) {
@@ -293,5 +298,5 @@ int pass1c(struct fsck_sb *sbp)
block_no++;
}
- return 0;
+ return FSCK_OK;
}
diff --git a/gfs/gfs_fsck/pass2.c b/gfs/gfs_fsck/pass2.c
index 8615e5c..b6845cf 100644
--- a/gfs/gfs_fsck/pass2.c
+++ b/gfs/gfs_fsck/pass2.c
@@ -236,11 +236,14 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
if(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(ip->i_sbd, "Clear directory entry tp out of range block? (y/n) ")) {
log_err("Clearing %s\n", tmp_name);
if(dirent_del(ip, bh, prev_de, dent))
log_err("Error encountered while removing bad "
"directory entry. Skipping.\n");
+ else
+ errors_corrected++;
*update = 1;
return 1;
} else {
@@ -262,8 +265,10 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
log_err("Found a bad directory entry: %s at block %lld.\n",
filename, de->de_inum.no_addr);
+ errors_found++;
if(query(sbp, "Delete the inode containing bad blocks? "
"(y/n)")) {
+ errors_corrected++;
if (!load_inode(sbp, de->de_inum.no_addr, &entry_ip)) {
check_inode_eattr(entry_ip,
&pass2_fxns_delete);
@@ -294,6 +299,7 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
q.block_type, q.block_type == meta_inval ?
"previously marked invalid" : "is not an inode");
+ errors_found++;
if(query(sbp, "Clear directory entry to non-inode block? "
"(y/n) ")) {
osi_buf_t *bhi;
@@ -303,6 +309,7 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
"directory entry. Skipping.\n");
return -1;
}
+ errors_corrected++;
*update = 1;
log_warn("Directory entry '%s' cleared\n", tmp_name);
@@ -344,6 +351,7 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
log_warn("Type in dir entry (%s, %"PRIu64") conflicts with "
"type in dinode. (Dir entry is stale.)\n",
tmp_name, de->de_inum.no_addr);
+ errors_found++;
if(query(sbp, "Clear stale directory entry? (y/n) ")) {
load_inode(sbp, de->de_inum.no_addr, &entry_ip);
check_inode_eattr(entry_ip, &clear_eattrs);
@@ -352,8 +360,11 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
if(dirent_del(ip, bh, prev_de, dent))
log_err("Error encountered while removing bad "
"directory entry. Skipping.\n");
- *update = 1;
- log_err("Stale directory entry deleted\n");
+ else {
+ errors_corrected++;
+ *update = 1;
+ log_err("Stale directory entry deleted\n");
+ }
return 1;
} else {
log_err("Stale directory entry remains\n");
@@ -368,8 +379,10 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
if(ds->dotdir) {
log_err("already found '.' entry\n");
+ errors_found++;
if(query(sbp, "Clear duplicate '.' entry? (y/n) ")) {
+ errors_corrected++;
load_inode(sbp, de->de_inum.no_addr, &entry_ip);
check_inode_eattr(entry_ip, &clear_eattrs);
free_inode(&entry_ip);
@@ -400,7 +413,9 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
PRIu64".\n",
de->de_inum.no_addr,
ip->i_num.no_addr);
+ errors_found++;
if(query(sbp, "remove '.' reference? (y/n) ")) {
+ errors_corrected++;
load_inode(sbp, de->de_inum.no_addr, &entry_ip);
check_inode_eattr(entry_ip, &clear_eattrs);
free_inode(&entry_ip);
@@ -431,8 +446,10 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
log_debug("Found .. dentry\n");
if(ds->dotdotdir) {
log_err("already found '..' entry\n");
+ errors_found++;
if(query(sbp, "Clear duplicate '..' entry? (y/n) ")) {
+ errors_corrected++;
load_inode(sbp, de->de_inum.no_addr, &entry_ip);
check_inode_eattr(entry_ip, &clear_eattrs);
free_inode(&entry_ip);
@@ -455,7 +472,9 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
if(q.block_type != inode_dir) {
log_err("Found '..' entry pointing to"
" something that's not a directory");
+ errors_found++;
if(query(sbp, "Clear bad '..' directory entry? (y/n) ")) {
+ errors_corrected++;
load_inode(sbp, de->de_inum.no_addr, &entry_ip);
check_inode_eattr(entry_ip, &clear_eattrs);
free_inode(&entry_ip);
@@ -507,7 +526,9 @@ static int check_dentry(struct fsck_inode *ip, struct gfs_dirent *dent,
if(error > 0) {
log_err("Hard link to block %"PRIu64" detected.\n", filename, entryblock);
+ errors_found++;
if(query(sbp, "Clear hard link to directory? (y/n) ")) {
+ errors_corrected++;
*update = 1;
dirent_del(ip, bh, prev_de, dent);
@@ -637,11 +658,13 @@ static int check_root_dir(struct fsck_sb *sbp)
if(ds.q.block_type != inode_dir) {
log_err("Block %"PRIu64" marked as root inode in"
" superblock not a directory\n", rootblock);
+ errors_found++;
if(query(sbp, "Create new root inode? (y/n) ")) {
if(build_rooti(sbp)) {
stack;
return -1;
}
+ errors_corrected++;
} else {
log_err("Cannot continue without valid root inode\n");
return -1;
@@ -694,6 +717,7 @@ static int check_root_dir(struct fsck_sb *sbp)
if(!ds.dotdir) {
log_err("No '.' entry found\n");
+ errors_found++;
if (query(sbp, "Is it okay to add '.' entry? (y/n) ")) {
sprintf(tmp_name, ".");
filename.len = strlen(tmp_name); /* no trailing NULL */
@@ -717,6 +741,7 @@ static int check_root_dir(struct fsck_sb *sbp)
"directory.\n");
return -1;
}
+ errors_corrected++;
increment_link(ip->i_sbd, ip->i_num.no_addr);
ds.entry_count++;
free(filename.name);
@@ -741,10 +766,12 @@ static int check_root_dir(struct fsck_sb *sbp)
if(ip->i_di.di_entries != ds.entry_count) {
log_err("Entries is %d - should be %d for %"PRIu64"\n",
ip->i_di.di_entries, ds.entry_count, ip->i_di.di_num.no_addr);
+ errors_found++;
if(query(sbp, "Fix entries for %"PRIu64"? (y/n) ",
ip->i_di.di_num.no_addr)) {
ip->i_di.di_entries = ds.entry_count;
- log_warn("Entries updated\n");
+ log_err("Entries updated\n");
+ errors_corrected++;
update = 1;
} else {
log_err("Entries for %"PRIu64" left out of sync\n",
@@ -787,7 +814,7 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
if(check_root_dir(sbp)) {
stack;
- return -1;
+ return FSCK_ERROR;
}
log_info("Checking directory inodes.\n");
@@ -796,7 +823,7 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
need_update = 0;
warm_fuzzy_stuff(i);
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return 0;
+ return FSCK_OK;
/* Skip the root inode - it's checked above */
if(i == sbp->sb.sb_root_di.no_addr)
@@ -805,7 +832,7 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
if(block_check(sbp->bl, i, &q)) {
log_err("Can't get block %"PRIu64 " from block list\n",
i);
- return -1;
+ return FSCK_ERROR;
}
if(q.block_type != inode_dir)
@@ -823,24 +850,25 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
if(check_metatree(ip, &pass2_fxns)) {
stack;
free_inode(&ip);
- return -1;
+ return FSCK_ERROR;
}
free_inode(&ip);
}
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(sbp, "Remove directory entry for bad"
" inode %"PRIu64" in %"PRIu64
"? (y/n)", i, di->treewalk_parent)) {
@@ -849,13 +877,14 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
i);
if(error < 0) {
stack;
- return -1;
+ return FSCK_ERROR;
}
if(error > 0) {
log_warn("Unable to find dentry for %"
PRIu64" in %"PRIu64"\n",
i, di->treewalk_parent);
}
+ errors_corrected++;
log_warn("Directory entry removed\n");
} else {
log_err("Directory entry to invalid inode remains\n");
@@ -869,18 +898,19 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
log_err("Unable to retrieve block #%"PRIu64
" for directory\n",
i);
- return -1;
+ return FSCK_ERROR;
}
if(copyin_inode(sbp, bh, &ip)) {
stack;
relse_buf(sbp, bh);
- return -1;
+ return FSCK_ERROR;
}
if(!ds.dotdir) {
log_err("No '.' entry found for directory inode at "
"block %" PRIu64 "\n", i);
+ errors_found++;
if (query(sbp,
"Is it okay to add '.' entry? (y/n) ")) {
sprintf(tmp_name, ".");
@@ -890,13 +920,13 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
filename.len))) {
log_err("Unable to allocate name\n");
stack;
- return -1;
+ return FSCK_ERROR;
}
if(!memset(filename.name, 0, sizeof(char) *
filename.len)) {
log_err("Unable to zero name\n");
stack;
- return -1;
+ return FSCK_ERROR;
}
memcpy(filename.name, tmp_name, filename.len);
@@ -904,8 +934,9 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
ip->i_di.di_type)){
log_err("Failed to link \".\" entry "
"to directory.\n");
- return -1;
+ return FSCK_ERROR;
}
+ errors_corrected++;
increment_link(ip->i_sbd, ip->i_num.no_addr);
ds.entry_count++;
free(filename.name);
@@ -921,7 +952,9 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
"block %" PRIu64 "\n",
ip->i_di.di_entries, ds.entry_count,
ip->i_di.di_num.no_addr);
+ errors_found++;
if (query(sbp, "Fix the entry count? (y/n) ")) {
+ errors_corrected++;
ip->i_di.di_entries = ds.entry_count;
need_update = 1;
} else {
@@ -935,7 +968,7 @@ int pass2(struct fsck_sb *sbp, struct options *opts)
relse_buf(sbp, bh);
}
}
- return 0;
+ return FSCK_OK;
}
diff --git a/gfs/gfs_fsck/pass3.c b/gfs/gfs_fsck/pass3.c
index 15eded1..0fafa18 100644
--- a/gfs/gfs_fsck/pass3.c
+++ b/gfs/gfs_fsck/pass3.c
@@ -127,6 +127,7 @@ static struct dir_info *mark_and_return_parent(struct fsck_sb *sbp,
"is bad - reattaching to l+f");
/* FIXME: add a dinode for this entry instead? */
+ errors_found++;
if(query(sbp, "Remove directory entry for bad"
" inode %"PRIu64" in %"PRIu64
"? (y/n)", di->dinode,
@@ -143,6 +144,7 @@ static struct dir_info *mark_and_return_parent(struct fsck_sb *sbp,
PRIu64" in %"PRIu64"\n",
di->dinode, di->treewalk_parent);
}
+ errors_corrected++;
log_warn("Directory entry removed\n");
} else {
log_err("Directory entry to invalid inode remains\n");
@@ -212,20 +214,22 @@ int pass3(struct fsck_sb *sbp, struct options *opts)
* 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(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(sbp, "Clear unlinked directory with bad blocks? (y/n) ")) {
block_set(sbp->bl, di->dinode, block_free);
+ errors_corrected++;
break;
} else {
log_err("Unlinked directory with bad blocks remains\n");
@@ -250,7 +254,9 @@ int pass3(struct fsck_sb *sbp, struct options *opts)
* 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(sbp, "Remove zero-size unlinked directory? (y/n) ")) {
+ errors_corrected++;
block_set(sbp->bl, di->dinode, block_free);
free_inode(&ip);
break;
@@ -258,11 +264,13 @@ int pass3(struct fsck_sb *sbp, struct options *opts)
log_err("Zero-size unlinked directory remains\n");
}
}
+ errors_found++;
if(query(sbp, "Add unlinked directory to l+f? (y/n) ")) {
+ errors_corrected++;
if(add_inode_to_lf(ip)) {
stack;
free_inode(&ip);
- return -1;
+ return FSCK_ERROR;
}
log_warn("Directory relinked to l+f\n");
} else {
@@ -282,5 +290,5 @@ int pass3(struct fsck_sb *sbp, struct options *opts)
if(sbp->lf_dip)
log_debug("At end of pass3, l+f entries is %u\n",
sbp->lf_dip->i_di.di_entries);
- return 0;
+ return FSCK_OK;
}
diff --git a/gfs/gfs_fsck/pass4.c b/gfs/gfs_fsck/pass4.c
index 6448adc..be900ec 100644
--- a/gfs/gfs_fsck/pass4.c
+++ b/gfs/gfs_fsck/pass4.c
@@ -62,7 +62,7 @@ static int scan_inode_list(struct fsck_sb *sbp, osi_list_t *list) {
return 0;
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);
}
/* Don't check reference counts on the special gfs files */
if((ii->inode == sbp->sb.sb_rindex_di.no_addr) ||
@@ -83,8 +83,10 @@ static int scan_inode_list(struct fsck_sb *sbp, osi_list_t *list) {
log_err("Unlinked inode contains"
"bad blocks\n",
ii->inode);
+ errors_found++;
if(query(sbp, "Delete unlinked inode with bad "
"blocks? (y/n) ")) {
+ errors_corrected++;
load_inode(sbp, ii->inode, &ip);
check_inode_eattr(ip,
&pass4_fxns_delete);
@@ -92,6 +94,7 @@ static int scan_inode_list(struct fsck_sb *sbp, osi_list_t *list) {
free_inode(&ip);
block_set(sbp->bl, ii->inode,
block_free);
+ log_err("Unlinked inode with bad blocks cleared\n");
continue;
} else
log_err("Unlinked inode with bad blocks not cleared\n");
@@ -105,8 +108,10 @@ static int scan_inode_list(struct fsck_sb *sbp, osi_list_t *list) {
q.block_type != inode_sock) {
log_err("Unlinked block marked as an inode is "
"not an inode (%d)\n", q.block_type);
+ errors_found++;
if(query(sbp, "Delete unlinked inode"
"? (y/n) ")) {
+ errors_corrected++;
if (!load_inode(sbp, ii->inode, &ip)) {
check_inode_eattr(ip,
&pass4_fxns_delete);
@@ -131,22 +136,32 @@ static int scan_inode_list(struct fsck_sb *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(sbp, "Clear zero-size unlinked inode? (y/n) ")) {
+ errors_corrected++;
block_set(sbp->bl, ii->inode, block_free);
free_inode(&ip);
+ log_err("Unlinked inode with zero size cleared\n");
continue;
- }
+ } else
+ log_err("Unlinked inode with zero size"
+ " not cleared\n");
}
+ errors_found++;
if(query(sbp, "Add unlinked inode to l+f? (y/n)")) {
if(add_inode_to_lf(ip)) {
stack;
free_inode(&ip);
+ log_err("Unable to unlinked inode to "
+ "l+f\n");
return -1;
- }
- else {
+ } else {
fix_inode_count(sbp, ii, ip);
lf_addition = 1;
+ errors_corrected++;
+ log_err("Unlinked inode added to "
+ "l+f\n");
}
} else
log_err("Unlinked inode left unlinked\n");
@@ -158,8 +173,10 @@ static int scan_inode_list(struct fsck_sb *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(sbp, "Update link count for inode %"
PRIu64"? (y/n) ", ii->inode)) {
+ errors_corrected++;
load_inode(sbp, ii->inode, &ip);
fix_inode_count(sbp, ii, ip);
free_inode(&ip);
@@ -206,16 +223,16 @@ int pass4(struct fsck_sb *sbp, struct options *opts)
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 = &sbp->inode_hash[i];
if(scan_inode_list(sbp, list)) {
stack;
- return -1;
+ return FSCK_ERROR;
}
}
if(sbp->lf_dip)
log_debug("At end of pass4, l+f entries is %u\n",
sbp->lf_dip->i_di.di_entries);
- return 0;
+ return FSCK_OK;
}
diff --git a/gfs/gfs_fsck/pass5.c b/gfs/gfs_fsck/pass5.c
index e534f32..1d4db05 100644
--- a/gfs/gfs_fsck/pass5.c
+++ b/gfs/gfs_fsck/pass5.c
@@ -215,6 +215,7 @@ static int check_block_status(struct fsck_sb *sbp, char *buffer, unsigned int bu
rg_status, block_status, q.block_type);
if((rg_status == GFS_BLKST_FREEMETA) &&
(block_status == GFS_BLKST_FREE)) {
+ errors_found++;
log_info("Converting free metadata block at %"
PRIu64" to a free data block\n", block);
if(!sbp->opts->no) {
@@ -226,7 +227,8 @@ static int check_block_status(struct fsck_sb *sbp, char *buffer, unsigned int bu
block);
}
else {
- log_info("Succeeded.\n");
+ log_err("Succeeded.\n");
+ errors_corrected++;
}
}
}
@@ -246,12 +248,15 @@ static int check_block_status(struct fsck_sb *sbp, char *buffer, unsigned int bu
q.block_type,
block_type_string(&q));
+ errors_found++;
if(query(sbp, "Fix bitmap for block %"
PRIu64"? (y/n) ", block)) {
if(fs_set_bitmap(sbp, block, block_status))
log_err("Failed.\n");
- else
+ else {
log_err("Succeeded.\n");
+ errors_corrected++;
+ }
} else
log_err("Bitmap at block %"PRIu64
" left inconsistent\n", block);
@@ -348,8 +353,10 @@ static int update_rgrp(struct fsck_rgrp *rgp, uint32_t *count, int rgcount)
rgp->rd_rg.rg_freemeta = count[4];
}
+ errors_found++;
if(query(rgp->rd_sbd,
"Update resource group counts? (y/n) ")) {
+ errors_corrected++;
log_warn("Resource group counts updated\n");
/* write out the rgrp */
gfs_rgrp_out(&rgp->rd_rg, BH_DATA(rgp->rd_bh[0]));
@@ -378,14 +385,14 @@ int pass5(struct fsck_sb *sbp, struct options *opts)
/* Reconcile RG bitmaps with fsck bitmap */
for(tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next){
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
- return 0;
+ return FSCK_OK;
log_info("Updating Resource Group %"PRIu64"\n", rg_count);
memset(count, 0, sizeof(*count) * 5);
rgp = osi_list_entry(tmp, struct fsck_rgrp, rd_list);
if(fs_rgrp_read(rgp, FALSE)){
stack;
- return -1;
+ return FSCK_ERROR;
}
/* Compare the bitmaps and report the differences */
update_rgrp(rgp, count, rg_count);
@@ -396,5 +403,5 @@ int pass5(struct fsck_sb *sbp, struct options *opts)
* anything to do here... */
- return 0;
+ return FSCK_OK;
}
diff --git a/gfs/gfs_fsck/rgrp.c b/gfs/gfs_fsck/rgrp.c
index e432aa9..101e6e6 100644
--- a/gfs/gfs_fsck/rgrp.c
+++ b/gfs/gfs_fsck/rgrp.c
@@ -176,7 +176,7 @@ int fs_rgrp_read(struct fsck_rgrp *rgd, int repair_if_corrupted)
for (x = 0; x < length; x++){
if(rgd->rd_bh[x]){
log_err("Programmer error! Bitmaps are already present in rgrp.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
error = get_and_read_buf(sdp, rgd->rd_ri.ri_addr + x,
&(rgd->rd_bh[x]), 0);
@@ -191,6 +191,7 @@ int fs_rgrp_read(struct fsck_rgrp *rgd, int repair_if_corrupted)
BH_BLKNO(rgd->rd_bh[x]), BH_BLKNO(rgd->rd_bh[x]),
(int)x+1, (int)length);
if (repair_if_corrupted) {
+ errors_found++;
if (query(sdp, "Fix the RG? (y/n)")) {
log_err("Attempting to repair the RG.\n");
if (x) {
@@ -217,6 +218,7 @@ int fs_rgrp_read(struct fsck_rgrp *rgd, int repair_if_corrupted)
BH_DATA(rgd->rd_bh[x]));
}
write_buf(sdp, rgd->rd_bh[x], BW_WAIT);
+ errors_corrected++;
}
}
else {
diff --git a/gfs/gfs_fsck/super.c b/gfs/gfs_fsck/super.c
index dc2b019..d5f5a58 100644
--- a/gfs/gfs_fsck/super.c
+++ b/gfs/gfs_fsck/super.c
@@ -1304,6 +1304,7 @@ int ri_update(struct fsck_sb *sdp)
ri_bitbytes, PRIx32);
/* If we modified the index, write it back to disk. */
if (rgindex_modified) {
+ errors_found++;
if(query(sdp, "Fix the index? (y/n)")) {
gfs_rindex_out(&rgd->rd_ri, (char *)&buf);
error = writei(sdp->riinode, (char *)&buf,
@@ -1313,6 +1314,8 @@ int ri_update(struct fsck_sb *sdp)
log_err("Unable to fix resource group index %u.\n",
rg + 1);
goto fail;
+ } else {
+ errors_corrected++;
}
}
else
@@ -1325,8 +1328,11 @@ int ri_update(struct fsck_sb *sdp)
if (rgd->rd_ri.ri_data == (uint32_t)-4) {
if (!fix_grow_problems) {
log_err("A problem with the rindex file caused by gfs_grow was detected.\n");
- if(query(sdp, "Fix the rindex problem? (y/n)"))
+ errors_found++;
+ if(query(sdp, "Fix the rindex problem? (y/n)")) {
+ errors_corrected++;
fix_grow_problems = 1;
+ }
}
/* Keep a counter in case we hit it more than once. */
grow_problems++;
diff --git a/gfs/gfs_fsck/util.c b/gfs/gfs_fsck/util.c
index 03a42fc..e81bc31 100644
--- a/gfs/gfs_fsck/util.c
+++ b/gfs/gfs_fsck/util.c
@@ -154,7 +154,7 @@ int next_rg_meta(struct fsck_rgrp *rgd, uint64 *block, int first)
if(!first && (*block < rgd->rd_ri.ri_data1)){
log_err("next_rg_meta: Start block is outside rgrp bounds.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
for(i=0; i < length; i++){
@@ -207,7 +207,7 @@ int next_rg_meta_free(struct fsck_rgrp *rgd, uint64 *block, int first, int *mfre
if(!first && (*block < rgd->rd_ri.ri_data1)){
log_err("next_rg_meta: Start block is outside rgrp bounds.\n");
- exit(1);
+ exit(FSCK_ERROR);
}
for(i=0; i < length; i++){
@@ -271,13 +271,13 @@ int next_rg_metatype(struct fsck_rgrp *rgd, uint64 *block, uint32 type, int firs
if(get_and_read_buf(sdp, *block, &bh, 0)){
log_err("next_rg_metatype: Unable to read meta block "
"#%"PRIu64" from disk\n", *block);
- exit(1);
+ exit(FSCK_ERROR);
}
if(check_meta(bh,0)){
log_err("next_rg_metatype: next_rg_meta returned block #%"PRIu64",\n"
" which is not a valid meta block.\n", *block);
- exit(1);
+ exit(FSCK_ERROR);
}
first = 0;
More information about the cluster-commits
mailing list