1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
/* 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 list_head event_list;
/* 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 list_head entry;
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__ */
|