mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 02:44:41 +01:00
xfs: convey metadata health events to the health monitor
Connect the filesystem metadata health event collection system to the health monitor so that xfs can send events to xfs_healer as it collects information. Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
25ca57fa36
commit
5eb4cb18e4
6 changed files with 511 additions and 2 deletions
|
|
@ -1008,6 +1008,12 @@ struct xfs_rtgroup_geometry {
|
|||
/* affects the whole fs */
|
||||
#define XFS_HEALTH_MONITOR_DOMAIN_MOUNT (0)
|
||||
|
||||
/* metadata health events */
|
||||
#define XFS_HEALTH_MONITOR_DOMAIN_FS (1)
|
||||
#define XFS_HEALTH_MONITOR_DOMAIN_AG (2)
|
||||
#define XFS_HEALTH_MONITOR_DOMAIN_INODE (3)
|
||||
#define XFS_HEALTH_MONITOR_DOMAIN_RTGROUP (4)
|
||||
|
||||
/* Health monitor event types */
|
||||
|
||||
/* status of the monitor itself */
|
||||
|
|
@ -1017,11 +1023,37 @@ struct xfs_rtgroup_geometry {
|
|||
/* filesystem was unmounted */
|
||||
#define XFS_HEALTH_MONITOR_TYPE_UNMOUNT (2)
|
||||
|
||||
/* metadata health events */
|
||||
#define XFS_HEALTH_MONITOR_TYPE_SICK (3)
|
||||
#define XFS_HEALTH_MONITOR_TYPE_CORRUPT (4)
|
||||
#define XFS_HEALTH_MONITOR_TYPE_HEALTHY (5)
|
||||
|
||||
/* lost events */
|
||||
struct xfs_health_monitor_lost {
|
||||
__u64 count;
|
||||
};
|
||||
|
||||
/* fs/rt metadata */
|
||||
struct xfs_health_monitor_fs {
|
||||
/* XFS_FSOP_GEOM_SICK_* flags */
|
||||
__u32 mask;
|
||||
};
|
||||
|
||||
/* ag/rtgroup metadata */
|
||||
struct xfs_health_monitor_group {
|
||||
/* XFS_{AG,RTGROUP}_SICK_* flags */
|
||||
__u32 mask;
|
||||
__u32 gno;
|
||||
};
|
||||
|
||||
/* inode metadata */
|
||||
struct xfs_health_monitor_inode {
|
||||
/* XFS_BS_SICK_* flags */
|
||||
__u32 mask;
|
||||
__u32 gen;
|
||||
__u64 ino;
|
||||
};
|
||||
|
||||
struct xfs_health_monitor_event {
|
||||
/* XFS_HEALTH_MONITOR_DOMAIN_* */
|
||||
__u32 domain;
|
||||
|
|
@ -1039,6 +1071,9 @@ struct xfs_health_monitor_event {
|
|||
*/
|
||||
union {
|
||||
struct xfs_health_monitor_lost lost;
|
||||
struct xfs_health_monitor_fs fs;
|
||||
struct xfs_health_monitor_group group;
|
||||
struct xfs_health_monitor_inode inode;
|
||||
} e;
|
||||
|
||||
/* zeroes */
|
||||
|
|
|
|||
|
|
@ -289,4 +289,9 @@ void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bulkstat *bs);
|
|||
#define xfs_metadata_is_sick(error) \
|
||||
(unlikely((error) == -EFSCORRUPTED || (error) == -EFSBADCRC))
|
||||
|
||||
unsigned int xfs_healthmon_inode_mask(unsigned int sick_mask);
|
||||
unsigned int xfs_healthmon_rtgroup_mask(unsigned int sick_mask);
|
||||
unsigned int xfs_healthmon_perag_mask(unsigned int sick_mask);
|
||||
unsigned int xfs_healthmon_fs_mask(unsigned int sick_mask);
|
||||
|
||||
#endif /* __XFS_HEALTH_H__ */
|
||||
|
|
|
|||
|
|
@ -108,14 +108,19 @@ xfs_fs_mark_sick(
|
|||
struct xfs_mount *mp,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
ASSERT(!(mask & ~XFS_SICK_FS_ALL));
|
||||
trace_xfs_fs_mark_sick(mp, mask);
|
||||
|
||||
spin_lock(&mp->m_sb_lock);
|
||||
old_mask = mp->m_fs_sick;
|
||||
mp->m_fs_sick |= mask;
|
||||
spin_unlock(&mp->m_sb_lock);
|
||||
|
||||
fserror_report_metadata(mp->m_super, -EFSCORRUPTED, GFP_NOFS);
|
||||
if (mask)
|
||||
xfs_healthmon_report_fs(mp, XFS_HEALTHMON_SICK, old_mask, mask);
|
||||
}
|
||||
|
||||
/* Mark per-fs metadata as having been checked and found unhealthy by fsck. */
|
||||
|
|
@ -124,15 +129,21 @@ xfs_fs_mark_corrupt(
|
|||
struct xfs_mount *mp,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
ASSERT(!(mask & ~XFS_SICK_FS_ALL));
|
||||
trace_xfs_fs_mark_corrupt(mp, mask);
|
||||
|
||||
spin_lock(&mp->m_sb_lock);
|
||||
old_mask = mp->m_fs_sick;
|
||||
mp->m_fs_sick |= mask;
|
||||
mp->m_fs_checked |= mask;
|
||||
spin_unlock(&mp->m_sb_lock);
|
||||
|
||||
fserror_report_metadata(mp->m_super, -EFSCORRUPTED, GFP_NOFS);
|
||||
if (mask)
|
||||
xfs_healthmon_report_fs(mp, XFS_HEALTHMON_CORRUPT, old_mask,
|
||||
mask);
|
||||
}
|
||||
|
||||
/* Mark a per-fs metadata healed. */
|
||||
|
|
@ -141,15 +152,22 @@ xfs_fs_mark_healthy(
|
|||
struct xfs_mount *mp,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
ASSERT(!(mask & ~XFS_SICK_FS_ALL));
|
||||
trace_xfs_fs_mark_healthy(mp, mask);
|
||||
|
||||
spin_lock(&mp->m_sb_lock);
|
||||
old_mask = mp->m_fs_sick;
|
||||
mp->m_fs_sick &= ~mask;
|
||||
if (!(mp->m_fs_sick & XFS_SICK_FS_PRIMARY))
|
||||
mp->m_fs_sick &= ~XFS_SICK_FS_SECONDARY;
|
||||
mp->m_fs_checked |= mask;
|
||||
spin_unlock(&mp->m_sb_lock);
|
||||
|
||||
if (mask)
|
||||
xfs_healthmon_report_fs(mp, XFS_HEALTHMON_HEALTHY, old_mask,
|
||||
mask);
|
||||
}
|
||||
|
||||
/* Sample which per-fs metadata are unhealthy. */
|
||||
|
|
@ -199,14 +217,20 @@ xfs_group_mark_sick(
|
|||
struct xfs_group *xg,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
xfs_group_check_mask(xg, mask);
|
||||
trace_xfs_group_mark_sick(xg, mask);
|
||||
|
||||
spin_lock(&xg->xg_state_lock);
|
||||
old_mask = xg->xg_sick;
|
||||
xg->xg_sick |= mask;
|
||||
spin_unlock(&xg->xg_state_lock);
|
||||
|
||||
fserror_report_metadata(xg->xg_mount->m_super, -EFSCORRUPTED, GFP_NOFS);
|
||||
if (mask)
|
||||
xfs_healthmon_report_group(xg, XFS_HEALTHMON_SICK, old_mask,
|
||||
mask);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -217,15 +241,21 @@ xfs_group_mark_corrupt(
|
|||
struct xfs_group *xg,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
xfs_group_check_mask(xg, mask);
|
||||
trace_xfs_group_mark_corrupt(xg, mask);
|
||||
|
||||
spin_lock(&xg->xg_state_lock);
|
||||
old_mask = xg->xg_sick;
|
||||
xg->xg_sick |= mask;
|
||||
xg->xg_checked |= mask;
|
||||
spin_unlock(&xg->xg_state_lock);
|
||||
|
||||
fserror_report_metadata(xg->xg_mount->m_super, -EFSCORRUPTED, GFP_NOFS);
|
||||
if (mask)
|
||||
xfs_healthmon_report_group(xg, XFS_HEALTHMON_CORRUPT, old_mask,
|
||||
mask);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -236,15 +266,22 @@ xfs_group_mark_healthy(
|
|||
struct xfs_group *xg,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
xfs_group_check_mask(xg, mask);
|
||||
trace_xfs_group_mark_healthy(xg, mask);
|
||||
|
||||
spin_lock(&xg->xg_state_lock);
|
||||
old_mask = xg->xg_sick;
|
||||
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);
|
||||
|
||||
if (mask)
|
||||
xfs_healthmon_report_group(xg, XFS_HEALTHMON_HEALTHY, old_mask,
|
||||
mask);
|
||||
}
|
||||
|
||||
/* Sample which per-ag metadata are unhealthy. */
|
||||
|
|
@ -283,10 +320,13 @@ xfs_inode_mark_sick(
|
|||
struct xfs_inode *ip,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
ASSERT(!(mask & ~XFS_SICK_INO_ALL));
|
||||
trace_xfs_inode_mark_sick(ip, mask);
|
||||
|
||||
spin_lock(&ip->i_flags_lock);
|
||||
old_mask = ip->i_sick;
|
||||
ip->i_sick |= mask;
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
|
||||
|
|
@ -300,6 +340,9 @@ xfs_inode_mark_sick(
|
|||
spin_unlock(&VFS_I(ip)->i_lock);
|
||||
|
||||
fserror_report_file_metadata(VFS_I(ip), -EFSCORRUPTED, GFP_NOFS);
|
||||
if (mask)
|
||||
xfs_healthmon_report_inode(ip, XFS_HEALTHMON_SICK, old_mask,
|
||||
mask);
|
||||
}
|
||||
|
||||
/* Mark inode metadata as having been checked and found unhealthy by fsck. */
|
||||
|
|
@ -308,10 +351,13 @@ xfs_inode_mark_corrupt(
|
|||
struct xfs_inode *ip,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
ASSERT(!(mask & ~XFS_SICK_INO_ALL));
|
||||
trace_xfs_inode_mark_corrupt(ip, mask);
|
||||
|
||||
spin_lock(&ip->i_flags_lock);
|
||||
old_mask = ip->i_sick;
|
||||
ip->i_sick |= mask;
|
||||
ip->i_checked |= mask;
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
|
|
@ -326,6 +372,9 @@ xfs_inode_mark_corrupt(
|
|||
spin_unlock(&VFS_I(ip)->i_lock);
|
||||
|
||||
fserror_report_file_metadata(VFS_I(ip), -EFSCORRUPTED, GFP_NOFS);
|
||||
if (mask)
|
||||
xfs_healthmon_report_inode(ip, XFS_HEALTHMON_CORRUPT, old_mask,
|
||||
mask);
|
||||
}
|
||||
|
||||
/* Mark parts of an inode healed. */
|
||||
|
|
@ -334,15 +383,22 @@ xfs_inode_mark_healthy(
|
|||
struct xfs_inode *ip,
|
||||
unsigned int mask)
|
||||
{
|
||||
unsigned int old_mask;
|
||||
|
||||
ASSERT(!(mask & ~XFS_SICK_INO_ALL));
|
||||
trace_xfs_inode_mark_healthy(ip, mask);
|
||||
|
||||
spin_lock(&ip->i_flags_lock);
|
||||
old_mask = ip->i_sick;
|
||||
ip->i_sick &= ~mask;
|
||||
if (!(ip->i_sick & XFS_SICK_INO_PRIMARY))
|
||||
ip->i_sick &= ~XFS_SICK_INO_SECONDARY;
|
||||
ip->i_checked |= mask;
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
|
||||
if (mask)
|
||||
xfs_healthmon_report_inode(ip, XFS_HEALTHMON_HEALTHY, old_mask,
|
||||
mask);
|
||||
}
|
||||
|
||||
/* Sample which parts of an inode are unhealthy. */
|
||||
|
|
@ -422,6 +478,25 @@ xfs_fsop_geom_health(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate XFS_SICK_FS_* into XFS_FSOP_GEOM_SICK_* except for the rt free
|
||||
* space codes, which are sent via the rtgroup events.
|
||||
*/
|
||||
unsigned int
|
||||
xfs_healthmon_fs_mask(
|
||||
unsigned int sick_mask)
|
||||
{
|
||||
const struct ioctl_sick_map *m;
|
||||
unsigned int ioctl_mask = 0;
|
||||
|
||||
for_each_sick_map(fs_map, m) {
|
||||
if (sick_mask & m->sick_mask)
|
||||
ioctl_mask |= m->ioctl_mask;
|
||||
}
|
||||
|
||||
return ioctl_mask;
|
||||
}
|
||||
|
||||
static const struct ioctl_sick_map ag_map[] = {
|
||||
{ XFS_SICK_AG_SB, XFS_AG_GEOM_SICK_SB },
|
||||
{ XFS_SICK_AG_AGF, XFS_AG_GEOM_SICK_AGF },
|
||||
|
|
@ -458,6 +533,22 @@ xfs_ag_geom_health(
|
|||
}
|
||||
}
|
||||
|
||||
/* Translate XFS_SICK_AG_* into XFS_AG_GEOM_SICK_*. */
|
||||
unsigned int
|
||||
xfs_healthmon_perag_mask(
|
||||
unsigned int sick_mask)
|
||||
{
|
||||
const struct ioctl_sick_map *m;
|
||||
unsigned int ioctl_mask = 0;
|
||||
|
||||
for_each_sick_map(ag_map, m) {
|
||||
if (sick_mask & m->sick_mask)
|
||||
ioctl_mask |= m->ioctl_mask;
|
||||
}
|
||||
|
||||
return ioctl_mask;
|
||||
}
|
||||
|
||||
static const struct ioctl_sick_map rtgroup_map[] = {
|
||||
{ XFS_SICK_RG_SUPER, XFS_RTGROUP_GEOM_SICK_SUPER },
|
||||
{ XFS_SICK_RG_BITMAP, XFS_RTGROUP_GEOM_SICK_BITMAP },
|
||||
|
|
@ -488,6 +579,22 @@ xfs_rtgroup_geom_health(
|
|||
}
|
||||
}
|
||||
|
||||
/* Translate XFS_SICK_RG_* into XFS_RTGROUP_GEOM_SICK_*. */
|
||||
unsigned int
|
||||
xfs_healthmon_rtgroup_mask(
|
||||
unsigned int sick_mask)
|
||||
{
|
||||
const struct ioctl_sick_map *m;
|
||||
unsigned int ioctl_mask = 0;
|
||||
|
||||
for_each_sick_map(rtgroup_map, m) {
|
||||
if (sick_mask & m->sick_mask)
|
||||
ioctl_mask |= m->ioctl_mask;
|
||||
}
|
||||
|
||||
return ioctl_mask;
|
||||
}
|
||||
|
||||
static const struct ioctl_sick_map ino_map[] = {
|
||||
{ XFS_SICK_INO_CORE, XFS_BS_SICK_INODE },
|
||||
{ XFS_SICK_INO_BMBTD, XFS_BS_SICK_BMBTD },
|
||||
|
|
@ -526,6 +633,22 @@ xfs_bulkstat_health(
|
|||
}
|
||||
}
|
||||
|
||||
/* Translate XFS_SICK_INO_* into XFS_BS_SICK_*. */
|
||||
unsigned int
|
||||
xfs_healthmon_inode_mask(
|
||||
unsigned int sick_mask)
|
||||
{
|
||||
const struct ioctl_sick_map *m;
|
||||
unsigned int ioctl_mask = 0;
|
||||
|
||||
for_each_sick_map(ino_map, m) {
|
||||
if (sick_mask & m->sick_mask)
|
||||
ioctl_mask |= m->ioctl_mask;
|
||||
}
|
||||
|
||||
return ioctl_mask;
|
||||
}
|
||||
|
||||
/* Mark a block mapping sick. */
|
||||
void
|
||||
xfs_bmap_mark_sick(
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "xfs_da_btree.h"
|
||||
#include "xfs_quota_defs.h"
|
||||
#include "xfs_rtgroup.h"
|
||||
#include "xfs_health.h"
|
||||
#include "xfs_healthmon.h"
|
||||
|
||||
#include <linux/anon_inodes.h>
|
||||
|
|
@ -174,6 +175,33 @@ xfs_healthmon_merge_events(
|
|||
case XFS_HEALTHMON_LOST:
|
||||
existing->lostcount += new->lostcount;
|
||||
return true;
|
||||
|
||||
case XFS_HEALTHMON_SICK:
|
||||
case XFS_HEALTHMON_CORRUPT:
|
||||
case XFS_HEALTHMON_HEALTHY:
|
||||
switch (existing->domain) {
|
||||
case XFS_HEALTHMON_FS:
|
||||
existing->fsmask |= new->fsmask;
|
||||
return true;
|
||||
case XFS_HEALTHMON_AG:
|
||||
case XFS_HEALTHMON_RTGROUP:
|
||||
if (existing->group == new->group){
|
||||
existing->grpmask |= new->grpmask;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case XFS_HEALTHMON_INODE:
|
||||
if (existing->ino == new->ino &&
|
||||
existing->gen == new->gen) {
|
||||
existing->imask |= new->imask;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -337,6 +365,135 @@ xfs_healthmon_unmount(
|
|||
xfs_healthmon_put(hm);
|
||||
}
|
||||
|
||||
/* Compute the reporting mask for non-unmount metadata health events. */
|
||||
static inline unsigned int
|
||||
metadata_event_mask(
|
||||
struct xfs_healthmon *hm,
|
||||
enum xfs_healthmon_type type,
|
||||
unsigned int old_mask,
|
||||
unsigned int new_mask)
|
||||
{
|
||||
/* If we want all events, return all events. */
|
||||
if (hm->verbose)
|
||||
return new_mask;
|
||||
|
||||
switch (type) {
|
||||
case XFS_HEALTHMON_SICK:
|
||||
/* Always report runtime corruptions */
|
||||
return new_mask;
|
||||
case XFS_HEALTHMON_CORRUPT:
|
||||
/* Only report new fsck errors */
|
||||
return new_mask & ~old_mask;
|
||||
case XFS_HEALTHMON_HEALTHY:
|
||||
/* Only report healthy metadata that got fixed */
|
||||
return new_mask & old_mask;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Report XFS_FS_SICK_* events to healthmon */
|
||||
void
|
||||
xfs_healthmon_report_fs(
|
||||
struct xfs_mount *mp,
|
||||
enum xfs_healthmon_type type,
|
||||
unsigned int old_mask,
|
||||
unsigned int new_mask)
|
||||
{
|
||||
struct xfs_healthmon_event event = {
|
||||
.type = type,
|
||||
.domain = XFS_HEALTHMON_FS,
|
||||
};
|
||||
struct xfs_healthmon *hm = xfs_healthmon_get(mp);
|
||||
|
||||
if (!hm)
|
||||
return;
|
||||
|
||||
event.fsmask = metadata_event_mask(hm, type, old_mask, new_mask) &
|
||||
~XFS_SICK_FS_SECONDARY;
|
||||
trace_xfs_healthmon_report_fs(hm, old_mask, new_mask, &event);
|
||||
|
||||
if (event.fsmask)
|
||||
xfs_healthmon_push(hm, &event);
|
||||
|
||||
xfs_healthmon_put(hm);
|
||||
}
|
||||
|
||||
/* Report XFS_SICK_(AG|RG)* flags to healthmon */
|
||||
void
|
||||
xfs_healthmon_report_group(
|
||||
struct xfs_group *xg,
|
||||
enum xfs_healthmon_type type,
|
||||
unsigned int old_mask,
|
||||
unsigned int new_mask)
|
||||
{
|
||||
struct xfs_healthmon_event event = {
|
||||
.type = type,
|
||||
.group = xg->xg_gno,
|
||||
};
|
||||
struct xfs_healthmon *hm = xfs_healthmon_get(xg->xg_mount);
|
||||
|
||||
if (!hm)
|
||||
return;
|
||||
|
||||
switch (xg->xg_type) {
|
||||
case XG_TYPE_RTG:
|
||||
event.domain = XFS_HEALTHMON_RTGROUP;
|
||||
event.grpmask = metadata_event_mask(hm, type, old_mask,
|
||||
new_mask) &
|
||||
~XFS_SICK_RG_SECONDARY;
|
||||
break;
|
||||
case XG_TYPE_AG:
|
||||
event.domain = XFS_HEALTHMON_AG;
|
||||
event.grpmask = metadata_event_mask(hm, type, old_mask,
|
||||
new_mask) &
|
||||
~XFS_SICK_AG_SECONDARY;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_xfs_healthmon_report_group(hm, old_mask, new_mask, &event);
|
||||
|
||||
if (event.grpmask)
|
||||
xfs_healthmon_push(hm, &event);
|
||||
|
||||
xfs_healthmon_put(hm);
|
||||
}
|
||||
|
||||
/* Report XFS_SICK_INO_* flags to healthmon */
|
||||
void
|
||||
xfs_healthmon_report_inode(
|
||||
struct xfs_inode *ip,
|
||||
enum xfs_healthmon_type type,
|
||||
unsigned int old_mask,
|
||||
unsigned int new_mask)
|
||||
{
|
||||
struct xfs_healthmon_event event = {
|
||||
.type = type,
|
||||
.domain = XFS_HEALTHMON_INODE,
|
||||
.ino = ip->i_ino,
|
||||
.gen = VFS_I(ip)->i_generation,
|
||||
};
|
||||
struct xfs_healthmon *hm = xfs_healthmon_get(ip->i_mount);
|
||||
|
||||
if (!hm)
|
||||
return;
|
||||
|
||||
event.imask = metadata_event_mask(hm, type, old_mask, new_mask) &
|
||||
~XFS_SICK_INO_SECONDARY;
|
||||
trace_xfs_healthmon_report_inode(hm, old_mask, event.imask, &event);
|
||||
|
||||
if (event.imask)
|
||||
xfs_healthmon_push(hm, &event);
|
||||
|
||||
xfs_healthmon_put(hm);
|
||||
}
|
||||
|
||||
static inline void
|
||||
xfs_healthmon_reset_outbuf(
|
||||
struct xfs_healthmon *hm)
|
||||
|
|
@ -347,11 +504,19 @@ xfs_healthmon_reset_outbuf(
|
|||
|
||||
static const unsigned int domain_map[] = {
|
||||
[XFS_HEALTHMON_MOUNT] = XFS_HEALTH_MONITOR_DOMAIN_MOUNT,
|
||||
[XFS_HEALTHMON_FS] = XFS_HEALTH_MONITOR_DOMAIN_FS,
|
||||
[XFS_HEALTHMON_AG] = XFS_HEALTH_MONITOR_DOMAIN_AG,
|
||||
[XFS_HEALTHMON_INODE] = XFS_HEALTH_MONITOR_DOMAIN_INODE,
|
||||
[XFS_HEALTHMON_RTGROUP] = XFS_HEALTH_MONITOR_DOMAIN_RTGROUP,
|
||||
};
|
||||
|
||||
static const unsigned int type_map[] = {
|
||||
[XFS_HEALTHMON_RUNNING] = XFS_HEALTH_MONITOR_TYPE_RUNNING,
|
||||
[XFS_HEALTHMON_LOST] = XFS_HEALTH_MONITOR_TYPE_LOST,
|
||||
[XFS_HEALTHMON_SICK] = XFS_HEALTH_MONITOR_TYPE_SICK,
|
||||
[XFS_HEALTHMON_CORRUPT] = XFS_HEALTH_MONITOR_TYPE_CORRUPT,
|
||||
[XFS_HEALTHMON_HEALTHY] = XFS_HEALTH_MONITOR_TYPE_HEALTHY,
|
||||
[XFS_HEALTHMON_UNMOUNT] = XFS_HEALTH_MONITOR_TYPE_UNMOUNT,
|
||||
};
|
||||
|
||||
/* Render event as a V0 structure */
|
||||
|
|
@ -384,6 +549,22 @@ xfs_healthmon_format_v0(
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case XFS_HEALTHMON_FS:
|
||||
hme.e.fs.mask = xfs_healthmon_fs_mask(event->fsmask);
|
||||
break;
|
||||
case XFS_HEALTHMON_RTGROUP:
|
||||
hme.e.group.mask = xfs_healthmon_rtgroup_mask(event->grpmask);
|
||||
hme.e.group.gno = event->group;
|
||||
break;
|
||||
case XFS_HEALTHMON_AG:
|
||||
hme.e.group.mask = xfs_healthmon_perag_mask(event->grpmask);
|
||||
hme.e.group.gno = event->group;
|
||||
break;
|
||||
case XFS_HEALTHMON_INODE:
|
||||
hme.e.inode.mask = xfs_healthmon_inode_mask(event->imask);
|
||||
hme.e.inode.ino = event->ino;
|
||||
hme.e.inode.gen = event->gen;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,10 +71,21 @@ enum xfs_healthmon_type {
|
|||
XFS_HEALTHMON_RUNNING, /* monitor running */
|
||||
XFS_HEALTHMON_LOST, /* message lost */
|
||||
XFS_HEALTHMON_UNMOUNT, /* filesystem is unmounting */
|
||||
|
||||
/* metadata health events */
|
||||
XFS_HEALTHMON_SICK, /* runtime corruption observed */
|
||||
XFS_HEALTHMON_CORRUPT, /* fsck reported corruption */
|
||||
XFS_HEALTHMON_HEALTHY, /* fsck reported healthy structure */
|
||||
};
|
||||
|
||||
enum xfs_healthmon_domain {
|
||||
XFS_HEALTHMON_MOUNT, /* affects the whole fs */
|
||||
|
||||
/* metadata health events */
|
||||
XFS_HEALTHMON_FS, /* main filesystem metadata */
|
||||
XFS_HEALTHMON_AG, /* allocation group metadata */
|
||||
XFS_HEALTHMON_INODE, /* inode metadata */
|
||||
XFS_HEALTHMON_RTGROUP, /* realtime group metadata */
|
||||
};
|
||||
|
||||
struct xfs_healthmon_event {
|
||||
|
|
@ -90,9 +101,37 @@ struct xfs_healthmon_event {
|
|||
struct {
|
||||
uint64_t lostcount;
|
||||
};
|
||||
/* fs/rt metadata */
|
||||
struct {
|
||||
/* XFS_SICK_* flags */
|
||||
unsigned int fsmask;
|
||||
};
|
||||
/* ag/rtgroup metadata */
|
||||
struct {
|
||||
/* XFS_SICK_(AG|RG)* flags */
|
||||
unsigned int grpmask;
|
||||
unsigned int group;
|
||||
};
|
||||
/* inode metadata */
|
||||
struct {
|
||||
/* XFS_SICK_INO_* flags */
|
||||
unsigned int imask;
|
||||
uint32_t gen;
|
||||
xfs_ino_t ino;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void xfs_healthmon_report_fs(struct xfs_mount *mp,
|
||||
enum xfs_healthmon_type type, unsigned int old_mask,
|
||||
unsigned int new_mask);
|
||||
void xfs_healthmon_report_group(struct xfs_group *xg,
|
||||
enum xfs_healthmon_type type, unsigned int old_mask,
|
||||
unsigned int new_mask);
|
||||
void xfs_healthmon_report_inode(struct xfs_inode *ip,
|
||||
enum xfs_healthmon_type type, unsigned int old_mask,
|
||||
unsigned int new_mask);
|
||||
|
||||
long xfs_ioc_health_monitor(struct file *file,
|
||||
struct xfs_health_monitor __user *arg);
|
||||
|
||||
|
|
|
|||
|
|
@ -6009,15 +6009,29 @@ DEFINE_HEALTHMON_EVENT(xfs_healthmon_report_unmount);
|
|||
|
||||
#define XFS_HEALTHMON_TYPE_STRINGS \
|
||||
{ XFS_HEALTHMON_LOST, "lost" }, \
|
||||
{ XFS_HEALTHMON_UNMOUNT, "unmount" }
|
||||
{ XFS_HEALTHMON_UNMOUNT, "unmount" }, \
|
||||
{ XFS_HEALTHMON_SICK, "sick" }, \
|
||||
{ XFS_HEALTHMON_CORRUPT, "corrupt" }, \
|
||||
{ XFS_HEALTHMON_HEALTHY, "healthy" }
|
||||
|
||||
#define XFS_HEALTHMON_DOMAIN_STRINGS \
|
||||
{ XFS_HEALTHMON_MOUNT, "mount" }
|
||||
{ XFS_HEALTHMON_MOUNT, "mount" }, \
|
||||
{ XFS_HEALTHMON_FS, "fs" }, \
|
||||
{ XFS_HEALTHMON_AG, "ag" }, \
|
||||
{ XFS_HEALTHMON_INODE, "inode" }, \
|
||||
{ XFS_HEALTHMON_RTGROUP, "rtgroup" }
|
||||
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_LOST);
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_UNMOUNT);
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_SICK);
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_CORRUPT);
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_HEALTHY);
|
||||
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_MOUNT);
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_FS);
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_AG);
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_INODE);
|
||||
TRACE_DEFINE_ENUM(XFS_HEALTHMON_RTGROUP);
|
||||
|
||||
DECLARE_EVENT_CLASS(xfs_healthmon_event_class,
|
||||
TP_PROTO(const struct xfs_healthmon *hm,
|
||||
|
|
@ -6054,6 +6068,19 @@ DECLARE_EVENT_CLASS(xfs_healthmon_event_class,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case XFS_HEALTHMON_FS:
|
||||
__entry->mask = event->fsmask;
|
||||
break;
|
||||
case XFS_HEALTHMON_AG:
|
||||
case XFS_HEALTHMON_RTGROUP:
|
||||
__entry->mask = event->grpmask;
|
||||
__entry->group = event->group;
|
||||
break;
|
||||
case XFS_HEALTHMON_INODE:
|
||||
__entry->mask = event->imask;
|
||||
__entry->ino = event->ino;
|
||||
__entry->gen = event->gen;
|
||||
break;
|
||||
}
|
||||
),
|
||||
TP_printk("dev %d:%d type %s domain %s mask 0x%x ino 0x%llx gen 0x%x offset 0x%llx len 0x%llx group 0x%x lost %llu",
|
||||
|
|
@ -6081,6 +6108,105 @@ DEFINE_HEALTHMONEVENT_EVENT(xfs_healthmon_format_overflow);
|
|||
DEFINE_HEALTHMONEVENT_EVENT(xfs_healthmon_drop);
|
||||
DEFINE_HEALTHMONEVENT_EVENT(xfs_healthmon_merge);
|
||||
|
||||
TRACE_EVENT(xfs_healthmon_report_fs,
|
||||
TP_PROTO(const struct xfs_healthmon *hm,
|
||||
unsigned int old_mask, unsigned int new_mask,
|
||||
const struct xfs_healthmon_event *event),
|
||||
TP_ARGS(hm, old_mask, new_mask, event),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(unsigned int, type)
|
||||
__field(unsigned int, domain)
|
||||
__field(unsigned int, old_mask)
|
||||
__field(unsigned int, new_mask)
|
||||
__field(unsigned int, fsmask)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = hm->dev;
|
||||
__entry->type = event->type;
|
||||
__entry->domain = event->domain;
|
||||
__entry->old_mask = old_mask;
|
||||
__entry->new_mask = new_mask;
|
||||
__entry->fsmask = event->fsmask;
|
||||
),
|
||||
TP_printk("dev %d:%d type %s domain %s oldmask 0x%x newmask 0x%x fsmask 0x%x",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__print_symbolic(__entry->type, XFS_HEALTHMON_TYPE_STRINGS),
|
||||
__print_symbolic(__entry->domain, XFS_HEALTHMON_DOMAIN_STRINGS),
|
||||
__entry->old_mask,
|
||||
__entry->new_mask,
|
||||
__entry->fsmask)
|
||||
);
|
||||
|
||||
TRACE_EVENT(xfs_healthmon_report_group,
|
||||
TP_PROTO(const struct xfs_healthmon *hm,
|
||||
unsigned int old_mask, unsigned int new_mask,
|
||||
const struct xfs_healthmon_event *event),
|
||||
TP_ARGS(hm, old_mask, new_mask, event),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(unsigned int, type)
|
||||
__field(unsigned int, domain)
|
||||
__field(unsigned int, old_mask)
|
||||
__field(unsigned int, new_mask)
|
||||
__field(unsigned int, grpmask)
|
||||
__field(unsigned int, group)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = hm->dev;
|
||||
__entry->type = event->type;
|
||||
__entry->domain = event->domain;
|
||||
__entry->old_mask = old_mask;
|
||||
__entry->new_mask = new_mask;
|
||||
__entry->grpmask = event->grpmask;
|
||||
__entry->group = event->group;
|
||||
),
|
||||
TP_printk("dev %d:%d type %s domain %s oldmask 0x%x newmask 0x%x grpmask 0x%x group 0x%x",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__print_symbolic(__entry->type, XFS_HEALTHMON_TYPE_STRINGS),
|
||||
__print_symbolic(__entry->domain, XFS_HEALTHMON_DOMAIN_STRINGS),
|
||||
__entry->old_mask,
|
||||
__entry->new_mask,
|
||||
__entry->grpmask,
|
||||
__entry->group)
|
||||
);
|
||||
|
||||
TRACE_EVENT(xfs_healthmon_report_inode,
|
||||
TP_PROTO(const struct xfs_healthmon *hm,
|
||||
unsigned int old_mask, unsigned int new_mask,
|
||||
const struct xfs_healthmon_event *event),
|
||||
TP_ARGS(hm, old_mask, new_mask, event),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(unsigned int, type)
|
||||
__field(unsigned int, domain)
|
||||
__field(unsigned int, old_mask)
|
||||
__field(unsigned int, new_mask)
|
||||
__field(unsigned int, imask)
|
||||
__field(unsigned long long, ino)
|
||||
__field(unsigned int, gen)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = hm->dev;
|
||||
__entry->type = event->type;
|
||||
__entry->domain = event->domain;
|
||||
__entry->old_mask = old_mask;
|
||||
__entry->new_mask = new_mask;
|
||||
__entry->imask = event->imask;
|
||||
__entry->ino = event->ino;
|
||||
__entry->gen = event->gen;
|
||||
),
|
||||
TP_printk("dev %d:%d type %s domain %s oldmask 0x%x newmask 0x%x imask 0x%x ino 0x%llx gen 0x%x",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__print_symbolic(__entry->type, XFS_HEALTHMON_TYPE_STRINGS),
|
||||
__print_symbolic(__entry->domain, XFS_HEALTHMON_DOMAIN_STRINGS),
|
||||
__entry->old_mask,
|
||||
__entry->new_mask,
|
||||
__entry->imask,
|
||||
__entry->ino,
|
||||
__entry->gen)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_XFS_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue