xfs: record rt group metadata errors in the health system
authorDarrick J. Wong <djwong@kernel.org>
Mon, 4 Nov 2024 04:19:21 +0000 (20:19 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 5 Nov 2024 21:38:40 +0000 (13:38 -0800)
Record the state of per-rtgroup metadata sickness in the rtgroup
structure for later reporting.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_health.h
fs/xfs/libxfs/xfs_rtbitmap.c
fs/xfs/libxfs/xfs_rtgroup.c
fs/xfs/libxfs/xfs_rtgroup.h
fs/xfs/scrub/health.c
fs/xfs/xfs_health.c
fs/xfs/xfs_trace.h

index a23df94..3d93b57 100644 (file)
@@ -54,6 +54,7 @@ struct xfs_inode;
 struct xfs_fsop_geom;
 struct xfs_btree_cur;
 struct xfs_da_args;
+struct xfs_rtgroup;
 
 /* Observable health issues for metadata spanning the entire filesystem. */
 #define XFS_SICK_FS_COUNTERS   (1 << 0)  /* summary counters */
@@ -65,9 +66,10 @@ struct xfs_da_args;
 #define XFS_SICK_FS_METADIR    (1 << 6)  /* metadata directory tree */
 #define XFS_SICK_FS_METAPATH   (1 << 7)  /* metadata directory tree path */
 
-/* Observable health issues for realtime volume metadata. */
-#define XFS_SICK_RT_BITMAP     (1 << 0)  /* realtime bitmap */
-#define XFS_SICK_RT_SUMMARY    (1 << 1)  /* realtime summary */
+/* Observable health issues for realtime group metadata. */
+#define XFS_SICK_RG_SUPER      (1 << 0)  /* rt group superblock */
+#define XFS_SICK_RG_BITMAP     (1 << 1)  /* rt group bitmap */
+#define XFS_SICK_RG_SUMMARY    (1 << 2)  /* rt groups summary */
 
 /* Observable health issues for AG metadata. */
 #define XFS_SICK_AG_SB         (1 << 0)  /* superblock */
@@ -111,8 +113,9 @@ struct xfs_da_args;
                                 XFS_SICK_FS_METADIR | \
                                 XFS_SICK_FS_METAPATH)
 
-#define XFS_SICK_RT_PRIMARY    (XFS_SICK_RT_BITMAP | \
-                                XFS_SICK_RT_SUMMARY)
+#define XFS_SICK_RG_PRIMARY    (XFS_SICK_RG_SUPER | \
+                                XFS_SICK_RG_BITMAP | \
+                                XFS_SICK_RG_SUMMARY)
 
 #define XFS_SICK_AG_PRIMARY    (XFS_SICK_AG_SB | \
                                 XFS_SICK_AG_AGF | \
@@ -142,26 +145,26 @@ struct xfs_da_args;
 
 /* Secondary state related to (but not primary evidence of) health problems. */
 #define XFS_SICK_FS_SECONDARY  (0)
-#define XFS_SICK_RT_SECONDARY  (0)
+#define XFS_SICK_RG_SECONDARY  (0)
 #define XFS_SICK_AG_SECONDARY  (0)
 #define XFS_SICK_INO_SECONDARY (XFS_SICK_INO_FORGET)
 
 /* Evidence of health problems elsewhere. */
 #define XFS_SICK_FS_INDIRECT   (0)
-#define XFS_SICK_RT_INDIRECT   (0)
+#define XFS_SICK_RG_INDIRECT   (0)
 #define XFS_SICK_AG_INDIRECT   (XFS_SICK_AG_INODES)
 #define XFS_SICK_INO_INDIRECT  (0)
 
 /* All health masks. */
-#define XFS_SICK_FS_ALL        (XFS_SICK_FS_PRIMARY | \
+#define XFS_SICK_FS_ALL                (XFS_SICK_FS_PRIMARY | \
                                 XFS_SICK_FS_SECONDARY | \
                                 XFS_SICK_FS_INDIRECT)
 
-#define XFS_SICK_RT_ALL        (XFS_SICK_RT_PRIMARY | \
-                                XFS_SICK_RT_SECONDARY | \
-                                XFS_SICK_RT_INDIRECT)
+#define XFS_SICK_RG_ALL                (XFS_SICK_RG_PRIMARY | \
+                                XFS_SICK_RG_SECONDARY | \
+                                XFS_SICK_RG_INDIRECT)
 
-#define XFS_SICK_AG_ALL        (XFS_SICK_AG_PRIMARY | \
+#define XFS_SICK_AG_ALL                (XFS_SICK_AG_PRIMARY | \
                                 XFS_SICK_AG_SECONDARY | \
                                 XFS_SICK_AG_INDIRECT)
 
@@ -195,11 +198,8 @@ void xfs_fs_mark_healthy(struct xfs_mount *mp, unsigned int mask);
 void xfs_fs_measure_sickness(struct xfs_mount *mp, unsigned int *sick,
                unsigned int *checked);
 
-void xfs_rt_mark_sick(struct xfs_mount *mp, unsigned int mask);
-void xfs_rt_mark_corrupt(struct xfs_mount *mp, unsigned int mask);
-void xfs_rt_mark_healthy(struct xfs_mount *mp, unsigned int mask);
-void xfs_rt_measure_sickness(struct xfs_mount *mp, unsigned int *sick,
-               unsigned int *checked);
+void xfs_rgno_mark_sick(struct xfs_mount *mp, xfs_rgnumber_t rgno,
+               unsigned int mask);
 
 void xfs_agno_mark_sick(struct xfs_mount *mp, xfs_agnumber_t agno,
                unsigned int mask);
@@ -244,11 +244,17 @@ xfs_group_has_sickness(
        xfs_group_measure_sickness(xg, &sick, &checked);
        return sick & mask;
 }
+
 #define xfs_ag_has_sickness(pag, mask) \
        xfs_group_has_sickness(pag_group(pag), (mask))
 #define xfs_ag_is_healthy(pag) \
        (!xfs_ag_has_sickness((pag), UINT_MAX))
 
+#define xfs_rtgroup_has_sickness(rtg, mask) \
+       xfs_group_has_sickness(rtg_group(rtg), (mask))
+#define xfs_rtgroup_is_healthy(rtg) \
+       (!xfs_rtgroup_has_sickness((rtg), UINT_MAX))
+
 static inline bool
 xfs_inode_has_sickness(struct xfs_inode *ip, unsigned int mask)
 {
index 416bbcd..e201064 100644 (file)
@@ -76,28 +76,31 @@ static int
 xfs_rtbuf_get(
        struct xfs_rtalloc_args *args,
        xfs_fileoff_t           block,  /* block number in bitmap or summary */
-       int                     issum)  /* is summary not bitmap */
+       enum xfs_rtg_inodes     type)
 {
+       struct xfs_inode        *ip = args->rtg->rtg_inodes[type];
        struct xfs_mount        *mp = args->mp;
        struct xfs_buf          **cbpp; /* cached block buffer */
        xfs_fileoff_t           *coffp; /* cached block number */
        struct xfs_buf          *bp;    /* block buffer, result */
-       struct xfs_inode        *ip;    /* bitmap or summary inode */
        struct xfs_bmbt_irec    map;
-       enum xfs_blft           type;
+       enum xfs_blft           buf_type;
        int                     nmap = 1;
        int                     error;
 
-       if (issum) {
+       switch (type) {
+       case XFS_RTGI_SUMMARY:
                cbpp = &args->sumbp;
                coffp = &args->sumoff;
-               ip = args->rtg->rtg_inodes[XFS_RTGI_SUMMARY];
-               type = XFS_BLFT_RTSUMMARY_BUF;
-       } else {
+               buf_type = XFS_BLFT_RTSUMMARY_BUF;
+               break;
+       case XFS_RTGI_BITMAP:
                cbpp = &args->rbmbp;
                coffp = &args->rbmoff;
-               ip = args->rtg->rtg_inodes[XFS_RTGI_BITMAP];
-               type = XFS_BLFT_RTBITMAP_BUF;
+               buf_type = XFS_BLFT_RTBITMAP_BUF;
+               break;
+       default:
+               return -EINVAL;
        }
 
        /*
@@ -120,8 +123,7 @@ xfs_rtbuf_get(
                return error;
 
        if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map))) {
-               xfs_rt_mark_sick(mp, issum ? XFS_SICK_RT_SUMMARY :
-                                            XFS_SICK_RT_BITMAP);
+               xfs_rtginode_mark_sick(args->rtg, type);
                return -EFSCORRUPTED;
        }
 
@@ -130,12 +132,11 @@ xfs_rtbuf_get(
                                   XFS_FSB_TO_DADDR(mp, map.br_startblock),
                                   mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
        if (xfs_metadata_is_sick(error))
-               xfs_rt_mark_sick(mp, issum ? XFS_SICK_RT_SUMMARY :
-                                            XFS_SICK_RT_BITMAP);
+               xfs_rtginode_mark_sick(args->rtg, type);
        if (error)
                return error;
 
-       xfs_trans_buf_set_type(args->tp, bp, type);
+       xfs_trans_buf_set_type(args->tp, bp, buf_type);
        *cbpp = bp;
        *coffp = block;
        return 0;
@@ -149,11 +150,11 @@ xfs_rtbitmap_read_buf(
        struct xfs_mount                *mp = args->mp;
 
        if (XFS_IS_CORRUPT(mp, block >= mp->m_sb.sb_rbmblocks)) {
-               xfs_rt_mark_sick(mp, XFS_SICK_RT_BITMAP);
+               xfs_rtginode_mark_sick(args->rtg, XFS_RTGI_BITMAP);
                return -EFSCORRUPTED;
        }
 
-       return xfs_rtbuf_get(args, block, 0);
+       return xfs_rtbuf_get(args, block, XFS_RTGI_BITMAP);
 }
 
 int
@@ -164,10 +165,10 @@ xfs_rtsummary_read_buf(
        struct xfs_mount                *mp = args->mp;
 
        if (XFS_IS_CORRUPT(mp, block >= mp->m_rsumblocks)) {
-               xfs_rt_mark_sick(args->mp, XFS_SICK_RT_SUMMARY);
+               xfs_rtginode_mark_sick(args->rtg, XFS_RTGI_SUMMARY);
                return -EFSCORRUPTED;
        }
-       return xfs_rtbuf_get(args, block, 1);
+       return xfs_rtbuf_get(args, block, XFS_RTGI_SUMMARY);
 }
 
 /*
index 470260c..790a0b8 100644 (file)
@@ -271,6 +271,8 @@ struct xfs_rtginode_ops {
 
        enum xfs_metafile_type  metafile_type;
 
+       unsigned int            sick;   /* rtgroup sickness flag */
+
        /* Does the fs have this feature? */
        bool                    (*enabled)(struct xfs_mount *mp);
 
@@ -285,11 +287,13 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = {
        [XFS_RTGI_BITMAP] = {
                .name           = "bitmap",
                .metafile_type  = XFS_METAFILE_RTBITMAP,
+               .sick           = XFS_SICK_RG_BITMAP,
                .create         = xfs_rtbitmap_create,
        },
        [XFS_RTGI_SUMMARY] = {
                .name           = "summary",
                .metafile_type  = XFS_METAFILE_RTSUMMARY,
+               .sick           = XFS_SICK_RG_SUMMARY,
                .create         = xfs_rtsummary_create,
        },
 };
@@ -323,6 +327,17 @@ xfs_rtginode_enabled(
        return ops->enabled(rtg_mount(rtg));
 }
 
+/* Mark an rtgroup inode sick */
+void
+xfs_rtginode_mark_sick(
+       struct xfs_rtgroup      *rtg,
+       enum xfs_rtg_inodes     type)
+{
+       const struct xfs_rtginode_ops *ops = &xfs_rtginode_ops[type];
+
+       xfs_group_mark_sick(rtg_group(rtg), ops->sick);
+}
+
 /* Load and existing rtgroup inode into the rtgroup structure. */
 int
 xfs_rtginode_load(
@@ -358,8 +373,10 @@ xfs_rtginode_load(
        } else {
                const char      *path;
 
-               if (!mp->m_rtdirip)
+               if (!mp->m_rtdirip) {
+                       xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR);
                        return -EFSCORRUPTED;
+               }
 
                path = xfs_rtginode_path(rtg_rgno(rtg), type);
                if (!path)
@@ -369,17 +386,22 @@ xfs_rtginode_load(
                kfree(path);
        }
 
-       if (error)
+       if (error) {
+               if (xfs_metadata_is_sick(error))
+                       xfs_rtginode_mark_sick(rtg, type);
                return error;
+       }
 
        if (XFS_IS_CORRUPT(mp, ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
                               ip->i_df.if_format != XFS_DINODE_FMT_BTREE)) {
                xfs_irele(ip);
+               xfs_rtginode_mark_sick(rtg, type);
                return -EFSCORRUPTED;
        }
 
        if (XFS_IS_CORRUPT(mp, ip->i_projid != rtg_rgno(rtg))) {
                xfs_irele(ip);
+               xfs_rtginode_mark_sick(rtg, type);
                return -EFSCORRUPTED;
        }
 
@@ -416,8 +438,10 @@ xfs_rtginode_create(
        if (!xfs_rtginode_enabled(rtg, type))
                return 0;
 
-       if (!mp->m_rtdirip)
+       if (!mp->m_rtdirip) {
+               xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR);
                return -EFSCORRUPTED;
+       }
 
        upd.path = xfs_rtginode_path(rtg_rgno(rtg), type);
        if (!upd.path)
@@ -464,8 +488,10 @@ int
 xfs_rtginode_mkdir_parent(
        struct xfs_mount        *mp)
 {
-       if (!mp->m_metadirip)
+       if (!mp->m_metadirip) {
+               xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR);
                return -EFSCORRUPTED;
+       }
 
        return xfs_metadir_mkdir(mp->m_metadirip, "rtgroups", &mp->m_rtdirip);
 }
@@ -477,8 +503,10 @@ xfs_rtginode_load_parent(
 {
        struct xfs_mount        *mp = tp->t_mountp;
 
-       if (!mp->m_metadirip)
+       if (!mp->m_metadirip) {
+               xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR);
                return -EFSCORRUPTED;
+       }
 
        return xfs_metadir_load(tp, mp->m_metadirip, "rtgroups",
                        XFS_METAFILE_DIR, &mp->m_rtdirip);
index e7679fa..fba62b2 100644 (file)
@@ -240,6 +240,7 @@ int xfs_rtginode_load_parent(struct xfs_trans *tp);
 const char *xfs_rtginode_name(enum xfs_rtg_inodes type);
 enum xfs_metafile_type xfs_rtginode_metafile_type(enum xfs_rtg_inodes type);
 bool xfs_rtginode_enabled(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type);
+void xfs_rtginode_mark_sick(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type);
 int xfs_rtginode_load(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type,
                struct xfs_trans *tp);
 int xfs_rtginode_create(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type,
index b8b92ff..7547fb5 100644 (file)
@@ -12,6 +12,7 @@
 #include "xfs_btree.h"
 #include "xfs_ag.h"
 #include "xfs_health.h"
+#include "xfs_rtgroup.h"
 #include "scrub/scrub.h"
 #include "scrub/health.h"
 #include "scrub/common.h"
@@ -71,9 +72,9 @@
 
 enum xchk_health_group {
        XHG_FS = 1,
-       XHG_RT,
        XHG_AG,
        XHG_INO,
+       XHG_RTGROUP,
 };
 
 struct xchk_health_map {
@@ -100,8 +101,8 @@ static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = {
        [XFS_SCRUB_TYPE_XATTR]          = { XHG_INO, XFS_SICK_INO_XATTR },
        [XFS_SCRUB_TYPE_SYMLINK]        = { XHG_INO, XFS_SICK_INO_SYMLINK },
        [XFS_SCRUB_TYPE_PARENT]         = { XHG_INO, XFS_SICK_INO_PARENT },
-       [XFS_SCRUB_TYPE_RTBITMAP]       = { XHG_RT,  XFS_SICK_RT_BITMAP },
-       [XFS_SCRUB_TYPE_RTSUM]          = { XHG_RT,  XFS_SICK_RT_SUMMARY },
+       [XFS_SCRUB_TYPE_RTBITMAP]       = { XHG_RTGROUP, XFS_SICK_RG_BITMAP },
+       [XFS_SCRUB_TYPE_RTSUM]          = { XHG_RTGROUP, XFS_SICK_RG_SUMMARY },
        [XFS_SCRUB_TYPE_UQUOTA]         = { XHG_FS,  XFS_SICK_FS_UQUOTA },
        [XFS_SCRUB_TYPE_GQUOTA]         = { XHG_FS,  XFS_SICK_FS_GQUOTA },
        [XFS_SCRUB_TYPE_PQUOTA]         = { XHG_FS,  XFS_SICK_FS_PQUOTA },
@@ -162,11 +163,13 @@ xchk_mark_all_healthy(
        struct xfs_mount        *mp)
 {
        struct xfs_perag        *pag = NULL;
+       struct xfs_rtgroup      *rtg = NULL;
 
        xfs_fs_mark_healthy(mp, XFS_SICK_FS_INDIRECT);
-       xfs_rt_mark_healthy(mp, XFS_SICK_RT_INDIRECT);
        while ((pag = xfs_perag_next(mp, pag)))
                xfs_group_mark_healthy(pag_group(pag), XFS_SICK_AG_INDIRECT);
+       while ((rtg = xfs_rtgroup_next(mp, rtg)))
+               xfs_group_mark_healthy(rtg_group(rtg), XFS_SICK_RG_INDIRECT);
 }
 
 /*
@@ -184,6 +187,7 @@ xchk_update_health(
        struct xfs_scrub        *sc)
 {
        struct xfs_perag        *pag;
+       struct xfs_rtgroup      *rtg;
        bool                    bad;
 
        /*
@@ -236,11 +240,13 @@ xchk_update_health(
                else
                        xfs_fs_mark_healthy(sc->mp, sc->sick_mask);
                break;
-       case XHG_RT:
+       case XHG_RTGROUP:
+               rtg = xfs_rtgroup_get(sc->mp, sc->sm->sm_agno);
                if (bad)
-                       xfs_rt_mark_corrupt(sc->mp, sc->sick_mask);
+                       xfs_group_mark_corrupt(rtg_group(rtg), sc->sick_mask);
                else
-                       xfs_rt_mark_healthy(sc->mp, sc->sick_mask);
+                       xfs_group_mark_healthy(rtg_group(rtg), sc->sick_mask);
+               xfs_rtgroup_put(rtg);
                break;
        default:
                ASSERT(0);
@@ -295,6 +301,7 @@ xchk_health_record(
 {
        struct xfs_mount        *mp = sc->mp;
        struct xfs_perag        *pag = NULL;
+       struct xfs_rtgroup      *rtg = NULL;
        unsigned int            sick;
        unsigned int            checked;
 
@@ -302,15 +309,17 @@ xchk_health_record(
        if (sick & XFS_SICK_FS_PRIMARY)
                xchk_set_corrupt(sc);
 
-       xfs_rt_measure_sickness(mp, &sick, &checked);
-       if (sick & XFS_SICK_RT_PRIMARY)
-               xchk_set_corrupt(sc);
-
        while ((pag = xfs_perag_next(mp, pag))) {
                xfs_group_measure_sickness(pag_group(pag), &sick, &checked);
                if (sick & XFS_SICK_AG_PRIMARY)
                        xchk_set_corrupt(sc);
        }
 
+       while ((rtg = xfs_rtgroup_next(mp, rtg))) {
+               xfs_group_measure_sickness(rtg_group(rtg), &sick, &checked);
+               if (sick & XFS_SICK_RG_PRIMARY)
+                       xchk_set_corrupt(sc);
+       }
+
        return 0;
 }
index b0d0c6b..9d8ee01 100644 (file)
 #include "xfs_da_format.h"
 #include "xfs_da_btree.h"
 #include "xfs_quota_defs.h"
+#include "xfs_rtgroup.h"
+
+static void
+xfs_health_unmount_group(
+       struct xfs_group        *xg,
+       bool                    *warn)
+{
+       unsigned int            sick = 0;
+       unsigned int            checked = 0;
+
+       xfs_group_measure_sickness(xg, &sick, &checked);
+       if (sick) {
+               trace_xfs_group_unfixed_corruption(xg, sick);
+               *warn = true;
+       }
+}
 
 /*
  * Warn about metadata corruption that we detected but haven't fixed, and
@@ -29,6 +45,7 @@ xfs_health_unmount(
        struct xfs_mount        *mp)
 {
        struct xfs_perag        *pag = NULL;
+       struct xfs_rtgroup      *rtg = NULL;
        unsigned int            sick = 0;
        unsigned int            checked = 0;
        bool                    warn = false;
@@ -37,21 +54,12 @@ xfs_health_unmount(
                return;
 
        /* Measure AG corruption levels. */
-       while ((pag = xfs_perag_next(mp, pag))) {
-               xfs_group_measure_sickness(pag_group(pag), &sick, &checked);
-               if (sick) {
-                       trace_xfs_group_unfixed_corruption(pag_group(pag),
-                                       sick);
-                       warn = true;
-               }
-       }
+       while ((pag = xfs_perag_next(mp, pag)))
+               xfs_health_unmount_group(pag_group(pag), &warn);
 
-       /* Measure realtime volume corruption levels. */
-       xfs_rt_measure_sickness(mp, &sick, &checked);
-       if (sick) {
-               trace_xfs_rt_unfixed_corruption(mp, sick);
-               warn = true;
-       }
+       /* Measure realtime group corruption levels. */
+       while ((rtg = xfs_rtgroup_next(mp, rtg)))
+               xfs_health_unmount_group(rtg_group(rtg), &warn);
 
        /*
         * Measure fs corruption and keep the sample around for the warning.
@@ -150,65 +158,6 @@ xfs_fs_measure_sickness(
        spin_unlock(&mp->m_sb_lock);
 }
 
-/* Mark unhealthy realtime metadata. */
-void
-xfs_rt_mark_sick(
-       struct xfs_mount        *mp,
-       unsigned int            mask)
-{
-       ASSERT(!(mask & ~XFS_SICK_RT_ALL));
-       trace_xfs_rt_mark_sick(mp, mask);
-
-       spin_lock(&mp->m_sb_lock);
-       mp->m_rt_sick |= mask;
-       spin_unlock(&mp->m_sb_lock);
-}
-
-/* Mark realtime metadata as having been checked and found unhealthy by fsck. */
-void
-xfs_rt_mark_corrupt(
-       struct xfs_mount        *mp,
-       unsigned int            mask)
-{
-       ASSERT(!(mask & ~XFS_SICK_RT_ALL));
-       trace_xfs_rt_mark_corrupt(mp, mask);
-
-       spin_lock(&mp->m_sb_lock);
-       mp->m_rt_sick |= mask;
-       mp->m_rt_checked |= mask;
-       spin_unlock(&mp->m_sb_lock);
-}
-
-/* Mark a realtime metadata healed. */
-void
-xfs_rt_mark_healthy(
-       struct xfs_mount        *mp,
-       unsigned int            mask)
-{
-       ASSERT(!(mask & ~XFS_SICK_RT_ALL));
-       trace_xfs_rt_mark_healthy(mp, mask);
-
-       spin_lock(&mp->m_sb_lock);
-       mp->m_rt_sick &= ~mask;
-       if (!(mp->m_rt_sick & XFS_SICK_RT_PRIMARY))
-               mp->m_rt_sick &= ~XFS_SICK_RT_SECONDARY;
-       mp->m_rt_checked |= mask;
-       spin_unlock(&mp->m_sb_lock);
-}
-
-/* Sample which realtime metadata are unhealthy. */
-void
-xfs_rt_measure_sickness(
-       struct xfs_mount        *mp,
-       unsigned int            *sick,
-       unsigned int            *checked)
-{
-       spin_lock(&mp->m_sb_lock);
-       *sick = mp->m_rt_sick;
-       *checked = mp->m_rt_checked;
-       spin_unlock(&mp->m_sb_lock);
-}
-
 /* Mark unhealthy per-ag metadata given a raw AG number. */
 void
 xfs_agno_mark_sick(
@@ -226,13 +175,24 @@ xfs_agno_mark_sick(
        xfs_perag_put(pag);
 }
 
+static inline void
+xfs_group_check_mask(
+       struct xfs_group        *xg,
+       unsigned int            mask)
+{
+       if (xg->xg_type == XG_TYPE_AG)
+               ASSERT(!(mask & ~XFS_SICK_AG_ALL));
+       else
+               ASSERT(!(mask & ~XFS_SICK_RG_ALL));
+}
+
 /* Mark unhealthy per-ag metadata. */
 void
 xfs_group_mark_sick(
        struct xfs_group        *xg,
        unsigned int            mask)
 {
-       ASSERT(!(mask & ~XFS_SICK_AG_ALL));
+       xfs_group_check_mask(xg, mask);
        trace_xfs_group_mark_sick(xg, mask);
 
        spin_lock(&xg->xg_state_lock);
@@ -248,7 +208,7 @@ xfs_group_mark_corrupt(
        struct xfs_group        *xg,
        unsigned int            mask)
 {
-       ASSERT(!(mask & ~XFS_SICK_AG_ALL));
+       xfs_group_check_mask(xg, mask);
        trace_xfs_group_mark_corrupt(xg, mask);
 
        spin_lock(&xg->xg_state_lock);
@@ -265,7 +225,7 @@ xfs_group_mark_healthy(
        struct xfs_group        *xg,
        unsigned int            mask)
 {
-       ASSERT(!(mask & ~XFS_SICK_AG_ALL));
+       xfs_group_check_mask(xg, mask);
        trace_xfs_group_mark_healthy(xg, mask);
 
        spin_lock(&xg->xg_state_lock);
@@ -289,6 +249,23 @@ xfs_group_measure_sickness(
        spin_unlock(&xg->xg_state_lock);
 }
 
+/* Mark unhealthy per-rtgroup metadata given a raw rt group number. */
+void
+xfs_rgno_mark_sick(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno,
+       unsigned int            mask)
+{
+       struct xfs_rtgroup      *rtg = xfs_rtgroup_get(mp, rgno);
+
+       /* per-rtgroup structure not set up yet? */
+       if (!rtg)
+               return;
+
+       xfs_group_mark_sick(rtg_group(rtg), mask);
+       xfs_rtgroup_put(rtg);
+}
+
 /* Mark the unhealthy parts of an inode. */
 void
 xfs_inode_mark_sick(
@@ -388,8 +365,8 @@ static const struct ioctl_sick_map fs_map[] = {
 };
 
 static const struct ioctl_sick_map rt_map[] = {
-       { XFS_SICK_RT_BITMAP,   XFS_FSOP_GEOM_SICK_RT_BITMAP },
-       { XFS_SICK_RT_SUMMARY,  XFS_FSOP_GEOM_SICK_RT_SUMMARY },
+       { XFS_SICK_RG_BITMAP,   XFS_FSOP_GEOM_SICK_RT_BITMAP },
+       { XFS_SICK_RG_SUMMARY,  XFS_FSOP_GEOM_SICK_RT_SUMMARY },
 };
 
 static inline void
@@ -411,6 +388,7 @@ xfs_fsop_geom_health(
        struct xfs_mount                *mp,
        struct xfs_fsop_geom            *geo)
 {
+       struct xfs_rtgroup              *rtg = NULL;
        const struct ioctl_sick_map     *m;
        unsigned int                    sick;
        unsigned int                    checked;
@@ -422,9 +400,11 @@ xfs_fsop_geom_health(
        for_each_sick_map(fs_map, m)
                xfgeo_health_tick(geo, sick, checked, m);
 
-       xfs_rt_measure_sickness(mp, &sick, &checked);
-       for_each_sick_map(rt_map, m)
-               xfgeo_health_tick(geo, sick, checked, m);
+       while ((rtg = xfs_rtgroup_next(mp, rtg))) {
+               xfs_group_measure_sickness(rtg_group(rtg), &sick, &checked);
+               for_each_sick_map(rt_map, m)
+                       xfgeo_health_tick(geo, sick, checked, m);
+       }
 }
 
 static const struct ioctl_sick_map ag_map[] = {
index f66e5b5..62169c2 100644 (file)
@@ -4255,10 +4255,6 @@ DEFINE_FS_CORRUPT_EVENT(xfs_fs_mark_sick);
 DEFINE_FS_CORRUPT_EVENT(xfs_fs_mark_corrupt);
 DEFINE_FS_CORRUPT_EVENT(xfs_fs_mark_healthy);
 DEFINE_FS_CORRUPT_EVENT(xfs_fs_unfixed_corruption);
-DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_sick);
-DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_corrupt);
-DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_healthy);
-DEFINE_FS_CORRUPT_EVENT(xfs_rt_unfixed_corruption);
 
 DECLARE_EVENT_CLASS(xfs_group_corrupt_class,
        TP_PROTO(const struct xfs_group *xg, unsigned int flags),