1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Copyright (c) 2024-2026 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <djwong@kernel.org> 5 */ 6 #ifndef __XFS_HEALTHMON_H__ 7 #define __XFS_HEALTHMON_H__ 8 9 struct xfs_healthmon { 10 /* 11 * Weak reference to the xfs filesystem that is being monitored. It 12 * will be set to zero when the filesystem detaches from the monitor. 13 * Do not dereference this pointer. 14 */ 15 uintptr_t mount_cookie; 16 17 /* 18 * Device number of the filesystem being monitored. This is for 19 * consistent tracing even after unmount. 20 */ 21 dev_t dev; 22 23 /* 24 * Reference count of this structure. The open healthmon fd holds one 25 * ref, the xfs_mount holds another ref if it points to this object, 26 * and running event handlers hold their own refs. 27 */ 28 refcount_t ref; 29 30 /* lock for event list and event counters */ 31 struct mutex lock; 32 33 /* list of event objects */ 34 struct list_head event_list; 35 36 /* preallocated event for unmount */ 37 struct xfs_healthmon_event *unmount_event; 38 39 /* number of events in the list */ 40 unsigned int events; 41 42 /* do we want all events? */ 43 bool verbose:1; 44 45 /* waiter so read/poll can sleep until the arrival of events */ 46 struct wait_queue_head wait; 47 48 /* 49 * Buffer for formatting events for a read_iter call. Events are 50 * formatted into the buffer at bufhead, and buftail determines where 51 * to start a copy_iter to get those events to userspace. All buffer 52 * fields are protected by inode_lock. 53 */ 54 char *buffer; 55 size_t bufsize; 56 size_t bufhead; 57 size_t buftail; 58 59 /* did we lose previous events? */ 60 unsigned long long lost_prev_event; 61 62 /* total counts of events observed and lost events */ 63 unsigned long long total_events; 64 unsigned long long total_lost; 65 }; 66 67 void xfs_healthmon_unmount(struct xfs_mount *mp); 68 69 enum xfs_healthmon_type { 70 XFS_HEALTHMON_RUNNING, /* monitor running */ 71 XFS_HEALTHMON_LOST, /* message lost */ 72 XFS_HEALTHMON_UNMOUNT, /* filesystem is unmounting */ 73 74 /* filesystem shutdown */ 75 XFS_HEALTHMON_SHUTDOWN, 76 77 /* metadata health events */ 78 XFS_HEALTHMON_SICK, /* runtime corruption observed */ 79 XFS_HEALTHMON_CORRUPT, /* fsck reported corruption */ 80 XFS_HEALTHMON_HEALTHY, /* fsck reported healthy structure */ 81 82 /* media errors */ 83 XFS_HEALTHMON_MEDIA_ERROR, 84 85 /* file range events */ 86 XFS_HEALTHMON_BUFREAD, 87 XFS_HEALTHMON_BUFWRITE, 88 XFS_HEALTHMON_DIOREAD, 89 XFS_HEALTHMON_DIOWRITE, 90 XFS_HEALTHMON_DATALOST, 91 }; 92 93 enum xfs_healthmon_domain { 94 XFS_HEALTHMON_MOUNT, /* affects the whole fs */ 95 96 /* metadata health events */ 97 XFS_HEALTHMON_FS, /* main filesystem metadata */ 98 XFS_HEALTHMON_AG, /* allocation group metadata */ 99 XFS_HEALTHMON_INODE, /* inode metadata */ 100 XFS_HEALTHMON_RTGROUP, /* realtime group metadata */ 101 102 /* media errors */ 103 XFS_HEALTHMON_DATADEV, 104 XFS_HEALTHMON_RTDEV, 105 XFS_HEALTHMON_LOGDEV, 106 107 /* file range events */ 108 XFS_HEALTHMON_FILERANGE, 109 }; 110 111 struct xfs_healthmon_event { 112 struct list_head entry; 113 114 enum xfs_healthmon_type type; 115 enum xfs_healthmon_domain domain; 116 117 uint64_t time_ns; 118 119 union { 120 /* lost events */ 121 struct { 122 uint64_t lostcount; 123 }; 124 /* fs/rt metadata */ 125 struct { 126 /* XFS_SICK_* flags */ 127 unsigned int fsmask; 128 }; 129 /* ag/rtgroup metadata */ 130 struct { 131 /* XFS_SICK_(AG|RG)* flags */ 132 unsigned int grpmask; 133 unsigned int group; 134 }; 135 /* inode metadata */ 136 struct { 137 /* XFS_SICK_INO_* flags */ 138 unsigned int imask; 139 uint32_t gen; 140 xfs_ino_t ino; 141 }; 142 /* shutdown */ 143 struct { 144 unsigned int flags; 145 }; 146 /* media errors */ 147 struct { 148 xfs_daddr_t daddr; 149 uint64_t bbcount; 150 }; 151 /* file range events */ 152 struct { 153 xfs_ino_t fino; 154 loff_t fpos; 155 uint64_t flen; 156 uint32_t fgen; 157 int error; 158 }; 159 }; 160 }; 161 162 void xfs_healthmon_report_fs(struct xfs_mount *mp, 163 enum xfs_healthmon_type type, unsigned int old_mask, 164 unsigned int new_mask); 165 void xfs_healthmon_report_group(struct xfs_group *xg, 166 enum xfs_healthmon_type type, unsigned int old_mask, 167 unsigned int new_mask); 168 void xfs_healthmon_report_inode(struct xfs_inode *ip, 169 enum xfs_healthmon_type type, unsigned int old_mask, 170 unsigned int new_mask); 171 172 void xfs_healthmon_report_shutdown(struct xfs_mount *mp, uint32_t flags); 173 174 void xfs_healthmon_report_media(struct xfs_mount *mp, enum xfs_device fdev, 175 xfs_daddr_t daddr, uint64_t bbcount); 176 177 void xfs_healthmon_report_file_ioerror(struct xfs_inode *ip, 178 const struct fserror_event *p); 179 180 long xfs_ioc_health_monitor(struct file *file, 181 struct xfs_health_monitor __user *arg); 182 183 #endif /* __XFS_HEALTHMON_H__ */ 184