xfs: complain about bad file mapping records in the ondisk bmbt
authorDarrick J. Wong <djwong@kernel.org>
Wed, 12 Apr 2023 02:00:05 +0000 (19:00 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 12 Apr 2023 02:00:05 +0000 (19:00 -0700)
Similar to what we've just done for the other btrees, create a function
to log corrupt bmbt records and call it whenever we encounter a bad
record in the ondisk btree.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/libxfs/xfs_inode_fork.c

index 0b4fb39..5e66807 100644 (file)
@@ -1083,6 +1083,34 @@ struct xfs_iread_state {
        xfs_extnum_t            loaded;
 };
 
+int
+xfs_bmap_complain_bad_rec(
+       struct xfs_inode                *ip,
+       int                             whichfork,
+       xfs_failaddr_t                  fa,
+       const struct xfs_bmbt_irec      *irec)
+{
+       struct xfs_mount                *mp = ip->i_mount;
+       const char                      *forkname;
+
+       switch (whichfork) {
+       case XFS_DATA_FORK:     forkname = "data"; break;
+       case XFS_ATTR_FORK:     forkname = "attr"; break;
+       case XFS_COW_FORK:      forkname = "CoW"; break;
+       default:                forkname = "???"; break;
+       }
+
+       xfs_warn(mp,
+ "Bmap BTree record corruption in inode 0x%llx %s fork detected at %pS!",
+                               ip->i_ino, forkname, fa);
+       xfs_warn(mp,
+               "Offset 0x%llx, start block 0x%llx, block count 0x%llx state 0x%x",
+               irec->br_startoff, irec->br_startblock, irec->br_blockcount,
+               irec->br_state);
+
+       return -EFSCORRUPTED;
+}
+
 /* Stuff every bmbt record from this block into the incore extent map. */
 static int
 xfs_iread_bmbt_block(
@@ -1125,7 +1153,8 @@ xfs_iread_bmbt_block(
                        xfs_inode_verifier_error(ip, -EFSCORRUPTED,
                                        "xfs_iread_extents(2)", frp,
                                        sizeof(*frp), fa);
-                       return -EFSCORRUPTED;
+                       return xfs_bmap_complain_bad_rec(ip, whichfork, fa,
+                                       &new);
                }
                xfs_iext_insert(ip, &ir->icur, &new,
                                xfs_bmap_fork_to_state(whichfork));
index e5a4920..9ff030d 100644 (file)
@@ -265,6 +265,8 @@ static inline uint32_t xfs_bmap_fork_to_state(int whichfork)
 
 xfs_failaddr_t xfs_bmap_validate_extent(struct xfs_inode *ip, int whichfork,
                struct xfs_bmbt_irec *irec);
+int xfs_bmap_complain_bad_rec(struct xfs_inode *ip, int whichfork,
+               xfs_failaddr_t fa, const struct xfs_bmbt_irec *irec);
 
 int    xfs_bmapi_remap(struct xfs_trans *tp, struct xfs_inode *ip,
                xfs_fileoff_t bno, xfs_filblks_t len, xfs_fsblock_t startblock,
index 6b21760..ff37eec 100644 (file)
@@ -140,7 +140,8 @@ xfs_iformat_extents(
                                xfs_inode_verifier_error(ip, -EFSCORRUPTED,
                                                "xfs_iformat_extents(2)",
                                                dp, sizeof(*dp), fa);
-                               return -EFSCORRUPTED;
+                               return xfs_bmap_complain_bad_rec(ip, whichfork,
+                                               fa, &new);
                        }
 
                        xfs_iext_insert(ip, &icur, &new, state);