gfs2-utils: master - fsck.gfs2: Don't just assume the remaining EA reference is good

Bob Peterson rpeterso at fedoraproject.org
Tue Sep 29 18:38:00 UTC 2015


Gitweb:        http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=af10124e7a98670e049797b5f59f8b2331c583d1
Commit:        af10124e7a98670e049797b5f59f8b2331c583d1
Parent:        cd7a3ddc01a243bc571dd281a9d70e7b1b4dc8fa
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Wed Sep 23 12:58:55 2015 -0500
Committer:     Bob Peterson <rpeterso at redhat.com>
CommitterDate: Tue Sep 29 13:23:10 2015 -0500

fsck.gfs2: Don't just assume the remaining EA reference is good

When pass1b is resolving duplicate block references, it pares them
down to the last reference, then sets the block type from that
last reference. However, the last reference might be bad too.
For example, consider a block referenced as data by two corrupt inodes
and referenced as an extended attribute by a third corrupt inode.
In pass1b, it might eliminate the two inodes that referenced it as
data, then set the block as extended attribute based on the remaining
reference. However, if the block is not really an extended attribute,
that would be an error that would only be caught on a subsequent run.
This patch adds a check to make sure the remaining reference as an
extended attribute is also valid. If not, the block is freed.
---
 gfs2/fsck/pass1b.c |   39 ++++++++++++++++++++++++++++++++++-----
 1 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index 83a506c..4d16635 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -417,11 +417,40 @@ static void resolve_last_reference(struct gfs2_sbd *sdp, struct duptree *dt,
 					  sdp->gfs1 ? GFS2_BLKST_DINODE :
 					  GFS2_BLKST_USED);
 	} else {
-		fsck_blockmap_set(ip, dt->block,
-				  _("reference-repaired extended "
-				    "attribute"),
-				  sdp->gfs1 ? GFS2_BLKST_DINODE :
-				  GFS2_BLKST_USED);
+		if (acceptable_ref == ref_as_ea)
+			fsck_blockmap_set(ip, dt->block,
+					  _("reference-repaired extended "
+					    "attribute"),
+					  sdp->gfs1 ? GFS2_BLKST_DINODE :
+					  GFS2_BLKST_USED);
+		else {
+			log_err(_("Error: The remaining reference to block "
+				  " %lld (0x%llx) is as extended attribute, "
+				  "in inode %lld (0x%llx) but the block is "
+				  "not an EA.\n"),
+				(unsigned long long)dt->block,
+				(unsigned long long)dt->block,
+				(unsigned long long)id->block_no,
+				(unsigned long long)id->block_no);
+			if (query(_("Okay to remove the bad extended "
+				    "attribute from inode %lld (0x%llx)? "
+				    "(y/n) "),
+				  (unsigned long long)id->block_no,
+				  (unsigned long long)id->block_no)) {
+				ip->i_di.di_eattr = 0;
+				ip->i_di.di_flags &= ~GFS2_DIF_EA_INDIRECT;
+				ip->i_di.di_blocks--;
+				bmodified(ip->i_bh);
+				fsck_blockmap_set(ip, dt->block,
+						  _("reference-repaired EA"),
+						  GFS2_BLKST_FREE);
+				log_err(_("The bad extended attribute was "
+					  "removed.\n"));
+			} else {
+				log_err(_("The bad extended attribute was not "
+					  "removed.\n"));
+			}
+		}
 	}
 	fsck_inode_put(&ip); /* out, brelse, free */
 	log_debug(_("Done with duplicate reference to block 0x%llx\n"),


More information about the cluster-commits mailing list