| /* 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__ */ |