commit 4707be4ee1e214cc420679650e1897b3b0817638 Author: Andrew Price 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 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++;