xfs: move metadata health tracking to the generic group structure

Prepare for also tracking the health status of the upcoming realtime
groups by moving the health tracking code to the generic xfs_group
structure.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
This commit is contained in:
Christoph Hellwig
2024-11-03 20:18:40 -08:00
committed by Darrick J. Wong
parent 86437e6abb
commit 5c8483cec3
8 changed files with 94 additions and 91 deletions

View File

@@ -232,7 +232,6 @@ xfs_perag_alloc(
/* Place kernel structure only init below this point. */
spin_lock_init(&pag->pag_ici_lock);
spin_lock_init(&pag->pagb_lock);
spin_lock_init(&pag->pag_state_lock);
INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker);
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
xfs_defer_drain_init(&pag->pag_intents_drain);

View File

@@ -69,13 +69,6 @@ struct xfs_perag {
#ifdef __KERNEL__
/* -- kernel only structures below this line -- */
/*
* Bitsets of per-ag metadata that have been checked and/or are sick.
* Callers should hold pag_state_lock before accessing this field.
*/
uint16_t pag_checked;
uint16_t pag_sick;
#ifdef CONFIG_XFS_ONLINE_REPAIR
/*
* Alternate btree heights so that online repair won't trip the write
@@ -87,8 +80,6 @@ struct xfs_perag {
uint8_t pagf_repair_rmap_level;
#endif
spinlock_t pag_state_lock;
spinlock_t pagb_lock; /* lock for pagb_tree */
struct rb_root pagb_tree; /* ordered tree of busy extents */
unsigned int pagb_gen; /* generation count for pagb_tree */

View File

@@ -182,6 +182,10 @@ xfs_group_insert(
xg->xg_gno = index;
xg->xg_type = type;
#ifdef __KERNEL__
spin_lock_init(&xg->xg_state_lock);
#endif
/* Active ref owned by mount indicates group is online. */
atomic_set(&xg->xg_active_ref, 1);

View File

@@ -11,6 +11,18 @@ struct xfs_group {
enum xfs_group_type xg_type;
atomic_t xg_ref; /* passive reference count */
atomic_t xg_active_ref; /* active reference count */
#ifdef __KERNEL__
/* -- kernel only structures below this line -- */
/*
* Bitsets of per-ag metadata that have been checked and/or are sick.
* Callers should hold xg_state_lock before accessing this field.
*/
uint16_t xg_checked;
uint16_t xg_sick;
spinlock_t xg_state_lock;
#endif /* __KERNEL__ */
};
struct xfs_group *xfs_group_get(struct xfs_mount *mp, uint32_t index,

View File

@@ -6,6 +6,8 @@
#ifndef __XFS_HEALTH_H__
#define __XFS_HEALTH_H__
struct xfs_group;
/*
* In-Core Filesystem Health Assessments
* =====================================
@@ -197,10 +199,12 @@ void xfs_rt_measure_sickness(struct xfs_mount *mp, unsigned int *sick,
void xfs_agno_mark_sick(struct xfs_mount *mp, xfs_agnumber_t agno,
unsigned int mask);
void xfs_ag_mark_sick(struct xfs_perag *pag, unsigned int mask);
void xfs_ag_mark_corrupt(struct xfs_perag *pag, unsigned int mask);
void xfs_ag_mark_healthy(struct xfs_perag *pag, unsigned int mask);
void xfs_ag_measure_sickness(struct xfs_perag *pag, unsigned int *sick,
void xfs_group_mark_sick(struct xfs_group *xg, unsigned int mask);
#define xfs_ag_mark_sick(pag, mask) \
xfs_group_mark_sick(pag_group(pag), (mask))
void xfs_group_mark_corrupt(struct xfs_group *xg, unsigned int mask);
void xfs_group_mark_healthy(struct xfs_group *xg, unsigned int mask);
void xfs_group_measure_sickness(struct xfs_group *xg, unsigned int *sick,
unsigned int *checked);
void xfs_inode_mark_sick(struct xfs_inode *ip, unsigned int mask);
@@ -227,22 +231,19 @@ xfs_fs_has_sickness(struct xfs_mount *mp, unsigned int mask)
}
static inline bool
xfs_rt_has_sickness(struct xfs_mount *mp, unsigned int mask)
xfs_group_has_sickness(
struct xfs_group *xg,
unsigned int mask)
{
unsigned int sick, checked;
unsigned int sick, checked;
xfs_rt_measure_sickness(mp, &sick, &checked);
return sick & mask;
}
static inline bool
xfs_ag_has_sickness(struct xfs_perag *pag, unsigned int mask)
{
unsigned int sick, checked;
xfs_ag_measure_sickness(pag, &sick, &checked);
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))
static inline bool
xfs_inode_has_sickness(struct xfs_inode *ip, unsigned int mask)
@@ -259,18 +260,6 @@ xfs_fs_is_healthy(struct xfs_mount *mp)
return !xfs_fs_has_sickness(mp, -1U);
}
static inline bool
xfs_rt_is_healthy(struct xfs_mount *mp)
{
return !xfs_rt_has_sickness(mp, -1U);
}
static inline bool
xfs_ag_is_healthy(struct xfs_perag *pag)
{
return !xfs_ag_has_sickness(pag, -1U);
}
static inline bool
xfs_inode_is_healthy(struct xfs_inode *ip)
{

View File

@@ -165,7 +165,7 @@ xchk_mark_all_healthy(
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_ag_mark_healthy(pag, XFS_SICK_AG_INDIRECT);
xfs_group_mark_healthy(pag_group(pag), XFS_SICK_AG_INDIRECT);
}
/*
@@ -206,9 +206,9 @@ xchk_update_health(
case XHG_AG:
pag = xfs_perag_get(sc->mp, sc->sm->sm_agno);
if (bad)
xfs_ag_mark_corrupt(pag, sc->sick_mask);
xfs_group_mark_corrupt(pag_group(pag), sc->sick_mask);
else
xfs_ag_mark_healthy(pag, sc->sick_mask);
xfs_group_mark_healthy(pag_group(pag), sc->sick_mask);
xfs_perag_put(pag);
break;
case XHG_INO:
@@ -306,7 +306,7 @@ xchk_health_record(
xchk_set_corrupt(sc);
while ((pag = xfs_perag_next(mp, pag))) {
xfs_ag_measure_sickness(pag, &sick, &checked);
xfs_group_measure_sickness(pag_group(pag), &sick, &checked);
if (sick & XFS_SICK_AG_PRIMARY)
xchk_set_corrupt(sc);
}

View File

@@ -38,9 +38,10 @@ xfs_health_unmount(
/* Measure AG corruption levels. */
while ((pag = xfs_perag_next(mp, pag))) {
xfs_ag_measure_sickness(pag, &sick, &checked);
xfs_group_measure_sickness(pag_group(pag), &sick, &checked);
if (sick) {
trace_xfs_ag_unfixed_corruption(pag, sick);
trace_xfs_group_unfixed_corruption(pag_group(pag),
sick);
warn = true;
}
}
@@ -227,61 +228,65 @@ xfs_agno_mark_sick(
/* Mark unhealthy per-ag metadata. */
void
xfs_ag_mark_sick(
struct xfs_perag *pag,
xfs_group_mark_sick(
struct xfs_group *xg,
unsigned int mask)
{
ASSERT(!(mask & ~XFS_SICK_AG_ALL));
trace_xfs_ag_mark_sick(pag, mask);
trace_xfs_group_mark_sick(xg, mask);
spin_lock(&pag->pag_state_lock);
pag->pag_sick |= mask;
spin_unlock(&pag->pag_state_lock);
spin_lock(&xg->xg_state_lock);
xg->xg_sick |= mask;
spin_unlock(&xg->xg_state_lock);
}
/* Mark per-ag metadata as having been checked and found unhealthy by fsck. */
/*
* Mark per-group metadata as having been checked and found unhealthy by fsck.
*/
void
xfs_ag_mark_corrupt(
struct xfs_perag *pag,
xfs_group_mark_corrupt(
struct xfs_group *xg,
unsigned int mask)
{
ASSERT(!(mask & ~XFS_SICK_AG_ALL));
trace_xfs_ag_mark_corrupt(pag, mask);
trace_xfs_group_mark_corrupt(xg, mask);
spin_lock(&pag->pag_state_lock);
pag->pag_sick |= mask;
pag->pag_checked |= mask;
spin_unlock(&pag->pag_state_lock);
spin_lock(&xg->xg_state_lock);
xg->xg_sick |= mask;
xg->xg_checked |= mask;
spin_unlock(&xg->xg_state_lock);
}
/* Mark per-ag metadata ok. */
/*
* Mark per-group metadata ok.
*/
void
xfs_ag_mark_healthy(
struct xfs_perag *pag,
xfs_group_mark_healthy(
struct xfs_group *xg,
unsigned int mask)
{
ASSERT(!(mask & ~XFS_SICK_AG_ALL));
trace_xfs_ag_mark_healthy(pag, mask);
trace_xfs_group_mark_healthy(xg, mask);
spin_lock(&pag->pag_state_lock);
pag->pag_sick &= ~mask;
if (!(pag->pag_sick & XFS_SICK_AG_PRIMARY))
pag->pag_sick &= ~XFS_SICK_AG_SECONDARY;
pag->pag_checked |= mask;
spin_unlock(&pag->pag_state_lock);
spin_lock(&xg->xg_state_lock);
xg->xg_sick &= ~mask;
if (!(xg->xg_sick & XFS_SICK_AG_PRIMARY))
xg->xg_sick &= ~XFS_SICK_AG_SECONDARY;
xg->xg_checked |= mask;
spin_unlock(&xg->xg_state_lock);
}
/* Sample which per-ag metadata are unhealthy. */
void
xfs_ag_measure_sickness(
struct xfs_perag *pag,
xfs_group_measure_sickness(
struct xfs_group *xg,
unsigned int *sick,
unsigned int *checked)
{
spin_lock(&pag->pag_state_lock);
*sick = pag->pag_sick;
*checked = pag->pag_checked;
spin_unlock(&pag->pag_state_lock);
spin_lock(&xg->xg_state_lock);
*sick = xg->xg_sick;
*checked = xg->xg_checked;
spin_unlock(&xg->xg_state_lock);
}
/* Mark the unhealthy parts of an inode. */
@@ -447,7 +452,7 @@ xfs_ag_geom_health(
ageo->ag_sick = 0;
ageo->ag_checked = 0;
xfs_ag_measure_sickness(pag, &sick, &checked);
xfs_group_measure_sickness(pag_group(pag), &sick, &checked);
for (m = ag_map; m->sick_mask; m++) {
if (checked & m->sick_mask)
ageo->ag_checked |= m->ioctl_mask;

View File

@@ -4215,31 +4215,34 @@ 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_ag_corrupt_class,
TP_PROTO(const struct xfs_perag *pag, unsigned int flags),
TP_ARGS(pag, flags),
DECLARE_EVENT_CLASS(xfs_group_corrupt_class,
TP_PROTO(const struct xfs_group *xg, unsigned int flags),
TP_ARGS(xg, flags),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_agnumber_t, agno)
__field(enum xfs_group_type, type)
__field(uint32_t, index)
__field(unsigned int, flags)
),
TP_fast_assign(
__entry->dev = pag_mount(pag)->m_super->s_dev;
__entry->agno = pag_agno(pag);
__entry->dev = xg->xg_mount->m_super->s_dev;
__entry->type = xg->xg_type;
__entry->index = xg->xg_gno;
__entry->flags = flags;
),
TP_printk("dev %d:%d agno 0x%x flags 0x%x",
TP_printk("dev %d:%d %sno 0x%x flags 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno, __entry->flags)
__print_symbolic(__entry->type, XG_TYPE_STRINGS),
__entry->index, __entry->flags)
);
#define DEFINE_AG_CORRUPT_EVENT(name) \
DEFINE_EVENT(xfs_ag_corrupt_class, name, \
TP_PROTO(const struct xfs_perag *pag, unsigned int flags), \
TP_ARGS(pag, flags))
DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_sick);
DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_corrupt);
DEFINE_AG_CORRUPT_EVENT(xfs_ag_mark_healthy);
DEFINE_AG_CORRUPT_EVENT(xfs_ag_unfixed_corruption);
#define DEFINE_GROUP_CORRUPT_EVENT(name) \
DEFINE_EVENT(xfs_group_corrupt_class, name, \
TP_PROTO(const struct xfs_group *xg, unsigned int flags), \
TP_ARGS(xg, flags))
DEFINE_GROUP_CORRUPT_EVENT(xfs_group_mark_sick);
DEFINE_GROUP_CORRUPT_EVENT(xfs_group_mark_corrupt);
DEFINE_GROUP_CORRUPT_EVENT(xfs_group_mark_healthy);
DEFINE_GROUP_CORRUPT_EVENT(xfs_group_unfixed_corruption);
DECLARE_EVENT_CLASS(xfs_inode_corrupt_class,
TP_PROTO(struct xfs_inode *ip, unsigned int flags),