commit 4707be4ee1e214cc420679650e1897b3b0817638
Author: Andrew Price <anprice@redhat.com>
Date: Fri Oct 18 19:43:48 2019 +0100
fsck.gfs2: Clear bad indirect block pointers when bitmap meets expectations
This issue only occurs when an indirect pointer of a 'system' directory
points to an invalid block but the block's bitmap state is as expected.
If the block's state is not as expected, the corruption is fixed by an
earlier check.
In this scenario, pass1_check_metalist() checks the type of a block and
compares it with what it expected the indirect pointer to point to. If
there is a metadata mismatch a bad indirect pointer is reported but the
entire inode is considered invalid, causing it to be removed later, or
rebuilt in the case of protected structures such as the root inode.
This is heavy-handed and the right thing to do is to zero the indirect
block pointer.
Previously we had no access to the pointer block itself to update it in
pass1_check_metalist() but now that an iptr is passed in, it's just a
case of zeroing the pointer at the correct offset and marking the bh as
modified. This means that fsck.gfs2 can now fix bad indirect pointers of
the root directory without throwing away the entire directory tree.
Resolves: rhbz#1487726
Signed-off-by: Andrew Price <anprice@redhat.com>
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 66cf6dc6..deef1425 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -401,8 +401,15 @@ static int pass1_check_metalist(struct iptr iptr, struct gfs2_buffer_head **bh,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)block,
(unsigned long long)block, blktypedesc);
- brelse(nbh);
- return meta_skip_further;
+ if (query(_("Zero the indirect block pointer? (y/n) "))){
+ *iptr_ptr(iptr) = 0;
+ bmodified(iptr.ipt_bh);
+ *is_valid = 1;
+ return meta_skip_one;
+ } else {
+ brelse(nbh);
+ return meta_skip_further;
+ }
}
bc->indir_count++;