cluster: RHEL6 - fsck.gfs2: Make output messages more sensible
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 94431db3595d647c196e2b518065ddc2b02cae38
Parent: 5a677ee1d50a8545b72113d1873bbc78898d8531
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 12:36:04 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2: Make output messages more sensible
This patch changes several fsck output messages so that they make more
sense. Digging through very big and complex fsck.gfs2 output, I found
myself lost in many occasions. This patch makes it a lot easier to see
what decisions are made by fsck.gfs2 and why.
rhbz#675723
---
gfs2/fsck/initialize.c | 21 +++++++++++++++------
gfs2/fsck/metawalk.c | 2 +-
gfs2/fsck/pass1.c | 4 ++++
gfs2/fsck/pass1b.c | 5 +++--
gfs2/fsck/pass2.c | 18 ++++++++++++++----
gfs2/fsck/pass5.c | 21 +++++++++++++--------
gfs2/fsck/util.c | 3 ++-
7 files changed, 52 insertions(+), 22 deletions(-)
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 08da24f..d7586de 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -460,14 +460,14 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
uint64_t addl_mem_needed;
const char *level_desc[] = {
_("Checking if all rgrp and rindex values are good"),
- _("Checking if rindex values are ascending and evenly spaced"),
+ _("Checking if rindex values may be easily repaired"),
_("Calculating where the rgrps should be if evenly spaced"),
_("Trying to rebuild rindex assuming evenly spaced rgrps"),
_("Trying to rebuild rindex assuming unevenly spaced rgrps"),
};
const char *fail_desc[] = {
_("Some damage was found; we need to take remedial measures"),
- _("rindex is unevenly spaced: converted from gfs1 or corrupt"),
+ _("rindex is unevenly spaced: either gfs1-style or corrupt"),
_("rindex calculations don't match: uneven rgrp boundaries"),
_("Too many rgrp misses: rgrps must be unevenly spaced"),
_("Too much damage found: we cannot rebuild this rindex"),
@@ -513,16 +513,25 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
*******************************************************************/
log_warn( _("Validating Resource Group index.\n"));
for (trust_lvl = blind_faith; trust_lvl <= indignation; trust_lvl++) {
+ int ret;
+
log_warn( _("Level %d rgrp check: %s.\n"), trust_lvl + 1,
level_desc[trust_lvl]);
if ((rg_repair(sdp, trust_lvl, &rgcount, &sane) == 0) &&
- (ri_update(sdp, 0, &rgcount, &sane) == 0)) {
+ ((ret = ri_update(sdp, 0, &rgcount, &sane)) == 0)) {
log_warn( _("(level %d passed)\n"), trust_lvl + 1);
break;
+ } else {
+ if (ret < 0)
+ log_err( _("(level %d failed: %s)\n"),
+ trust_lvl + 1, fail_desc[trust_lvl]);
+ else
+ log_err( _("(level %d failed at block %lld "
+ "(0x%llx): %s)\n"), trust_lvl + 1,
+ (unsigned long long)ret,
+ (unsigned long long)ret,
+ fail_desc[trust_lvl]);
}
- else
- log_err( _("(level %d failed: %s)\n"), trust_lvl + 1,
- fail_desc[trust_lvl]);
if (fsck_abort)
break;
}
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index af27432..92973ae 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -336,7 +336,7 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
de.de_name_len ||
(de.de_inum.no_formal_ino && !de.de_name_len && !first)) {
log_err( _("Directory block %llu (0x%llx"
- "), entry %d of directory %llu"
+ "), entry %d of directory %llu "
"(0x%llx) is corrupt.\n"),
(unsigned long long)bh->b_blocknr,
(unsigned long long)bh->b_blocknr,
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index a1f4232..7077272 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1213,6 +1213,10 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip)
words, we would introduce file system corruption. So we
need to keep track of the fact that it's invalid and
skip parts that we can't be sure of based on dinode type. */
+ log_debug("Invalid mode dinode found at block %lld (0x%llx): "
+ "Invalidating all its metadata.\n",
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
check_metatree(ip, &invalidate_fxns);
if (fsck_blockmap_set(ip, block, _("invalid mode"),
gfs2_inode_invalid))
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index 65e6de9..259eb7a 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -426,7 +426,7 @@ static int clear_a_reference(struct gfs2_sbd *sdp, struct duptree *b,
log_warn( _("The bad inode was not cleared...\n"));
continue;
}
- log_warn( _("Clearing inode %lld (0x%llx)....\n"),
+ log_warn( _("Clearing inode %lld (0x%llx)...\n"),
(unsigned long long)id->block_no,
(unsigned long long)id->block_no);
clear_dup_fxns.private = (void *) dh;
@@ -597,7 +597,8 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *b)
gfs2_meta_eattr);
fsck_inode_put(&ip); /* out, brelse, free */
} else {
- log_debug( _("All duplicate references were resolved.\n"));
+ /* They may have answered no and not fixed all references. */
+ log_debug( _("All duplicate references were processed.\n"));
}
return 0;
}
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index abb77c3..0424241 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -258,7 +258,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
/* This entry's inode has bad blocks in it */
/* Handle bad blocks */
- log_err( _("Found a bad directory entry: %s\n"), tmp_name);
+ log_err( _("Found directory entry '%s' pointing to invalid "
+ "block %lld (0x%llx)\n"), tmp_name,
+ (unsigned long long)entryblock,
+ (unsigned long long)entryblock);
if (!query( _("Delete inode containing bad blocks? (y/n)"))) {
log_warn( _("Entry to inode containing bad blocks remains\n"));
@@ -275,6 +278,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
fsck_inode_put(&entry_ip);
fsck_blockmap_set(ip, entryblock,
_("bad directory entry"), gfs2_block_free);
+ log_err( _("Inode %lld (0x%llx) was deleted.\n"),
+ (unsigned long long)entryblock,
+ (unsigned long long)entryblock);
goto nuke_dentry;
}
if (q < gfs2_inode_dir || q > gfs2_inode_sock) {
@@ -350,7 +356,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
}
if (!strcmp(".", tmp_name)) {
- log_debug( _("Found . dentry\n"));
+ log_debug( _("Found . dentry in directory %lld (0x%llx)\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
if (ds->dotdir) {
log_err( _("Already found '.' entry in directory %llu"
@@ -408,9 +416,11 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
goto dentry_is_valid;
}
if (!strcmp("..", tmp_name)) {
- log_debug( _("Found .. dentry\n"));
+ log_debug( _("Found '..' dentry in directory %lld (0x%llx)\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
if (ds->dotdotdir) {
- log_err( _("Already found '..' entry in directory %llu"
+ log_err( _("Already had a '..' entry in directory %llu"
"(0x%llx)\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index 028515b..b71b2b6 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -83,7 +83,8 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer, unsigned int b
"(0x%llx).\n"),
(unsigned long long)block,
(unsigned long long)block);
- if (query(_("Do you want to fix the bitmap? (y/n) "))) {
+ if (query(_("Do you want to reclaim the block? "
+ "(y/n) "))) {
if (gfs2_set_bitmap(sdp, block, block_status))
log_err(_("Unlinked block %llu "
"(0x%llx) bitmap not fixed."
@@ -104,11 +105,12 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer, unsigned int b
const char *blockstatus[] = {"Free", "Data",
"Unlinked", "inode"};
- log_err( _("Ondisk and fsck bitmaps differ at"
- " block %"PRIu64" (0x%" PRIx64 ") \n"), block, block);
- log_err( _("Ondisk status is %u (%s) but FSCK thinks it should be "),
- rg_status, blockstatus[rg_status]);
- log_err("%u (%s)\n", block_status, blockstatus[block_status]);
+ log_err( _("Block %llu (0x%llx) bitmap says %u (%s) "
+ "but FSCK saw %u (%s)\n"),
+ (unsigned long long)block,
+ (unsigned long long)block, rg_status,
+ blockstatus[rg_status], block_status,
+ blockstatus[block_status]);
if (q) /* Don't print redundant "free" */
log_err( _("Metadata type is %u (%s)\n"), q,
block_type_string(q));
@@ -164,8 +166,11 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_list *rgp,
update = 1;
}
if (rgp->rg.rg_dinodes != count[1]) {
- log_err( _("Inode count inconsistent: is %u should be %u\n"),
- rgp->rg.rg_dinodes, count[1]);
+ log_err( _("RG #%llu (0x%llx) Inode count inconsistent: is "
+ "%u should be %u\n"),
+ (unsigned long long)rgp->ri.ri_addr,
+ (unsigned long long)rgp->ri.ri_addr,
+ rgp->rg.rg_dinodes, count[1]);
rgp->rg.rg_dinodes = count[1];
update = 1;
}
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index b71fc98..9930624 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -286,7 +286,8 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
if (first)
log_info( _("This is the original reference.\n"));
else
- log_info( _("This brings the total to: %d\n"), dt->refs);
+ log_info( _("This brings the total to: %d duplicate "
+ "references\n"), dt->refs);
return 0;
}
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: Shorten output
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 5a677ee1d50a8545b72113d1873bbc78898d8531
Parent: aab0d6535dab2ce48aa20062f7005a7deb4ad773
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 11:38:18 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2: Shorten output
This patch shortens some of the output of fsck.gfs2, thereby making
the output files smaller and more manageable.
rhbz#675723
---
gfs2/fsck/lost_n_found.c | 6 +++---
gfs2/fsck/metawalk.c | 7 ++++---
gfs2/fsck/pass5.c | 13 +++++++------
3 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index 7886625..0de4f8e 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -66,8 +66,8 @@ static void add_dotdot(struct gfs2_inode *ip)
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)di->dotdot_parent);
else
- log_debug(_("Couldn't find a valid \"..\" entry "
- "for orphan directory %lld (0x%llx)\n"),
+ log_debug(_("Couldn't find directory %lld (0x%llx) "
+ "in directory tree.\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
}
@@ -206,7 +206,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){
incr_link_count(lf_dip->i_di.di_num.no_addr,
ip->i_di.di_mode, _("to lost+found"));
- log_notice( _("Added inode #%llu (0x%llx) to lost+found dir\n"),
+ log_notice( _("Added inode #%llu (0x%llx) to lost+found\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
gfs2_dinode_out(&lf_dip->i_di, lf_dip->i_bh);
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 9252aec..af27432 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -45,12 +45,13 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
const char *allocdesc[] = {"free space", "data", "unlinked",
"inode", "reserved"};
- log_err( _("Block %llu (0x%llx) seems to be %s, but is "
- "marked as %s in the bitmap.\n"),
+ /* Keep these messages as short as possible, or the output
+ gets to be huge and unmanageable. */
+ log_err( _("Block %llu (0x%llx) was '%s', should be %s.\n"),
(unsigned long long)blk, (unsigned long long)blk,
allocdesc[new_bitmap_state],
allocdesc[old_bitmap_state]);
- if (query( _("Okay to fix the bitmap? (y/n)"))) {
+ if (query( _("Fix the bitmap? (y/n)"))) {
/* If the new bitmap state is free (and therefore the
old state was not) we have to add to the free
space in the rgrp. If the old bitmap state was
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index 1811e5a..028515b 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -79,8 +79,8 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer, unsigned int b
So we ignore it. */
if (rg_status == GFS2_BLKST_UNLINKED &&
block_status == GFS2_BLKST_FREE) {
- log_err( _("Unlinked inode block found at "
- "block %llu (0x%llx).\n"),
+ log_err( _("Unlinked inode found at block %llu "
+ "(0x%llx).\n"),
(unsigned long long)block,
(unsigned long long)block);
if (query(_("Do you want to fix the bitmap? (y/n) "))) {
@@ -109,16 +109,17 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer, unsigned int b
log_err( _("Ondisk status is %u (%s) but FSCK thinks it should be "),
rg_status, blockstatus[rg_status]);
log_err("%u (%s)\n", block_status, blockstatus[block_status]);
- log_err( _("Metadata type is %u (%s)\n"), q,
- block_type_string(q));
+ if (q) /* Don't print redundant "free" */
+ log_err( _("Metadata type is %u (%s)\n"), q,
+ block_type_string(q));
if (query(_("Fix bitmap for block %llu (0x%llx) ? (y/n) "),
(unsigned long long)block,
(unsigned long long)block)) {
if (gfs2_set_bitmap(sdp, block, block_status))
- log_err( _("Failed.\n"));
+ log_err( _("Repair failed.\n"));
else
- log_err( _("Succeeded.\n"));
+ log_err( _("Fixed.\n"));
} else
log_err( _("Bitmap at block %"PRIu64" (0x%" PRIx64
") left inconsistent\n"), block, block);
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: fsck.gfs2: split check_leaf_blks to be more readable
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: aab0d6535dab2ce48aa20062f7005a7deb4ad773
Parent: 4857f0866b3f5f641300f022fa9d4624ebe3f32a
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 10:08:21 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2: fsck.gfs2: split check_leaf_blks to be more readable
This patch splits function check_leaf_blks into two functions to make it
more understandable. Before, it had way too many levels of indentation and
spanned multiple screens. This makes it a lot more clear.
rhbz#675723
---
gfs2/fsck/metawalk.c | 255 +++++++++++++++++++++++++++-----------------------
1 files changed, 138 insertions(+), 117 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index cf75164..9252aec 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -436,10 +436,12 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
/* so that they replace the bad ones. We have to hack up the old */
/* leaf a bit, but it's better than deleting the whole directory, */
/* which is what used to happen before. */
-static void warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
- uint64_t *bad_leaf, uint64_t old_leaf,
- uint64_t first_ok_leaf, int pindex, const char *msg)
+static int warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
+ uint64_t *bad_leaf, uint64_t old_leaf,
+ uint64_t first_ok_leaf, int pindex, const char *msg)
{
+ int okay_to_fix = 0;
+
if (*bad_leaf != *leaf_no) {
log_err( _("Directory Inode %llu (0x%llx) points to leaf %llu"
" (0x%llx) %s.\n"),
@@ -449,7 +451,7 @@ static void warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
(unsigned long long)*leaf_no, msg);
}
if (*leaf_no == *bad_leaf ||
- query( _("Attempt to patch around it? (y/n) "))) {
+ (okay_to_fix = query( _("Attempt to patch around it? (y/n) ")))) {
if (!valid_block(ip->i_sbd, old_leaf) == 0)
gfs2_put_leaf_nr(ip, pindex, old_leaf);
else
@@ -462,6 +464,133 @@ static void warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
log_err( _("Bad leaf left in place.\n"));
*bad_leaf = *leaf_no;
*leaf_no = old_leaf;
+ return okay_to_fix;
+}
+
+/**
+ * check_leaf - check a leaf block for errors
+ */
+static int check_leaf(struct gfs2_inode *ip, int lindex,
+ struct metawalk_fxns *pass, int *ref_count,
+ uint64_t *leaf_no, uint64_t old_leaf, uint64_t *bad_leaf,
+ uint64_t first_ok_leaf, struct gfs2_leaf *leaf,
+ struct gfs2_leaf *oldleaf)
+{
+ int error = 0, fix;
+ struct gfs2_buffer_head *lbh = NULL;
+ uint32_t count = 0;
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ const char *msg;
+
+ *ref_count = 1;
+ /* Make sure the block number is in range. */
+ if (!valid_block(ip->i_sbd, *leaf_no)) {
+ log_err( _("Leaf block #%llu (0x%llx) is out of range for "
+ "directory #%llu (0x%llx).\n"),
+ (unsigned long long)*leaf_no,
+ (unsigned long long)*leaf_no,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
+ msg = _("that is out of range");
+ goto out_copy_old_leaf;
+ }
+
+ /* Try to read in the leaf block. */
+ lbh = bread(sdp, *leaf_no);
+ /* Make sure it's really a valid leaf block. */
+ if (gfs2_check_meta(lbh, GFS2_METATYPE_LF)) {
+ msg = _("that is not really a leaf");
+ goto out_copy_old_leaf;
+ }
+ if (pass->check_leaf) {
+ error = pass->check_leaf(ip, *leaf_no, pass->private);
+ if (error) {
+ log_info(_("Previous reference to leaf %lld (0x%llx) "
+ "has already checked it; skipping.\n"),
+ (unsigned long long)*leaf_no,
+ (unsigned long long)*leaf_no);
+ brelse(lbh);
+ return error;
+ }
+ }
+ /* Early versions of GFS2 had an endianess bug in the kernel that set
+ lf_dirent_format to cpu_to_be16(GFS2_FORMAT_DE). This was fixed
+ to use cpu_to_be32(), but we should check for incorrect values and
+ replace them with the correct value. */
+
+ gfs2_leaf_in(leaf, lbh);
+ if (leaf->lf_dirent_format == (GFS2_FORMAT_DE << 16)) {
+ log_debug( _("incorrect lf_dirent_format at leaf #%" PRIu64
+ "\n"), *leaf_no);
+ leaf->lf_dirent_format = GFS2_FORMAT_DE;
+ gfs2_leaf_out(leaf, lbh);
+ log_debug( _("Fixing lf_dirent_format.\n"));
+ }
+
+ /* Make sure it's really a leaf. */
+ if (leaf->lf_header.mh_type != GFS2_METATYPE_LF) {
+ log_err( _("Inode %llu (0x%llx) points to bad leaf %llu"
+ " (0x%llx).\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)*leaf_no,
+ (unsigned long long)*leaf_no);
+ msg = _("that is not a leaf");
+ goto out_copy_old_leaf;
+ }
+
+ if (pass->check_dentry && S_ISDIR(ip->i_di.di_mode)) {
+ error = check_entries(ip, lbh, DIR_EXHASH, &count, pass);
+
+ if (skip_this_pass || fsck_abort)
+ goto out;
+
+ if (error < 0) {
+ stack;
+ goto out;
+ }
+
+ if (count != leaf->lf_entries) {
+ /* release and re-read the leaf in case check_entries
+ changed it. */
+ brelse(lbh);
+ lbh = bread(sdp, *leaf_no);
+ gfs2_leaf_in(leaf, lbh);
+
+ log_err( _("Leaf %llu (0x%llx) entry count in "
+ "directory %llu (0x%llx) does not match "
+ "number of entries found - is %u, found %u\n"),
+ (unsigned long long)*leaf_no,
+ (unsigned long long)*leaf_no,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ leaf->lf_entries, count);
+ if (query( _("Update leaf entry count? (y/n) "))) {
+ leaf->lf_entries = count;
+ gfs2_leaf_out(leaf, lbh);
+ log_warn( _("Leaf entry count updated\n"));
+ } else
+ log_err( _("Leaf entry count left in "
+ "inconsistant state\n"));
+ }
+ }
+out:
+ brelse(lbh);
+ return 0;
+
+out_copy_old_leaf:
+ /* The leaf we read in is bad. So we'll copy the old leaf into the
+ * new one. However, that will make us shift our ref count. */
+ fix = warn_and_patch(ip, leaf_no, bad_leaf, old_leaf,
+ first_ok_leaf, lindex, msg);
+ (*ref_count)++;
+ memcpy(leaf, oldleaf, sizeof(struct gfs2_leaf));
+ if (lbh) {
+ if (fix)
+ bmodified(lbh);
+ brelse(lbh);
+ }
+ return 1;
}
/* Checks exhash directory entries */
@@ -474,8 +603,7 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
struct gfs2_buffer_head *lbh;
int lindex;
struct gfs2_sbd *sdp = ip->i_sbd;
- uint32_t count;
- int ref_count = 0, exp_count = 0;
+ int ref_count = 0;
/* Find the first valid leaf pointer in range and use it as our "old"
leaf. That way, bad blocks at the beginning will be overwritten
@@ -533,119 +661,12 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
if (error)
return error;
}
- ref_count = 1;
- count = 0;
- if (fsck_abort)
- break;
- /* Make sure the block number is in range. */
- if (!valid_block(ip->i_sbd, leaf_no)){
- log_err( _("Leaf block #%llu (0x%llx) is out "
- "of range for directory #%llu (0x%llx"
- ").\n"), (unsigned long long)leaf_no,
- (unsigned long long)leaf_no,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr);
- warn_and_patch(ip, &leaf_no, &bad_leaf,
- old_leaf, first_ok_leaf, lindex,
- _("that is out of range"));
- memcpy(&leaf, &oldleaf, sizeof(oldleaf));
- break;
- }
-
- /* Try to read in the leaf block. */
- lbh = bread(sdp, leaf_no);
- /* Make sure it's really a valid leaf block. */
- if (gfs2_check_meta(lbh, GFS2_METATYPE_LF)) {
- warn_and_patch(ip, &leaf_no, &bad_leaf,
- old_leaf, first_ok_leaf, lindex,
- _("that is not really a leaf"));
- memcpy(&leaf, &oldleaf, sizeof(oldleaf));
- bmodified(lbh);
- brelse(lbh);
- break;
- }
- gfs2_leaf_in(&leaf, lbh);
- if (pass->check_leaf)
- error = pass->check_leaf(ip, leaf_no,
- pass->private);
-
- /*
- * Early versions of GFS2 had an endianess bug in the
- * kernel that set lf_dirent_format to
- * cpu_to_be16(GFS2_FORMAT_DE). This was fixed to use
- * cpu_to_be32(), but we should check for incorrect
- * values and replace them with the correct value. */
-
- if (leaf.lf_dirent_format == (GFS2_FORMAT_DE << 16)) {
- log_debug( _("incorrect lf_dirent_format at leaf #%" PRIu64 "\n"), leaf_no);
- leaf.lf_dirent_format = GFS2_FORMAT_DE;
- gfs2_leaf_out(&leaf, lbh);
- log_debug( _("Fixing lf_dirent_format.\n"));
- }
-
- /* Make sure it's really a leaf. */
- if (leaf.lf_header.mh_type != GFS2_METATYPE_LF) {
- log_err( _("Inode %llu (0x%llx"
- ") points to bad leaf %llu"
- " (0x%llx).\n"),
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)leaf_no,
- (unsigned long long)leaf_no);
- brelse(lbh);
- break;
- }
- exp_count = (1 << (ip->i_di.di_depth - leaf.lf_depth));
- /*log_debug( _("expected count %u - di_depth %u,
- leaf depth %u\n"),
- exp_count, ip->i_di.di_depth, leaf.lf_depth);*/
-
- if (pass->check_dentry && S_ISDIR(ip->i_di.di_mode)) {
- error = check_entries(ip, lbh, DIR_EXHASH,
- &count, pass);
-
- if (skip_this_pass || fsck_abort)
- return 0;
-
- if (error < 0) {
- stack;
- brelse(lbh);
- return -1;
- }
-
- if (count != leaf.lf_entries) {
- brelse(lbh);
- lbh = bread(sdp, leaf_no);
- gfs2_leaf_in(&leaf, lbh);
-
- log_err( _("Leaf %llu (0x%llx) entry "
- "count in directory %llu"
- " (0x%llx) doesn't match "
- "number of entries found "
- "- is %u, found %u\n"),
- (unsigned long long)leaf_no,
- (unsigned long long)leaf_no,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- (unsigned long long)
- ip->i_di.di_num.no_addr,
- leaf.lf_entries, count);
- if (query( _("Update leaf entry count? (y/n) "))) {
- leaf.lf_entries = count;
- gfs2_leaf_out(&leaf, lbh);
- log_warn( _("Leaf entry count updated\n"));
- } else
- log_err( _("Leaf entry count left in inconsistant state\n"));
- }
- }
- brelse(lbh);
+ error = check_leaf(ip, lindex, pass, &ref_count,
+ &leaf_no, old_leaf, &bad_leaf,
+ first_ok_leaf, &leaf, &oldleaf);
old_leaf = leaf_no;
memcpy(&oldleaf, &leaf, sizeof(oldleaf));
- if (!leaf.lf_next)
+ if (!leaf.lf_next || error)
break;
leaf_no = leaf.lf_next;
log_debug( _("Leaf chain 0x%llx detected.\n"),
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: fsck.gfs2: Duplicate ref processing for leaf blocks
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 4857f0866b3f5f641300f022fa9d4624ebe3f32a
Parent: 2b9c1cfac56cef5bde3d9941bc5f21027c22b1c8
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 09:33:08 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2: fsck.gfs2: Duplicate ref processing for leaf blocks
This patch adds checks for duplicate block references to the leaf block
processing.
rhbz#675723
---
gfs2/fsck/pass1.c | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 26883d3..a1f4232 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -334,7 +334,27 @@ static int check_num_ptrs(struct gfs2_inode *ip, uint64_t leafno,
static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
{
struct block_count *bc = (struct block_count *) private;
+ uint8_t q;
+ /* Note if we've gotten this far, the block has already passed the
+ check in metawalk: gfs2_check_meta(lbh, GFS2_METATYPE_LF).
+ So we know it's a leaf block. */
+ q = block_type(block);
+ if (q != gfs2_block_free) {
+ log_err( _("Found duplicate block %llu (0x%llx) referenced "
+ "as a directory leaf in dinode "
+ "%llu (0x%llx) - was marked %d (%s)\n"),
+ (unsigned long long)block,
+ (unsigned long long)block,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr, q,
+ block_type_string(q));
+ add_duplicate_ref(ip, block, ref_as_meta, 0, INODE_VALID);
+ if (q == gfs2_leaf_blk) /* If the previous reference also saw
+ this as a leaf, it was already
+ checked, so don't check again. */
+ return -EEXIST;
+ }
fsck_blockmap_set(ip, block, _("directory leaf"), gfs2_leaf_blk);
bc->indir_count++;
return 0;
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: fsck.gfs2: Move check_num_ptrs from metawalk to pass1
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 2b9c1cfac56cef5bde3d9941bc5f21027c22b1c8
Parent: 95edb17a8a8312bc2e08c7ce8efc59b54bffda10
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 09:23:05 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2: fsck.gfs2: Move check_num_ptrs from metawalk to pass1
This patch moves function check_num_ptrs from metawalk.c to pass1.c
and also its helper function fix_leaf_pointers. This function checks
that the number of pointers in a leaf block is a factor of 2, and sane.
This should only happen once, when leaf blocks are initially checked.
Previously it was wasting a lot of time doing this check from every pass.
rhbz#675723
---
gfs2/fsck/metawalk.c | 129 +++-------------------------------------------
gfs2/fsck/metawalk.h | 3 +
gfs2/fsck/pass1.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 148 insertions(+), 124 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index dd0b929..cf75164 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -464,123 +464,6 @@ static void warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
*leaf_no = old_leaf;
}
-/*
- * fix_leaf_pointers - fix a directory dinode that has a number of pointers
- * that is not a multiple of 2.
- * dip - the directory inode having the problem
- * lindex - the index of the leaf right after the problem (need to back up)
- * cur_numleafs - current (incorrect) number of instances of the leaf block
- * correct_numleafs - the correct number instances of the leaf block
- */
-static int fix_leaf_pointers(struct gfs2_inode *dip, int *lindex,
- int cur_numleafs, int correct_numleafs)
-{
- int count;
- char *ptrbuf;
- int start_lindex = *lindex - cur_numleafs; /* start of bad ptrs */
- int tot_num_ptrs = (1 << dip->i_di.di_depth) - start_lindex;
- int bufsize = tot_num_ptrs * sizeof(uint64_t);
- int off_by = cur_numleafs - correct_numleafs;
-
- ptrbuf = malloc(bufsize);
- if (!ptrbuf) {
- log_err( _("Error: Cannot allocate memory to fix the leaf "
- "pointers.\n"));
- return -1;
- }
- /* Read all the pointers, starting with the first bad one */
- count = gfs2_readi(dip, ptrbuf, start_lindex * sizeof(uint64_t),
- bufsize);
- if (count != bufsize) {
- log_err( _("Error: bad read while fixing leaf pointers.\n"));
- free(ptrbuf);
- return -1;
- }
-
- bufsize -= off_by * sizeof(uint64_t); /* We need to write fewer */
- /* Write the same pointers, but offset them so they fit within the
- smaller factor of 2. So if we have 12 pointers, write out only
- the last 8 of them. If we have 7, write the last 4, etc.
- We need to write these starting at the current lindex and adjust
- lindex accordingly. */
- count = gfs2_writei(dip, ptrbuf + (off_by * sizeof(uint64_t)),
- start_lindex * sizeof(uint64_t), bufsize);
- if (count != bufsize) {
- log_err( _("Error: bad read while fixing leaf pointers.\n"));
- free(ptrbuf);
- return -1;
- }
- /* Now zero out the hole left at the end */
- memset(ptrbuf, 0, off_by * sizeof(uint64_t));
- gfs2_writei(dip, ptrbuf, (start_lindex * sizeof(uint64_t)) +
- bufsize, off_by * sizeof(uint64_t));
- free(ptrbuf);
- *lindex -= off_by; /* adjust leaf index to account for the change */
- return 0;
-}
-
-/* check_num_ptrs - check a previously processed leaf's pointer count */
-static int check_num_ptrs(struct gfs2_inode *ip, uint64_t old_leaf,
- int *ref_count, int *exp_count, int *lindex,
- struct gfs2_leaf *oldleaf)
-{
- int factor = 0, divisor = *ref_count, multiple = 1, error = 0;
- struct gfs2_buffer_head *lbh;
-
- /* Check to see if the number of pointers we found is a power of 2.
- It needs to be and if it's not we need to fix it.*/
- while (divisor > 1) {
- factor++;
- divisor /= 2;
- multiple = multiple << 1;
- }
- if (*ref_count != multiple) {
- log_err( _("Directory #%llu (0x%llx) has an "
- "invalid number of pointers to "
- "leaf #%llu (0x%llx)\n\tFound: %u, "
- "which is not a factor of 2.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)old_leaf,
- (unsigned long long)old_leaf, *ref_count);
- if (!query( _("Attempt to fix it? (y/n) "))) {
- log_err( _("Directory inode was not fixed.\n"));
- return 1;
- }
- error = fix_leaf_pointers(ip, lindex, *ref_count, multiple);
- if (error)
- return error;
- *ref_count = multiple;
- log_err( _("Directory inode was fixed.\n"));
- }
- /* Check to see if the counted number of leaf pointers is what we
- expect. */
- if (*ref_count != *exp_count) {
- log_err( _("Directory #%llu (0x%llx) has an "
- "incorrect number of pointers to "
- "leaf #%llu (0x%llx)\n\tFound: "
- "%u, Expected: %u\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)old_leaf,
- (unsigned long long)old_leaf, *ref_count, *exp_count);
- if (!query( _("Attempt to fix it? (y/n) "))) {
- log_err( _("Directory leaf was not fixed.\n"));
- return 1;
- }
- lbh = bread(ip->i_sbd, old_leaf);
- gfs2_leaf_in(oldleaf, lbh);
- log_err( _("Leaf depth was %d, changed to %d\n"),
- oldleaf->lf_depth, ip->i_di.di_depth - factor);
- oldleaf->lf_depth = ip->i_di.di_depth - factor;
- gfs2_leaf_out(oldleaf, lbh);
- brelse(lbh);
- *exp_count = *ref_count;
- log_err( _("Directory leaf was fixed.\n"));
- }
- return 0;
-}
-
/* Checks exhash directory entries */
static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
{
@@ -639,10 +522,14 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
}
do {
- if (!valid_block(ip->i_sbd, old_leaf) == 0) {
- error = check_num_ptrs(ip, old_leaf,
- &ref_count, &exp_count,
- &lindex, &oldleaf);
+ if (fsck_abort)
+ return 0;
+ if (pass->check_num_ptrs &&
+ valid_block(ip->i_sbd, old_leaf)) {
+ error = pass->check_num_ptrs(ip, old_leaf,
+ &ref_count,
+ &lindex,
+ &oldleaf);
if (error)
return error;
}
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index d705726..7a8ae4c 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -89,6 +89,9 @@ struct metawalk_fxns {
int (*finish_eattr_indir) (struct gfs2_inode *ip, int leaf_pointers,
int leaf_pointer_errors, void *private);
void (*big_file_msg) (struct gfs2_inode *ip, uint64_t blks_checked);
+ int (*check_num_ptrs) (struct gfs2_inode *ip, uint64_t leafno,
+ int *ref_count, int *lindex,
+ struct gfs2_leaf *leaf);
};
#endif /* _METAWALK_H */
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 271075c..26883d3 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -32,7 +32,7 @@ struct block_count {
uint64_t ea_count;
};
-static int leaf(struct gfs2_inode *ip, uint64_t block, void *private);
+static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private);
static int check_metalist(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, int h, void *private);
static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
@@ -57,6 +57,8 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
+static int check_num_ptrs(struct gfs2_inode *ip, uint64_t leafno,
+ int *ref_count, int *lindex, struct gfs2_leaf *leaf);
static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
int leaf_pointer_errors, void *private);
static int invalidate_metadata(struct gfs2_inode *ip, uint64_t block,
@@ -77,7 +79,7 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip);
struct metawalk_fxns pass1_fxns = {
.private = NULL,
- .check_leaf = leaf,
+ .check_leaf = check_leaf,
.check_metalist = check_metalist,
.check_data = check_data,
.check_eattr_indir = check_eattr_indir,
@@ -87,6 +89,7 @@ struct metawalk_fxns pass1_fxns = {
.check_eattr_extentry = check_extended_leaf_eattr,
.finish_eattr_indir = finish_eattr_indir,
.big_file_msg = big_file_comfort,
+ .check_num_ptrs = check_num_ptrs,
};
struct metawalk_fxns undo_fxns = {
@@ -197,7 +200,138 @@ struct metawalk_fxns sysdir_fxns = {
.check_dentry = resuscitate_dentry,
};
-static int leaf(struct gfs2_inode *ip, uint64_t block, void *private)
+/*
+ * fix_leaf_pointers - fix a directory dinode that has a number of pointers
+ * that is not a multiple of 2.
+ * dip - the directory inode having the problem
+ * lindex - the index of the leaf right after the problem (need to back up)
+ * cur_numleafs - current (incorrect) number of instances of the leaf block
+ * correct_numleafs - the correct number instances of the leaf block
+ */
+static int fix_leaf_pointers(struct gfs2_inode *dip, int *lindex,
+ int cur_numleafs, int correct_numleafs)
+{
+ int count;
+ char *ptrbuf;
+ int start_lindex = *lindex - cur_numleafs; /* start of bad ptrs */
+ int tot_num_ptrs = (1 << dip->i_di.di_depth) - start_lindex;
+ int bufsize = tot_num_ptrs * sizeof(uint64_t);
+ int off_by = cur_numleafs - correct_numleafs;
+
+ ptrbuf = malloc(bufsize);
+ if (!ptrbuf) {
+ log_err( _("Error: Cannot allocate memory to fix the leaf "
+ "pointers.\n"));
+ return -1;
+ }
+ /* Read all the pointers, starting with the first bad one */
+ count = gfs2_readi(dip, ptrbuf, start_lindex * sizeof(uint64_t),
+ bufsize);
+ if (count != bufsize) {
+ log_err( _("Error: bad read while fixing leaf pointers.\n"));
+ free(ptrbuf);
+ return -1;
+ }
+
+ bufsize -= off_by * sizeof(uint64_t); /* We need to write fewer */
+ /* Write the same pointers, but offset them so they fit within the
+ smaller factor of 2. So if we have 12 pointers, write out only
+ the last 8 of them. If we have 7, write the last 4, etc.
+ We need to write these starting at the current lindex and adjust
+ lindex accordingly. */
+ count = gfs2_writei(dip, ptrbuf + (off_by * sizeof(uint64_t)),
+ start_lindex * sizeof(uint64_t), bufsize);
+ if (count != bufsize) {
+ log_err( _("Error: bad read while fixing leaf pointers.\n"));
+ free(ptrbuf);
+ return -1;
+ }
+ /* Now zero out the hole left at the end */
+ memset(ptrbuf, 0, off_by * sizeof(uint64_t));
+ gfs2_writei(dip, ptrbuf, (start_lindex * sizeof(uint64_t)) +
+ bufsize, off_by * sizeof(uint64_t));
+ free(ptrbuf);
+ *lindex -= off_by; /* adjust leaf index to account for the change */
+ return 0;
+}
+
+/**
+ * check_num_ptrs - check a previously processed leaf's pointer count in the
+ * hash table.
+ *
+ * The number of pointers in a directory hash table that point to any given
+ * leaf block should always be a factor of two. The difference between the
+ * leaf block's depth and the dinode's di_depth gives us the factor.
+ * This function makes sure the leaf follows the rules properly.
+ *
+ * ip - pointer to the in-core inode structure
+ * leafno - the leaf number we're operating on
+ * ref_count - the number of pointers to this leaf we actually counted.
+ * exp_count - the number of pointers to this leaf we expect based on
+ * ip depth minus leaf depth.
+ * lindex - leaf index number
+ * leaf - the leaf structure for the leaf block to check
+ */
+static int check_num_ptrs(struct gfs2_inode *ip, uint64_t leafno,
+ int *ref_count, int *lindex, struct gfs2_leaf *leaf)
+{
+ int factor = 0, divisor = *ref_count, multiple = 1, error = 0;
+ struct gfs2_buffer_head *lbh;
+ int exp_count;
+
+ /* Check to see if the number of pointers we found is a power of 2.
+ It needs to be and if it's not we need to fix it.*/
+ while (divisor > 1) {
+ factor++;
+ divisor /= 2;
+ multiple = multiple << 1;
+ }
+ if (*ref_count != multiple) {
+ log_err( _("Directory #%llu (0x%llx) has an invalid number of "
+ "pointers to leaf #%llu (0x%llx)\n\tFound: %u, "
+ "which is not a factor of 2.\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)leafno,
+ (unsigned long long)leafno, *ref_count);
+ if (!query( _("Attempt to fix it? (y/n) "))) {
+ log_err( _("Directory inode was not fixed.\n"));
+ return 1;
+ }
+ error = fix_leaf_pointers(ip, lindex, *ref_count, multiple);
+ if (error)
+ return error;
+ *ref_count = multiple;
+ log_err( _("Directory inode was fixed.\n"));
+ }
+ /* Check to see if the counted number of leaf pointers is what we
+ expect based on the leaf depth. */
+ exp_count = (1 << (ip->i_di.di_depth - leaf->lf_depth));
+ if (*ref_count != exp_count) {
+ log_err( _("Directory #%llu (0x%llx) has an incorrect number "
+ "of pointers to leaf #%llu (0x%llx)\n\tFound: "
+ "%u, Expected: %u\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)leafno,
+ (unsigned long long)leafno, *ref_count, exp_count);
+ if (!query( _("Attempt to fix it? (y/n) "))) {
+ log_err( _("Directory leaf was not fixed.\n"));
+ return 1;
+ }
+ lbh = bread(ip->i_sbd, leafno);
+ gfs2_leaf_in(leaf, lbh);
+ log_err( _("Leaf depth was %d, changed to %d\n"),
+ leaf->lf_depth, ip->i_di.di_depth - factor);
+ leaf->lf_depth = ip->i_di.di_depth - factor;
+ gfs2_leaf_out(leaf, lbh);
+ brelse(lbh);
+ log_err( _("Directory leaf was fixed.\n"));
+ }
+ return 0;
+}
+
+static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
{
struct block_count *bc = (struct block_count *) private;
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: fsck.gfs2: Find and clear duplicate leaf blocks refs
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 95edb17a8a8312bc2e08c7ce8efc59b54bffda10
Parent: 01401b5167a5d2aa9b36a1dc4605ec07fca4db65
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 16:44:47 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2: fsck.gfs2: Find and clear duplicate leaf blocks refs
Duplicate references that were in leaf blocks were never found nor
cleared. This patch adds that capability.
rhbz#675723
---
gfs2/fsck/pass1b.c | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index ce358c4..65e6de9 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -26,6 +26,7 @@ struct dup_handler {
int ref_count;
};
+static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private);
static int check_metalist(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, int h, void *private);
static int check_data(struct gfs2_inode *ip, uint64_t block, void *private);
@@ -51,7 +52,7 @@ static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de,
struct metawalk_fxns find_refs = {
.private = NULL,
- .check_leaf = NULL,
+ .check_leaf = check_leaf,
.check_metalist = check_metalist,
.check_data = check_data,
.check_eattr_indir = check_eattr_indir,
@@ -73,6 +74,11 @@ struct metawalk_fxns find_dirents = {
.check_eattr_extentry = NULL,
};
+static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
+{
+ return add_duplicate_ref(ip, block, ref_as_meta, 1, INODE_VALID);
+}
+
static int check_metalist(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, int h, void *private)
{
@@ -250,6 +256,11 @@ static int clear_dup_data(struct gfs2_inode *ip, uint64_t block, void *private)
return clear_dup_metalist(ip, block, NULL, 0, private);
}
+static int clear_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
+{
+ return clear_dup_metalist(ip, block, NULL, 0, private);
+}
+
static int clear_dup_eattr_indir(struct gfs2_inode *ip, uint64_t block,
uint64_t parent, struct gfs2_buffer_head **bh,
void *private)
@@ -392,7 +403,7 @@ static int clear_a_reference(struct gfs2_sbd *sdp, struct duptree *b,
osi_list_t *tmp, *x;
struct metawalk_fxns clear_dup_fxns = {
.private = NULL,
- .check_leaf = NULL,
+ .check_leaf = clear_leaf,
.check_metalist = clear_dup_metalist,
.check_data = clear_dup_data,
.check_eattr_indir = clear_dup_eattr_indir,
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: fsck.gfs2: Don't stop invalidating blocks on invalid
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 01401b5167a5d2aa9b36a1dc4605ec07fca4db65
Parent: 1de5d9be1718dbf67ddb4e308b27f39d52415384
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 16:20:14 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2: fsck.gfs2: Don't stop invalidating blocks on invalid
When fsck found a duplicate reference to a block it invalidated the dinode's
metadata. But if it encountered an invalid block, for example, out of range,
the invalidating would stop. If we encounter a block that isn't valid, we
obviously can't invalidate it. However, if we return an error, all future
invalidating will stop for that dinode. That's wrong because we need it to
continue to invalidate the other valid blocks. If we don't do this, block
references that follow the bad one that are also referenced elsewhere
(duplicates) won't be flagged as such. As a result, they'll be freed when
this corrupt dinode is deleted, despite being used by another dinode as a
valid block. This patch makes it return a good return code so the invalidating
continues.
rhbz#675723
---
gfs2/fsck/pass1.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 49a8f4e..271075c 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -825,8 +825,15 @@ static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block,
{
uint8_t q;
- if (!valid_block(ip->i_sbd, block) != 0)
- return -EFAULT;
+ /* If the block isn't valid, we obviously can't invalidate it.
+ * However, if we return an error, invalidating will stop, and
+ * we want it to continue to invalidate the valid blocks. If we
+ * don't do this, block references that follow that are also
+ * referenced elsewhere (duplicates) won't be flagged as such,
+ * and as a result, they'll be freed when this dinode is deleted,
+ * despite being used by another dinode as a valid block. */
+ if (!valid_block(ip->i_sbd, block))
+ return 0;
q = block_type(block);
if (q != gfs2_block_free) {
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: fsck.gfs2: Refactor add_dotdot function in lost+found
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: c8accb82665995a1f7dfd15be79788cf1e54f05d
Parent: 2dd1ef3d036b0958fcf3dee56945e5454fd7bdb0
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 15:44:19 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2: fsck.gfs2: Refactor add_dotdot function in lost+found
This function factors out a section of code from function add_inode_to_lf.
This makes it easier to read and gives it the ability to print better
messages regarding where the block was previously linked.
rhbz#675723
---
gfs2/fsck/lost_n_found.c | 113 ++++++++++++++++++++++++++--------------------
1 files changed, 64 insertions(+), 49 deletions(-)
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index e5d7571..7886625 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -15,6 +15,69 @@
#include "metawalk.h"
#include "util.h"
+static void add_dotdot(struct gfs2_inode *ip)
+{
+ struct dir_info *di;
+ struct gfs2_sbd *sdp = ip->i_sbd;
+
+ log_info( _("Adding .. entry to directory %llu (0x%llx) pointing back "
+ "to lost+found\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
+
+ /* If there's a pre-existing .. directory entry, we have to
+ back out the links. */
+ di = dirtree_find(ip->i_di.di_num.no_addr);
+ if (di && !valid_block(sdp, di->dotdot_parent) == 0) {
+ struct gfs2_inode *dip;
+
+ log_debug(_("Directory %lld (0x%llx) already had a "
+ "\"..\" link to %lld (0x%llx).\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)di->dotdot_parent,
+ (unsigned long long)di->dotdot_parent);
+ decr_link_count(di->dotdot_parent, ip->i_di.di_num.no_addr,
+ _(".. unlinked, moving to lost+found"));
+ dip = fsck_load_inode(sdp, di->dotdot_parent);
+ if (dip->i_di.di_nlink > 0) {
+ dip->i_di.di_nlink--;
+ set_di_nlink(dip); /* keep inode tree in sync */
+ log_debug(_("Decrementing its links to %d\n"),
+ dip->i_di.di_nlink);
+ bmodified(dip->i_bh);
+ } else if (!dip->i_di.di_nlink) {
+ log_debug(_("Its link count is zero.\n"));
+ } else {
+ log_debug(_("Its link count is %d! Changing "
+ "it to 0.\n"), dip->i_di.di_nlink);
+ dip->i_di.di_nlink = 0;
+ set_di_nlink(dip); /* keep inode tree in sync */
+ bmodified(dip->i_bh);
+ }
+ fsck_inode_put(&dip);
+ di = NULL;
+ } else {
+ if (di)
+ log_debug(_("Couldn't find a valid \"..\" entry "
+ "for orphan directory %lld (0x%llx): "
+ "'..' = 0x%llx\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)di->dotdot_parent);
+ else
+ log_debug(_("Couldn't find a valid \"..\" entry "
+ "for orphan directory %lld (0x%llx)\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
+ }
+ if (gfs2_dirent_del(ip, "..", 2))
+ log_warn( _("add_inode_to_lf: Unable to remove "
+ "\"..\" directory entry.\n"));
+
+ dir_add(ip, "..", 2, &(lf_dip->i_di.di_num), DT_DIR);
+}
+
/* add_inode_to_lf - Add dir entry to lost+found for the inode
* @ip: inode to add to lost + found
*
@@ -86,55 +149,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){
switch(ip->i_di.di_mode & S_IFMT){
case S_IFDIR:
- log_info( _("Adding .. entry pointing to lost+found for "
- "directory %llu (0x%llx)\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
-
- /* If there's a pre-existing .. directory entry, we have to
- back out the links. */
- di = dirtree_find(ip->i_di.di_num.no_addr);
- if (di && !valid_block(sdp, di->dotdot_parent) == 0) {
- struct gfs2_inode *dip;
-
- log_debug(_("Directory %lld (0x%llx) already had a "
- "\"..\" link to %lld (0x%llx).\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)di->dotdot_parent,
- (unsigned long long)di->dotdot_parent);
- decr_link_count(di->dotdot_parent,
- ip->i_di.di_num.no_addr,
- _(".. unlinked, moving to lost+found"));
- dip = fsck_load_inode(sdp, di->dotdot_parent);
- if (dip->i_di.di_nlink > 0) {
- dip->i_di.di_nlink--;
- set_di_nlink(dip); /* keep inode tree in sync */
- log_debug(_("Decrementing its links to %d\n"),
- dip->i_di.di_nlink);
- bmodified(dip->i_bh);
- } else if (!dip->i_di.di_nlink) {
- log_debug(_("Its link count is zero.\n"));
- } else {
- log_debug(_("Its link count is %d! "
- "Changing it to 0.\n"),
- dip->i_di.di_nlink);
- dip->i_di.di_nlink = 0;
- set_di_nlink(dip); /* keep inode tree in sync */
- bmodified(dip->i_bh);
- }
- fsck_inode_put(&dip);
- di = NULL;
- } else
- log_debug(_("Couldn't find a valid \"..\" entry "
- "for orphan directory %lld (0x%llx)\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- if (gfs2_dirent_del(ip, "..", 2))
- log_warn( _("add_inode_to_lf: Unable to remove "
- "\"..\" directory entry.\n"));
-
- dir_add(ip, "..", 2, &(lf_dip->i_di.di_num), DT_DIR);
+ add_dotdot(ip);
sprintf(tmp_name, "lost_dir_%llu",
(unsigned long long)ip->i_di.di_num.no_addr);
inode_type = DT_DIR;
12 years, 4 months
cluster: RHEL6 - libgfs2: libgfs2: Use __FUNCTION__ rather than __FILE__
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 1de5d9be1718dbf67ddb4e308b27f39d52415384
Parent: c8accb82665995a1f7dfd15be79788cf1e54f05d
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 16:11:48 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
libgfs2: libgfs2: Use __FUNCTION__ rather than __FILE__
This patch changes the debug output of gfs2-utils to use __FUNCTION__
rather than __FILE__. The output file is much smaller. Digging through
a 6.5GB output is better and faster than a 9GB output file.
rhbz#675723
---
gfs2/fsck/metawalk.c | 13 +++----------
gfs2/fsck/metawalk.h | 2 +-
gfs2/libgfs2/libgfs2.h | 2 +-
3 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 94de22a..dd0b929 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -98,17 +98,10 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
int error;
if (print_level >= MSG_DEBUG) {
- const char *p;
-
- p = strrchr(caller, '/');
- if (p)
- p++;
- else
- p = caller;
/* I'm circumventing the log levels here on purpose to make the
output easier to debug. */
if (ip->i_di.di_num.no_addr == bblock) {
- print_fsck_log(MSG_DEBUG, p, fline,
+ print_fsck_log(MSG_DEBUG, caller, fline,
_("%s inode found at block %lld "
"(0x%llx): marking as '%s'\n"),
btype, (unsigned long long)
@@ -117,7 +110,7 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
ip->i_di.di_num.no_addr,
block_type_string(mark));
} else if (mark == gfs2_bad_block || mark == gfs2_meta_inval) {
- print_fsck_log(MSG_DEBUG, p, fline,
+ print_fsck_log(MSG_DEBUG, caller, fline,
_("inode %lld (0x%llx) references "
"%s block %lld (0x%llx): "
"marking as '%s'\n"),
@@ -129,7 +122,7 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
(unsigned long long)bblock,
block_type_string(mark));
} else {
- print_fsck_log(MSG_DEBUG, p, fline,
+ print_fsck_log(MSG_DEBUG, caller, fline,
_("inode %lld (0x%llx) references "
"%s block %lld (0x%llx): "
"marking as '%s'\n"),
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index c15d7b7..d705726 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -39,7 +39,7 @@ extern struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp,
#define is_duplicate(dblock) ((dupfind(dblock)) ? 1 : 0)
#define fsck_blockmap_set(ip, b, bt, m) _fsck_blockmap_set(ip, b, bt, m, \
- __FILE__, __LINE__)
+ __FUNCTION__, __LINE__)
/* metawalk_fxns: function pointers to check various parts of the fs
*
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 0ddb48f..9bae01b 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -693,7 +693,7 @@ extern int print_level;
#define MSG_NULL 1
#define print_log(priority, format...) \
- do { print_fsck_log(priority, __FILE__, __LINE__, ## format); } while(0)
+ do { print_fsck_log(priority, __FUNCTION__, __LINE__, ## format); } while(0)
#define log_debug(format...) \
do { if(print_level >= MSG_DEBUG) print_log(MSG_DEBUG, format); } while(0)
12 years, 4 months
cluster: RHEL6 - dirent_repair needs to mark the buffer as modified
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: f5da0eb475b287a1bc4227b54c87083878490c72
Parent: 5cacd15160d57c57e76b6defdd701460c296b8c9
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 14:47:49 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
dirent_repair needs to mark the buffer as modified
This patch adds a call to bmodified to function dirent_repair. Without
setting the modified bit, directory repairs may be forgotten and never
written back to disk, leaving the damage in place.
rhbz#675723
---
gfs2/fsck/metawalk.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 888acec..94de22a 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -264,6 +264,7 @@ static int dirent_repair(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
de->de_rec_len = GFS2_DIRENT_SIZE(de->de_name_len);
}
gfs2_dirent_out(de, (char *)dent);
+ bmodified(bh);
return 0;
}
12 years, 4 months