From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bob Peterson Date: Mon, 28 Sep 2015 09:45:52 -0500 Subject: [Cluster-devel] [gfs2-utils PATCH 07/20] fsck.gfs2: Don't just assume the remaining EA reference is good In-Reply-To: References: Message-ID: List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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. rhbz#1257625 --- gfs2/fsck/pass1b.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file 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"), -- 2.4.3