Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=40127ca5ab…
Commit: 40127ca5abc87bd93d748884a8b8b58d83afc234
Parent: 7520428d1f78a538243b92226335ce9d1551633c
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Sep 24 13:42:03 2015 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Sep 29 13:23:48 2015 -0500
fsck.gfs2: Print debug message to dilineate metadata blocks
Before this patch, when the data blocks were checked for a huge
file, there was no way to distinguish which metadata block had the
reference to the data block. This patch adds a new debug message
to announce which metadata block is being processed for the next
set of data blocks being analyzed.
---
gfs2/fsck/metawalk.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index bb03d1a..8fcaea3 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1454,6 +1454,10 @@ static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass,
uint64_t metablock = bh->b_blocknr;
/* If there isn't much pointer corruption check the pointers */
+ log_debug(_("\nProcessing data blocks for inode 0x%llx, metadata "
+ "block 0x%llx.\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)bh->b_blocknr);
for (ptr = ptr_start ; (char *)ptr < ptr_end && !fsck_abort; ptr++) {
if (!*ptr)
continue;
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=6260b11af9…
Commit: 6260b11af9222910550678f7c8933d4091870427
Parent: 9ef99edb80d10cb58ed3b44a3198b6c44544b8b2
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Sep 24 10:09:55 2015 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Sep 29 13:23:41 2015 -0500
fsck.gfs2: remove bad EAs at the end, not as-you-go
Before this patch, pass1 would check extended attributes and if they
were found to be bad, it would delete them as it found them. This
is the wrong approach and only gets us into trouble. The proper
approach is to traverse the tree and see if there are problems, and
if so, delete them at the end. This patch:
1. Removes function clear_eas() which was delete-as-you-go.
2. Instead, the errors are complained about but the traversal goes on.
3. Adds a new tree traversal, eattr_undo_fxns, which is used to
properly remove the corrupt extended attributes at the end of
the previous tree traversal.
---
gfs2/fsck/pass1.c | 107 ++++++++++++++++++++++++++++------------------------
1 files changed, 58 insertions(+), 49 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index f5bf66b..a515a62 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -102,7 +102,6 @@ struct metawalk_fxns pass1_fxns = {
.check_dentry = NULL,
.check_eattr_entry = check_eattr_entries,
.check_eattr_extentry = check_extended_leaf_eattr,
- .finish_eattr_indir = finish_eattr_indir,
.big_file_msg = big_file_comfort,
.repair_leaf = pass1_repair_leaf,
.undo_check_meta = undo_check_metalist,
@@ -585,6 +584,36 @@ static int ask_remove_inode_eattr(struct gfs2_inode *ip,
return 0;
}
+static int undo_eattr_indir_or_leaf(struct gfs2_inode *ip, uint64_t block,
+ uint64_t parent,
+ struct gfs2_buffer_head **bh,
+ void *private)
+{
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ uint8_t q;
+ int error;
+ struct block_count *bc = (struct block_count *) private;
+
+ if (!valid_block(ip->i_sbd, block))
+ return meta_error;
+
+ /* Need to check block_type before undoing the reference, which can
+ set it to free, which would cause the test below to fail. */
+ q = block_type(block);
+
+ error = undo_reference(ip, block, 0, private);
+ if (error)
+ return error;
+
+ bc->ea_count--;
+
+ if (q != (sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED))
+ return 1;
+
+ *bh = bread(sdp, block);
+ return 0;
+}
+
/* complain_eas - complain about extended attribute errors for an inode
*
* @ip - in core inode pointer
@@ -603,36 +632,6 @@ static void complain_eas(struct gfs2_inode *ip, uint64_t block,
(unsigned long long)block, (unsigned long long)block);
}
-/* clear_eas - clear the extended attributes for an inode
- *
- * @ip - in core inode pointer
- * @bc - pointer to a block count structure
- * block - the block that had the problem
- * duplicate - if this is a duplicate block, don't set it "free"
- * emsg - what to tell the user about the eas being checked
- * Returns: 1 if the EA is fixed, else 0 if it was not fixed.
- */
-static int clear_eas(struct gfs2_inode *ip, struct block_count *bc,
- uint64_t block, int duplicate, const char *emsg)
-{
- complain_eas(ip, block, emsg);
- if (query( _("Clear the bad Extended Attribute? (y/n) "))) {
- if (block == ip->i_di.di_eattr) {
- remove_inode_eattr(ip, bc);
- log_err( _("The bad extended attribute was "
- "removed.\n"));
- } else if (!duplicate) {
- delete_block(ip, block, NULL,
- _("bad extended attribute"), NULL);
- }
- return 1;
- } else {
- log_err( _("The bad Extended Attribute was not fixed.\n"));
- bc->ea_count++;
- return 0;
- }
-}
-
static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
uint64_t parent, struct gfs2_buffer_head **bh,
void *private)
@@ -657,22 +656,22 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
count it as a duplicate. */
*bh = bread(sdp, indirect);
if (gfs2_check_meta(*bh, GFS2_METATYPE_IN)) {
+ bc->ea_count++;
if (q != GFS2_BLKST_FREE) { /* Duplicate? */
add_duplicate_ref(ip, indirect, ref_as_ea, 0,
INODE_VALID);
complain_eas(ip, indirect,
_("Bad indirect Extended Attribute "
"duplicate found"));
- bc->ea_count++;
/* Return 0 here because if all that's wrong is a
duplicate block reference, we want pass1b to figure
it out. We don't want to delete all the extended
attributes as if they are in error. */
return 0;
}
- clear_eas(ip, bc, indirect, 0,
- _("Extended Attribute indirect block has incorrect "
- "type"));
+ complain_eas(ip, indirect,
+ _("Extended Attribute indirect block has "
+ "incorrect type"));
return 1;
}
if (q != GFS2_BLKST_FREE) { /* Duplicate? */
@@ -765,8 +764,8 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype,
attributes as if they are in error. */
return 0;
}
- clear_eas(ip, bc, block, 0, _("Extended Attribute leaf block "
- "has incorrect type"));
+ complain_eas(ip, block, _("Extended Attribute leaf block has "
+ "incorrect type"));
brelse(leaf_bh);
return 1;
}
@@ -782,16 +781,6 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype,
in error. */
return 0;
}
- if (ip->i_di.di_eattr == 0) {
- /* Can only get in here if there were unrecoverable ea
- errors that caused clear_eas to be called. What we
- need to do here is remove the subsequent ea blocks. */
- clear_eas(ip, bc, block, 0,
- _("Extended Attribute block removed due to "
- "previous errors.\n"));
- brelse(leaf_bh);
- return 1;
- }
/* Point of confusion: We've got to set the ea block itself to
GFS2_BLKST_USED here. Elsewhere we mark the inode with
gfs2_eattr_block meaning it contains an eattr for pass1c. */
@@ -1129,6 +1118,13 @@ struct metawalk_fxns rangecheck_fxns = {
.check_eattr_leaf = rangecheck_eattr_leaf,
};
+struct metawalk_fxns eattr_undo_fxns = {
+ .private = NULL,
+ .check_eattr_indir = undo_eattr_indir_or_leaf,
+ .check_eattr_leaf = undo_eattr_indir_or_leaf,
+ .finish_eattr_indir = finish_eattr_indir,
+};
+
/*
* handle_ip - process an incore structure representing a dinode.
*/
@@ -1195,9 +1191,22 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip)
if (!error) {
error = check_inode_eattr(ip, &pass1_fxns);
- if (error &&
- !(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT))
+ if (error) {
+ if (!query(_("Clear the bad Extended Attributes? "
+ "(y/n) "))) {
+ log_err( _("The bad Extended Attributes were "
+ "not fixed.\n"));
+ return 0;
+ }
+ log_err(_("Clearing the bad Extended Attributes in "
+ "inode %lld (0x%llx).\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
+ eattr_undo_fxns.private = &bc;
+ check_inode_eattr(ip, &eattr_undo_fxns);
ask_remove_inode_eattr(ip, &bc);
+ return 1;
+ }
}
if (ip->i_di.di_blocks !=
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=647bf61ecc…
Commit: 647bf61ecc78ba5bcfbacdc1ab95488cfe787aeb
Parent: 28a73aac8c060378553cd161222e30c5b8d40865
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Sep 24 07:51:51 2015 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Sep 29 13:23:34 2015 -0500
fsck.gfs2: Don't remove duplicate eattr blocks
Before this patch, if two dinodes referenced the same block, one of
them in the extended attributes, it would delete the extended
attributes. That's wrong because the other dinode referencing the
block might be a valid reference, and the block should not be
deleted out from under it. This patch changes the return code from
1 to 0 in this case, which causes pass1b to resolve whichever
reference is proper and delete or not delete the other reference
as appropriate. It also splits the clear_eas function into a
separate function to complain about the problem; that way the
duplicate errors above are still reported.
---
gfs2/fsck/pass1.c | 76 +++++++++++++++++++++++++++++++++-------------------
1 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 653be59..f21886b 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -585,6 +585,24 @@ static int ask_remove_inode_eattr(struct gfs2_inode *ip,
return 0;
}
+/* complain_eas - complain about extended attribute errors for an inode
+ *
+ * @ip - in core inode pointer
+ * block - the block that had the problem
+ * duplicate - if this is a duplicate block, don't set it "free"
+ * emsg - what to tell the user about the eas being checked
+ * Returns: 1 if the EA is fixed, else 0 if it was not fixed.
+ */
+static void complain_eas(struct gfs2_inode *ip, uint64_t block,
+ const char *emsg)
+{
+ log_err(_("Inode #%llu (0x%llx): %s"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr, emsg);
+ log_err(_(" at block #%lld (0x%llx).\n"),
+ (unsigned long long)block, (unsigned long long)block);
+}
+
/* clear_eas - clear the extended attributes for an inode
*
* @ip - in core inode pointer
@@ -597,11 +615,7 @@ static int ask_remove_inode_eattr(struct gfs2_inode *ip,
static int clear_eas(struct gfs2_inode *ip, struct block_count *bc,
uint64_t block, int duplicate, const char *emsg)
{
- log_err( _("Inode #%llu (0x%llx): %s"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr, emsg);
- log_err( _(" at block #%lld (0x%llx).\n"),
- (unsigned long long)block, (unsigned long long)block);
+ complain_eas(ip, block, emsg);
if (query( _("Clear the bad Extended Attribute? (y/n) "))) {
if (block == ip->i_di.di_eattr) {
remove_inode_eattr(ip, bc);
@@ -646,11 +660,15 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
if (q != GFS2_BLKST_FREE) { /* Duplicate? */
add_duplicate_ref(ip, indirect, ref_as_ea, 0,
INODE_VALID);
- if (!clear_eas(ip, bc, indirect, 1,
- _("Bad indirect Extended Attribute "
- "duplicate found")))
- bc->ea_count++;
- return 1;
+ complain_eas(ip, indirect,
+ _("Bad indirect Extended Attribute "
+ "duplicate found"));
+ bc->ea_count++;
+ /* Return 0 here because if all that's wrong is a
+ duplicate block reference, we want pass1b to figure
+ it out. We don't want to delete all the extended
+ attributes as if they are in error. */
+ return 0;
}
clear_eas(ip, bc, indirect, 0,
_("Extended Attribute indirect block has incorrect "
@@ -658,16 +676,11 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
return 1;
}
if (q != GFS2_BLKST_FREE) { /* Duplicate? */
- log_err( _("Inode #%llu (0x%llx): Duplicate Extended "
- "Attribute indirect block found at #%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)indirect,
- (unsigned long long)indirect);
add_duplicate_ref(ip, indirect, ref_as_ea, 0, INODE_VALID);
+ complain_eas(ip, indirect,
+ _("Duplicate Extended Attribute indirect block"));
bc->ea_count++;
- ret = 1;
+ ret = 0; /* For the same reason stated above. */
} else {
fsck_blockmap_set(ip, indirect,
_("indirect Extended Attribute"), sdp->gfs1 ?
@@ -740,27 +753,34 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype,
If it isn't, clear it but don't count it as a duplicate. */
leaf_bh = bread(sdp, block);
if (gfs2_check_meta(leaf_bh, btype)) {
+ bc->ea_count++;
if (q != GFS2_BLKST_FREE) { /* Duplicate? */
add_duplicate_ref(ip, block, ref_as_ea, 0,
INODE_VALID);
- clear_eas(ip, bc, block, 1,
- _("Bad Extended Attribute duplicate found"));
- } else {
- clear_eas(ip, bc, block, 0,
- _("Extended Attribute leaf block "
- "has incorrect type"));
+ complain_eas(ip, block, _("Extended attribute leaf "
+ "duplicate found"));
+ /* Return 0 here because if all that's wrong is a
+ duplicate block reference, we want pass1b to figure
+ it out. We don't want to delete all the extended
+ attributes as if they are in error. */
+ return 0;
}
+ clear_eas(ip, bc, block, 0, _("Extended Attribute leaf block "
+ "has incorrect type"));
brelse(leaf_bh);
return 1;
}
if (q != GFS2_BLKST_FREE) { /* Duplicate? */
- log_debug( _("Duplicate block found at #%lld (0x%llx).\n"),
- (unsigned long long)block,
- (unsigned long long)block);
+ complain_eas(ip, block, _("Extended Attribute leaf "
+ "duplicate found"));
add_duplicate_ref(ip, block, ref_as_data, 0, INODE_VALID);
bc->ea_count++;
brelse(leaf_bh);
- return 1;
+ /* Return 0 here because if all that's wrong is a duplicate
+ block reference, we want pass1b to figure it out. We don't
+ want to delete all the extended attributes as if they are
+ in error. */
+ return 0;
}
if (ip->i_di.di_eattr == 0) {
/* Can only get in here if there were unrecoverable ea
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=28a73aac8c…
Commit: 28a73aac8c060378553cd161222e30c5b8d40865
Parent: f2bef761d91128dcb586a2a67202cdc6ce646eed
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Sep 23 15:11:53 2015 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Sep 29 13:23:31 2015 -0500
fsck.gfs2: Remove redundancy in add_duplicate_ref
Before this patch, when a duplicate reference was added to the list,
function add_duplicate_ref would print out an info message that said:
This brings the total to: X duplicate references.
I found this message to be redundant and confusing. It's much more
clear to simply say:
This brings the total to: X references
---
gfs2/fsck/util.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index a6a5cdc..b22abc6 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -402,8 +402,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 duplicate "
- "references\n"), dt->refs);
+ log_info( _("This brings the total to: %d references\n"),
+ dt->refs);
return meta_is_good;
}
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=f2bef761d9…
Commit: f2bef761d91128dcb586a2a67202cdc6ce646eed
Parent: f44e9910a604ae4d81b4e7acb8e8e1248fb3dddc
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Sep 23 15:09:09 2015 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Sep 29 13:23:27 2015 -0500
fsck.gfs2: Always restore saved value for di_eattr
There are times when function check_indirect_eattr saves off the value
of di_eattr in order to properly process the extended attributes.
The saved value must always be restored, if it exists, otherwise
we can accidentally remove an inode's EA reference.
---
gfs2/fsck/metawalk.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index bf187f9..bb03d1a 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1144,13 +1144,12 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect,
}
ea_leaf_ptr++;
}
+ /* If we temporarily nuked the ea block to prevent checking past
+ a corrupt ea leaf, we need to restore the saved di_eattr block. */
+ if (di_eattr_save != 0)
+ ip->i_di.di_eattr = di_eattr_save;
if (pass->finish_eattr_indir) {
if (!first_ea_is_bad) {
- /* If the first ea is good but subsequent ones were
- bad and deleted, we need to restore the saved
- di_eattr block. */
- if (leaf_pointer_errors)
- ip->i_di.di_eattr = di_eattr_save;
pass->finish_eattr_indir(ip, leaf_pointers,
leaf_pointer_errors,
pass->private);
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=f44e9910a6…
Commit: f44e9910a604ae4d81b4e7acb8e8e1248fb3dddc
Parent: 9944c79285b7a1bd65c7b5a27d0e682ed0fd9da3
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Sep 23 14:28:00 2015 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Sep 29 13:23:24 2015 -0500
fsck.gfs2: Once an indirect ea error is found, flag all that follow
Before this patch, function check_indirect_eattr could find an error
with an indirect extended attribute, but it would ignore subsequent
EA errors and return a good return code. That's bad. Once you find
an EA error in an indirect list, all the ones that follow should be
flagged as errors and subsequently cleared. The return code should
also reflect that an error was found during the processing. This
patch adds a second "err" variable to keep track of whether new errors
were found as opposed to whether _any_ errors were found in the list.
It also prints new error messages where the error was found and on all
pointers following the original error.
---
gfs2/fsck/metawalk.c | 28 +++++++++++++++++++++++-----
1 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index b4330fb..bf187f9 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1081,7 +1081,7 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect,
struct gfs2_buffer_head *indirect_buf,
struct metawalk_fxns *pass)
{
- int error = 0;
+ int error = 0, err;
uint64_t *ea_leaf_ptr, *end;
uint64_t block;
struct gfs2_sbd *sdp = ip->i_sbd;
@@ -1096,11 +1096,29 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect,
while (*ea_leaf_ptr && (ea_leaf_ptr < end)){
block = be64_to_cpu(*ea_leaf_ptr);
leaf_pointers++;
- error = check_leaf_eattr(ip, block, indirect, pass);
- if (error) {
+ err = check_leaf_eattr(ip, block, indirect, pass);
+ if (err) {
+ error = err;
+ log_err(_("Error detected in leaf block %lld (0x%llx) "
+ "referenced by indirect block %lld (0x%llx)"
+ ".\n"),
+ (unsigned long long)block,
+ (unsigned long long)block,
+ (unsigned long long)indirect,
+ (unsigned long long)indirect);
+ log_err(_("Subsequent leaf block pointers should be "
+ "cleared.\n"));
+ }
+ if (error) { /* leaf blocks following an error must also be
+ treated as error blocks and cleared. */
leaf_pointer_errors++;
- if (query( _("Fix the indirect block too? (y/n) ")))
- *ea_leaf_ptr = 0;
+ log_err(_("Pointer to EA leaf block %lld (0x%llx) in "
+ "indirect block %lld (0x%llx) should be "
+ "cleared.\n"),
+ (unsigned long long)block,
+ (unsigned long long)block,
+ (unsigned long long)indirect,
+ (unsigned long long)indirect);
}
/* If the first eattr lead is bad, we can't have a hole, so we
have to treat this as an unrecoverable eattr error and