xref: /linux/fs/xfs/xfs_healthmon.h (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1a48373e7SDarrick J. Wong /* SPDX-License-Identifier: GPL-2.0-or-later */
2a48373e7SDarrick J. Wong /*
3a48373e7SDarrick J. Wong  * Copyright (c) 2024-2026 Oracle.  All Rights Reserved.
4a48373e7SDarrick J. Wong  * Author: Darrick J. Wong <djwong@kernel.org>
5a48373e7SDarrick J. Wong  */
6a48373e7SDarrick J. Wong #ifndef __XFS_HEALTHMON_H__
7a48373e7SDarrick J. Wong #define __XFS_HEALTHMON_H__
8a48373e7SDarrick J. Wong 
9a48373e7SDarrick J. Wong struct xfs_healthmon {
10a48373e7SDarrick J. Wong 	/*
11a48373e7SDarrick J. Wong 	 * Weak reference to the xfs filesystem that is being monitored.  It
12a48373e7SDarrick J. Wong 	 * will be set to zero when the filesystem detaches from the monitor.
13a48373e7SDarrick J. Wong 	 * Do not dereference this pointer.
14a48373e7SDarrick J. Wong 	 */
15a48373e7SDarrick J. Wong 	uintptr_t			mount_cookie;
16a48373e7SDarrick J. Wong 
17a48373e7SDarrick J. Wong 	/*
18a48373e7SDarrick J. Wong 	 * Device number of the filesystem being monitored.  This is for
19a48373e7SDarrick J. Wong 	 * consistent tracing even after unmount.
20a48373e7SDarrick J. Wong 	 */
21a48373e7SDarrick J. Wong 	dev_t				dev;
22a48373e7SDarrick J. Wong 
23a48373e7SDarrick J. Wong 	/*
24a48373e7SDarrick J. Wong 	 * Reference count of this structure.  The open healthmon fd holds one
25a48373e7SDarrick J. Wong 	 * ref, the xfs_mount holds another ref if it points to this object,
26a48373e7SDarrick J. Wong 	 * and running event handlers hold their own refs.
27a48373e7SDarrick J. Wong 	 */
28a48373e7SDarrick J. Wong 	refcount_t			ref;
29b3a289a2SDarrick J. Wong 
30b3a289a2SDarrick J. Wong 	/* lock for event list and event counters */
31b3a289a2SDarrick J. Wong 	struct mutex			lock;
32b3a289a2SDarrick J. Wong 
33b3a289a2SDarrick J. Wong 	/* list of event objects */
34b3a289a2SDarrick J. Wong 	struct xfs_healthmon_event	*first_event;
35b3a289a2SDarrick J. Wong 	struct xfs_healthmon_event	*last_event;
36b3a289a2SDarrick J. Wong 
3725ca57faSDarrick J. Wong 	/* preallocated event for unmount */
3825ca57faSDarrick J. Wong 	struct xfs_healthmon_event	*unmount_event;
3925ca57faSDarrick J. Wong 
40b3a289a2SDarrick J. Wong 	/* number of events in the list */
41b3a289a2SDarrick J. Wong 	unsigned int			events;
42b3a289a2SDarrick J. Wong 
43b3a289a2SDarrick J. Wong 	/* do we want all events? */
44b3a289a2SDarrick J. Wong 	bool				verbose:1;
45b3a289a2SDarrick J. Wong 
46b3a289a2SDarrick J. Wong 	/* waiter so read/poll can sleep until the arrival of events */
47b3a289a2SDarrick J. Wong 	struct wait_queue_head		wait;
48b3a289a2SDarrick J. Wong 
49b3a289a2SDarrick J. Wong 	/*
50b3a289a2SDarrick J. Wong 	 * Buffer for formatting events for a read_iter call.  Events are
51b3a289a2SDarrick J. Wong 	 * formatted into the buffer at bufhead, and buftail determines where
52b3a289a2SDarrick J. Wong 	 * to start a copy_iter to get those events to userspace.  All buffer
53b3a289a2SDarrick J. Wong 	 * fields are protected by inode_lock.
54b3a289a2SDarrick J. Wong 	 */
55b3a289a2SDarrick J. Wong 	char				*buffer;
56b3a289a2SDarrick J. Wong 	size_t				bufsize;
57b3a289a2SDarrick J. Wong 	size_t				bufhead;
58b3a289a2SDarrick J. Wong 	size_t				buftail;
59b3a289a2SDarrick J. Wong 
60b3a289a2SDarrick J. Wong 	/* did we lose previous events? */
61b3a289a2SDarrick J. Wong 	unsigned long long		lost_prev_event;
62b3a289a2SDarrick J. Wong 
63b3a289a2SDarrick J. Wong 	/* total counts of events observed and lost events */
64b3a289a2SDarrick J. Wong 	unsigned long long		total_events;
65b3a289a2SDarrick J. Wong 	unsigned long long		total_lost;
66a48373e7SDarrick J. Wong };
67a48373e7SDarrick J. Wong 
68a48373e7SDarrick J. Wong void xfs_healthmon_unmount(struct xfs_mount *mp);
69a48373e7SDarrick J. Wong 
70b3a289a2SDarrick J. Wong enum xfs_healthmon_type {
71b3a289a2SDarrick J. Wong 	XFS_HEALTHMON_RUNNING,	/* monitor running */
72b3a289a2SDarrick J. Wong 	XFS_HEALTHMON_LOST,	/* message lost */
7325ca57faSDarrick J. Wong 	XFS_HEALTHMON_UNMOUNT,	/* filesystem is unmounting */
745eb4cb18SDarrick J. Wong 
7574c4795eSDarrick J. Wong 	/* filesystem shutdown */
7674c4795eSDarrick J. Wong 	XFS_HEALTHMON_SHUTDOWN,
7774c4795eSDarrick J. Wong 
785eb4cb18SDarrick J. Wong 	/* metadata health events */
795eb4cb18SDarrick J. Wong 	XFS_HEALTHMON_SICK,	/* runtime corruption observed */
805eb4cb18SDarrick J. Wong 	XFS_HEALTHMON_CORRUPT,	/* fsck reported corruption */
815eb4cb18SDarrick J. Wong 	XFS_HEALTHMON_HEALTHY,	/* fsck reported healthy structure */
82e76e0e3fSDarrick J. Wong 
83e76e0e3fSDarrick J. Wong 	/* media errors */
84e76e0e3fSDarrick J. Wong 	XFS_HEALTHMON_MEDIA_ERROR,
85*dfa8bad3SDarrick J. Wong 
86*dfa8bad3SDarrick J. Wong 	/* file range events */
87*dfa8bad3SDarrick J. Wong 	XFS_HEALTHMON_BUFREAD,
88*dfa8bad3SDarrick J. Wong 	XFS_HEALTHMON_BUFWRITE,
89*dfa8bad3SDarrick J. Wong 	XFS_HEALTHMON_DIOREAD,
90*dfa8bad3SDarrick J. Wong 	XFS_HEALTHMON_DIOWRITE,
91*dfa8bad3SDarrick J. Wong 	XFS_HEALTHMON_DATALOST,
92b3a289a2SDarrick J. Wong };
93b3a289a2SDarrick J. Wong 
94b3a289a2SDarrick J. Wong enum xfs_healthmon_domain {
95b3a289a2SDarrick J. Wong 	XFS_HEALTHMON_MOUNT,	/* affects the whole fs */
965eb4cb18SDarrick J. Wong 
975eb4cb18SDarrick J. Wong 	/* metadata health events */
985eb4cb18SDarrick J. Wong 	XFS_HEALTHMON_FS,	/* main filesystem metadata */
995eb4cb18SDarrick J. Wong 	XFS_HEALTHMON_AG,	/* allocation group metadata */
1005eb4cb18SDarrick J. Wong 	XFS_HEALTHMON_INODE,	/* inode metadata */
1015eb4cb18SDarrick J. Wong 	XFS_HEALTHMON_RTGROUP,	/* realtime group metadata */
102e76e0e3fSDarrick J. Wong 
103e76e0e3fSDarrick J. Wong 	/* media errors */
104e76e0e3fSDarrick J. Wong 	XFS_HEALTHMON_DATADEV,
105e76e0e3fSDarrick J. Wong 	XFS_HEALTHMON_RTDEV,
106e76e0e3fSDarrick J. Wong 	XFS_HEALTHMON_LOGDEV,
107*dfa8bad3SDarrick J. Wong 
108*dfa8bad3SDarrick J. Wong 	/* file range events */
109*dfa8bad3SDarrick J. Wong 	XFS_HEALTHMON_FILERANGE,
110b3a289a2SDarrick J. Wong };
111b3a289a2SDarrick J. Wong 
112b3a289a2SDarrick J. Wong struct xfs_healthmon_event {
113b3a289a2SDarrick J. Wong 	struct xfs_healthmon_event	*next;
114b3a289a2SDarrick J. Wong 
115b3a289a2SDarrick J. Wong 	enum xfs_healthmon_type		type;
116b3a289a2SDarrick J. Wong 	enum xfs_healthmon_domain	domain;
117b3a289a2SDarrick J. Wong 
118b3a289a2SDarrick J. Wong 	uint64_t			time_ns;
119b3a289a2SDarrick J. Wong 
120b3a289a2SDarrick J. Wong 	union {
121b3a289a2SDarrick J. Wong 		/* lost events */
122b3a289a2SDarrick J. Wong 		struct {
123b3a289a2SDarrick J. Wong 			uint64_t	lostcount;
124b3a289a2SDarrick J. Wong 		};
1255eb4cb18SDarrick J. Wong 		/* fs/rt metadata */
1265eb4cb18SDarrick J. Wong 		struct {
1275eb4cb18SDarrick J. Wong 			/* XFS_SICK_* flags */
1285eb4cb18SDarrick J. Wong 			unsigned int	fsmask;
1295eb4cb18SDarrick J. Wong 		};
1305eb4cb18SDarrick J. Wong 		/* ag/rtgroup metadata */
1315eb4cb18SDarrick J. Wong 		struct {
1325eb4cb18SDarrick J. Wong 			/* XFS_SICK_(AG|RG)* flags */
1335eb4cb18SDarrick J. Wong 			unsigned int	grpmask;
1345eb4cb18SDarrick J. Wong 			unsigned int	group;
1355eb4cb18SDarrick J. Wong 		};
1365eb4cb18SDarrick J. Wong 		/* inode metadata */
1375eb4cb18SDarrick J. Wong 		struct {
1385eb4cb18SDarrick J. Wong 			/* XFS_SICK_INO_* flags */
1395eb4cb18SDarrick J. Wong 			unsigned int	imask;
1405eb4cb18SDarrick J. Wong 			uint32_t	gen;
1415eb4cb18SDarrick J. Wong 			xfs_ino_t	ino;
142b3a289a2SDarrick J. Wong 		};
14374c4795eSDarrick J. Wong 		/* shutdown */
14474c4795eSDarrick J. Wong 		struct {
14574c4795eSDarrick J. Wong 			unsigned int	flags;
14674c4795eSDarrick J. Wong 		};
147e76e0e3fSDarrick J. Wong 		/* media errors */
148e76e0e3fSDarrick J. Wong 		struct {
149e76e0e3fSDarrick J. Wong 			xfs_daddr_t	daddr;
150e76e0e3fSDarrick J. Wong 			uint64_t	bbcount;
151e76e0e3fSDarrick J. Wong 		};
152*dfa8bad3SDarrick J. Wong 		/* file range events */
153*dfa8bad3SDarrick J. Wong 		struct {
154*dfa8bad3SDarrick J. Wong 			xfs_ino_t	fino;
155*dfa8bad3SDarrick J. Wong 			loff_t		fpos;
156*dfa8bad3SDarrick J. Wong 			uint64_t	flen;
157*dfa8bad3SDarrick J. Wong 			uint32_t	fgen;
158*dfa8bad3SDarrick J. Wong 			int		error;
159*dfa8bad3SDarrick J. Wong 		};
160b3a289a2SDarrick J. Wong 	};
1615eb4cb18SDarrick J. Wong };
1625eb4cb18SDarrick J. Wong 
1635eb4cb18SDarrick J. Wong void xfs_healthmon_report_fs(struct xfs_mount *mp,
1645eb4cb18SDarrick J. Wong 		enum xfs_healthmon_type type, unsigned int old_mask,
1655eb4cb18SDarrick J. Wong 		unsigned int new_mask);
1665eb4cb18SDarrick J. Wong void xfs_healthmon_report_group(struct xfs_group *xg,
1675eb4cb18SDarrick J. Wong 		enum xfs_healthmon_type type, unsigned int old_mask,
1685eb4cb18SDarrick J. Wong 		unsigned int new_mask);
1695eb4cb18SDarrick J. Wong void xfs_healthmon_report_inode(struct xfs_inode *ip,
1705eb4cb18SDarrick J. Wong 		enum xfs_healthmon_type type, unsigned int old_mask,
1715eb4cb18SDarrick J. Wong 		unsigned int new_mask);
172b3a289a2SDarrick J. Wong 
17374c4795eSDarrick J. Wong void xfs_healthmon_report_shutdown(struct xfs_mount *mp, uint32_t flags);
17474c4795eSDarrick J. Wong 
175e76e0e3fSDarrick J. Wong void xfs_healthmon_report_media(struct xfs_mount *mp, enum xfs_device fdev,
176e76e0e3fSDarrick J. Wong 		xfs_daddr_t daddr, uint64_t bbcount);
177e76e0e3fSDarrick J. Wong 
178*dfa8bad3SDarrick J. Wong void xfs_healthmon_report_file_ioerror(struct xfs_inode *ip,
179*dfa8bad3SDarrick J. Wong 		const struct fserror_event *p);
180*dfa8bad3SDarrick J. Wong 
181a48373e7SDarrick J. Wong long xfs_ioc_health_monitor(struct file *file,
182a48373e7SDarrick J. Wong 		struct xfs_health_monitor __user *arg);
183a48373e7SDarrick J. Wong 
184a48373e7SDarrick J. Wong #endif /* __XFS_HEALTHMON_H__ */
185