blob: 0e936507037fdad75e35cd7f1a17c2a6777160d7 [file] [log] [blame] [edit]
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2024-2026 Oracle. All Rights Reserved.
* Author: Darrick J. Wong <djwong@kernel.org>
*/
#ifndef __XFS_HEALTHMON_H__
#define __XFS_HEALTHMON_H__
struct xfs_healthmon {
/*
* Weak reference to the xfs filesystem that is being monitored. It
* will be set to zero when the filesystem detaches from the monitor.
* Do not dereference this pointer.
*/
uintptr_t mount_cookie;
/*
* Device number of the filesystem being monitored. This is for
* consistent tracing even after unmount.
*/
dev_t dev;
/*
* Reference count of this structure. The open healthmon fd holds one
* ref, the xfs_mount holds another ref if it points to this object,
* and running event handlers hold their own refs.
*/
refcount_t ref;
/* lock for event list and event counters */
struct mutex lock;
/* list of event objects */
struct xfs_healthmon_event *first_event;
struct xfs_healthmon_event *last_event;
/* preallocated event for unmount */
struct xfs_healthmon_event *unmount_event;
/* number of events in the list */
unsigned int events;
/* do we want all events? */
bool verbose:1;
/* waiter so read/poll can sleep until the arrival of events */
struct wait_queue_head wait;
/*
* Buffer for formatting events for a read_iter call. Events are
* formatted into the buffer at bufhead, and buftail determines where
* to start a copy_iter to get those events to userspace. All buffer
* fields are protected by inode_lock.
*/
char *buffer;
size_t bufsize;
size_t bufhead;
size_t buftail;
/* did we lose previous events? */
unsigned long long lost_prev_event;
/* total counts of events observed and lost events */
unsigned long long total_events;
unsigned long long total_lost;
};
void xfs_healthmon_unmount(struct xfs_mount *mp);
enum xfs_healthmon_type {
XFS_HEALTHMON_RUNNING, /* monitor running */
XFS_HEALTHMON_LOST, /* message lost */
XFS_HEALTHMON_UNMOUNT, /* filesystem is unmounting */
/* filesystem shutdown */
XFS_HEALTHMON_SHUTDOWN,
/* metadata health events */
XFS_HEALTHMON_SICK, /* runtime corruption observed */
XFS_HEALTHMON_CORRUPT, /* fsck reported corruption */
XFS_HEALTHMON_HEALTHY, /* fsck reported healthy structure */
/* media errors */
XFS_HEALTHMON_MEDIA_ERROR,
/* file range events */
XFS_HEALTHMON_BUFREAD,
XFS_HEALTHMON_BUFWRITE,
XFS_HEALTHMON_DIOREAD,
XFS_HEALTHMON_DIOWRITE,
XFS_HEALTHMON_DATALOST,
};
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 */
/* media errors */
XFS_HEALTHMON_DATADEV,
XFS_HEALTHMON_RTDEV,
XFS_HEALTHMON_LOGDEV,
/* file range events */
XFS_HEALTHMON_FILERANGE,
};
struct xfs_healthmon_event {
struct xfs_healthmon_event *next;
enum xfs_healthmon_type type;
enum xfs_healthmon_domain domain;
uint64_t time_ns;
union {
/* lost events */
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;
};
/* shutdown */
struct {
unsigned int flags;
};
/* media errors */
struct {
xfs_daddr_t daddr;
uint64_t bbcount;
};
/* file range events */
struct {
xfs_ino_t fino;
loff_t fpos;
uint64_t flen;
uint32_t fgen;
int error;
};
};
};
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);
void xfs_healthmon_report_shutdown(struct xfs_mount *mp, uint32_t flags);
void xfs_healthmon_report_media(struct xfs_mount *mp, enum xfs_device fdev,
xfs_daddr_t daddr, uint64_t bbcount);
void xfs_healthmon_report_file_ioerror(struct xfs_inode *ip,
const struct fserror_event *p);
long xfs_ioc_health_monitor(struct file *file,
struct xfs_health_monitor __user *arg);
#endif /* __XFS_HEALTHMON_H__ */