diff options
author | Dave Chinner <dchinner@redhat.com> | 2023-11-10 07:33:13 +0300 |
---|---|---|
committer | Chandan Babu R <chandanbabu@kernel.org> | 2023-11-13 06:41:41 +0300 |
commit | 038ca189c0d2c1570b4d922f25b524007c85cf94 (patch) | |
tree | 9d78b83cdab4c29dbdd53e6fa6e89b029b36897a /fs/xfs/xfs_inode_item_recover.c | |
parent | a2e4388adfa44684c7c428a5a5980efe0d75e13e (diff) | |
download | linux-038ca189c0d2c1570b4d922f25b524007c85cf94.tar.xz |
xfs: inode recovery does not validate the recovered inode
Discovered when trying to track down a weird recovery corruption
issue that wasn't detected at recovery time.
The specific corruption was a zero extent count field when big
extent counts are in use, and it turns out the dinode verifier
doesn't detect that specific corruption case, either. So fix it too.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
Diffstat (limited to 'fs/xfs/xfs_inode_item_recover.c')
-rw-r--r-- | fs/xfs/xfs_inode_item_recover.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/fs/xfs/xfs_inode_item_recover.c b/fs/xfs/xfs_inode_item_recover.c index 0e5dba2343ea..1c5ba2a732b0 100644 --- a/fs/xfs/xfs_inode_item_recover.c +++ b/fs/xfs/xfs_inode_item_recover.c @@ -286,6 +286,7 @@ xlog_recover_inode_commit_pass2( struct xfs_log_dinode *ldip; uint isize; int need_free = 0; + xfs_failaddr_t fa; if (item->ri_buf[0].i_len == sizeof(struct xfs_inode_log_format)) { in_f = item->ri_buf[0].i_addr; @@ -528,8 +529,19 @@ out_owner_change: (dip->di_mode != 0)) error = xfs_recover_inode_owner_change(mp, dip, in_f, buffer_list); - /* re-generate the checksum. */ + /* re-generate the checksum and validate the recovered inode. */ xfs_dinode_calc_crc(log->l_mp, dip); + fa = xfs_dinode_verify(log->l_mp, in_f->ilf_ino, dip); + if (fa) { + XFS_CORRUPTION_ERROR( + "Bad dinode after recovery", + XFS_ERRLEVEL_LOW, mp, dip, sizeof(*dip)); + xfs_alert(mp, + "Metadata corruption detected at %pS, inode 0x%llx", + fa, in_f->ilf_ino); + error = -EFSCORRUPTED; + goto out_release; + } ASSERT(bp->b_mount == mp); bp->b_flags |= _XBF_LOGRECOVERY; |