From 24fd37ac51ae4ab6c317c9ac8b146c7e17caaa0c Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 15 Aug 2024 11:49:36 -0700 Subject: [PATCH] xfs: report realtime refcount btree corruption errors to the health system Whenever we encounter corrupt realtime refcount btree blocks, we should report that to the health monitoring system for later reporting. Signed-off-by: Darrick J. Wong --- libxfs/xfs_fs.h | 1 + libxfs/xfs_health.h | 4 +++- libxfs/xfs_inode_fork.c | 4 +++- libxfs/xfs_refcount.c | 2 ++ libxfs/xfs_rtgroup.c | 1 + libxfs/xfs_rtrefcount_btree.c | 6 +++++- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index a89f4261a..99d4a03c3 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -993,6 +993,7 @@ struct xfs_rtgroup_geometry { #define XFS_RTGROUP_GEOM_SICK_BITMAP (1U << 1) /* rtbitmap */ #define XFS_RTGROUP_GEOM_SICK_SUMMARY (1U << 2) /* rtsummary */ #define XFS_RTGROUP_GEOM_SICK_RMAPBT (1U << 3) /* reverse mappings */ +#define XFS_RTGROUP_GEOM_SICK_REFCNTBT (1U << 4) /* reference counts */ /* * ioctl commands that are used by Linux filesystems diff --git a/libxfs/xfs_health.h b/libxfs/xfs_health.h index 87b38d0bc..65a4af590 100644 --- a/libxfs/xfs_health.h +++ b/libxfs/xfs_health.h @@ -69,6 +69,7 @@ struct xfs_rtgroup; #define XFS_SICK_RG_BITMAP (1 << 1) /* rt group bitmap */ #define XFS_SICK_RG_SUMMARY (1 << 2) /* rt groups summary */ #define XFS_SICK_RG_RMAPBT (1 << 3) /* reverse mappings */ +#define XFS_SICK_RG_REFCNTBT (1 << 4) /* reference counts */ /* Observable health issues for AG metadata. */ #define XFS_SICK_AG_SB (1 << 0) /* superblock */ @@ -115,7 +116,8 @@ struct xfs_rtgroup; #define XFS_SICK_RG_PRIMARY (XFS_SICK_RG_SUPER | \ XFS_SICK_RG_BITMAP | \ XFS_SICK_RG_SUMMARY | \ - XFS_SICK_RG_RMAPBT) + XFS_SICK_RG_RMAPBT | \ + XFS_SICK_RG_REFCNTBT) #define XFS_SICK_AG_PRIMARY (XFS_SICK_AG_SB | \ XFS_SICK_AG_AGF | \ diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 39cf5ef46..bffcb05ba 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -281,8 +281,10 @@ xfs_iformat_data_fork( return xfs_iformat_rtrmap(ip, dip); case XFS_DINODE_FMT_REFCOUNT: /* same comment about growfs and rmap inodes applies */ - if (!xfs_has_reflink(ip->i_mount)) + if (!xfs_has_reflink(ip->i_mount)) { + xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); return -EFSCORRUPTED; + } return xfs_iformat_rtrefcount(ip, dip); default: xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c index bc759e7db..e5035bb8a 100644 --- a/libxfs/xfs_refcount.c +++ b/libxfs/xfs_refcount.c @@ -2194,6 +2194,8 @@ xfs_refcount_recover_rtcow_leftovers( struct xfs_mount *mp, struct xfs_rtgroup *rtg) { + if (!xfs_has_rtgroups(mp)) + return 0; return xfs_refcount_recover_group_cow_leftovers(mp, NULL, rtg); } diff --git a/libxfs/xfs_rtgroup.c b/libxfs/xfs_rtgroup.c index 3f1fdd4d3..36e193d30 100644 --- a/libxfs/xfs_rtgroup.c +++ b/libxfs/xfs_rtgroup.c @@ -429,6 +429,7 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = { [XFS_RTGI_REFCOUNT] = { .name = "refcount", .metafile_type = XFS_METAFILE_RTREFCOUNT, + .sick = XFS_SICK_RG_REFCNTBT, .fmt_mask = 1U << XFS_DINODE_FMT_REFCOUNT, /* same comment about growfs and rmap inodes applies here */ .enabled = xfs_has_reflink, diff --git a/libxfs/xfs_rtrefcount_btree.c b/libxfs/xfs_rtrefcount_btree.c index ed6ef0356..1b98570e6 100644 --- a/libxfs/xfs_rtrefcount_btree.c +++ b/libxfs/xfs_rtrefcount_btree.c @@ -25,6 +25,7 @@ #include "xfs_rtgroup.h" #include "xfs_rtbitmap.h" #include "xfs_metafile.h" +#include "xfs_health.h" static struct kmem_cache *xfs_rtrefcountbt_cur_cache; @@ -358,6 +359,7 @@ const struct xfs_btree_ops xfs_rtrefcountbt_ops = { .lru_refs = XFS_REFC_BTREE_REF, .statoff = XFS_STATS_CALC_INDEX(xs_rtrefcbt_2), + .sick_mask = XFS_SICK_RG_REFCNTBT, .dup_cursor = xfs_rtrefcountbt_dup_cursor, .alloc_block = xfs_btree_alloc_metafile_block, @@ -625,8 +627,10 @@ xfs_iformat_rtrefcount( level = be16_to_cpu(dfp->bb_level); if (level > mp->m_rtrefc_maxlevels || - xfs_rtrefcount_droot_space_calc(level, numrecs) > dsize) + xfs_rtrefcount_droot_space_calc(level, numrecs) > dsize) { + xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); return -EFSCORRUPTED; + } xfs_iroot_alloc(ip, XFS_DATA_FORK, xfs_rtrefcount_broot_space_calc(mp, level, numrecs)); -- 2.50.1