xref: /linux/fs/xfs/xfs_healthmon.h (revision 546b928da0427b0d6c663cbb992bd7bfa9ac7971)
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