Commit | Line | Data |
---|---|---|
508578f2 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
6772c1f1 DW |
2 | /* |
3 | * Copyright (C) 2019 Oracle. All Rights Reserved. | |
4 | * Author: Darrick J. Wong <darrick.wong@oracle.com> | |
5 | */ | |
6 | #ifndef __XFS_HEALTH_H__ | |
7 | #define __XFS_HEALTH_H__ | |
8 | ||
9 | /* | |
10 | * In-Core Filesystem Health Assessments | |
11 | * ===================================== | |
12 | * | |
13 | * We'd like to be able to summarize the current health status of the | |
14 | * filesystem so that the administrator knows when it's necessary to schedule | |
15 | * some downtime for repairs. Until then, we would also like to avoid abrupt | |
16 | * shutdowns due to corrupt metadata. | |
17 | * | |
18 | * The online scrub feature evaluates the health of all filesystem metadata. | |
19 | * When scrub detects corruption in a piece of metadata it will set the | |
20 | * corresponding sickness flag, and repair will clear it if successful. If | |
21 | * problems remain at unmount time, we can also request manual intervention by | |
22 | * logging a notice to run xfs_repair. | |
23 | * | |
24 | * Each health tracking group uses a pair of fields for reporting. The | |
25 | * "checked" field tell us if a given piece of metadata has ever been examined, | |
26 | * and the "sick" field tells us if that piece was found to need repairs. | |
27 | * Therefore we can conclude that for a given sick flag value: | |
28 | * | |
de6077ec DW |
29 | * - checked && sick => metadata needs repair |
30 | * - checked && !sick => metadata is ok | |
31 | * - !checked && sick => errors have been observed during normal operation, | |
32 | * but the metadata has not been checked thoroughly | |
33 | * - !checked && !sick => has not been examined since mount | |
4e587917 DW |
34 | * |
35 | * Evidence of health problems can be sorted into three basic categories: | |
36 | * | |
37 | * a) Primary evidence, which signals that something is defective within the | |
38 | * general grouping of metadata. | |
39 | * | |
40 | * b) Secondary evidence, which are side effects of primary problem but are | |
41 | * not themselves problems. These can be forgotten when the primary | |
42 | * health problems are addressed. | |
43 | * | |
44 | * c) Indirect evidence, which points to something being wrong in another | |
45 | * group, but we had to release resources and this is all that's left of | |
46 | * that state. | |
6772c1f1 DW |
47 | */ |
48 | ||
49 | struct xfs_mount; | |
50 | struct xfs_perag; | |
51 | struct xfs_inode; | |
c23232d4 | 52 | struct xfs_fsop_geom; |
a78d10f4 | 53 | struct xfs_btree_cur; |
ca14c096 | 54 | struct xfs_da_args; |
6772c1f1 DW |
55 | |
56 | /* Observable health issues for metadata spanning the entire filesystem. */ | |
57 | #define XFS_SICK_FS_COUNTERS (1 << 0) /* summary counters */ | |
58 | #define XFS_SICK_FS_UQUOTA (1 << 1) /* user quota */ | |
59 | #define XFS_SICK_FS_GQUOTA (1 << 2) /* group quota */ | |
60 | #define XFS_SICK_FS_PQUOTA (1 << 3) /* project quota */ | |
3d8f1426 | 61 | #define XFS_SICK_FS_QUOTACHECK (1 << 4) /* quota counts */ |
93687ee2 | 62 | #define XFS_SICK_FS_NLINKS (1 << 5) /* inode link counts */ |
6772c1f1 DW |
63 | |
64 | /* Observable health issues for realtime volume metadata. */ | |
65 | #define XFS_SICK_RT_BITMAP (1 << 0) /* realtime bitmap */ | |
66 | #define XFS_SICK_RT_SUMMARY (1 << 1) /* realtime summary */ | |
67 | ||
68 | /* Observable health issues for AG metadata. */ | |
69 | #define XFS_SICK_AG_SB (1 << 0) /* superblock */ | |
70 | #define XFS_SICK_AG_AGF (1 << 1) /* AGF header */ | |
71 | #define XFS_SICK_AG_AGFL (1 << 2) /* AGFL header */ | |
72 | #define XFS_SICK_AG_AGI (1 << 3) /* AGI header */ | |
73 | #define XFS_SICK_AG_BNOBT (1 << 4) /* free space by block */ | |
74 | #define XFS_SICK_AG_CNTBT (1 << 5) /* free space by length */ | |
75 | #define XFS_SICK_AG_INOBT (1 << 6) /* inode index */ | |
76 | #define XFS_SICK_AG_FINOBT (1 << 7) /* free inode index */ | |
77 | #define XFS_SICK_AG_RMAPBT (1 << 8) /* reverse mappings */ | |
78 | #define XFS_SICK_AG_REFCNTBT (1 << 9) /* reference counts */ | |
0e24ec3c | 79 | #define XFS_SICK_AG_INODES (1 << 10) /* inactivated bad inodes */ |
6772c1f1 DW |
80 | |
81 | /* Observable health issues for inode metadata. */ | |
82 | #define XFS_SICK_INO_CORE (1 << 0) /* inode core */ | |
83 | #define XFS_SICK_INO_BMBTD (1 << 1) /* data fork */ | |
84 | #define XFS_SICK_INO_BMBTA (1 << 2) /* attr fork */ | |
85 | #define XFS_SICK_INO_BMBTC (1 << 3) /* cow fork */ | |
86 | #define XFS_SICK_INO_DIR (1 << 4) /* directory */ | |
87 | #define XFS_SICK_INO_XATTR (1 << 5) /* extended attributes */ | |
88 | #define XFS_SICK_INO_SYMLINK (1 << 6) /* symbolic link remote target */ | |
89 | #define XFS_SICK_INO_PARENT (1 << 7) /* parent pointers */ | |
90 | ||
d9041681 DW |
91 | #define XFS_SICK_INO_BMBTD_ZAPPED (1 << 8) /* data fork erased */ |
92 | #define XFS_SICK_INO_BMBTA_ZAPPED (1 << 9) /* attr fork erased */ | |
93 | #define XFS_SICK_INO_DIR_ZAPPED (1 << 10) /* directory erased */ | |
94 | #define XFS_SICK_INO_SYMLINK_ZAPPED (1 << 11) /* symlink erased */ | |
95 | ||
0e24ec3c DW |
96 | /* Don't propagate sick status to ag health summary during inactivation */ |
97 | #define XFS_SICK_INO_FORGET (1 << 12) | |
98 | ||
6772c1f1 DW |
99 | /* Primary evidence of health problems in a given group. */ |
100 | #define XFS_SICK_FS_PRIMARY (XFS_SICK_FS_COUNTERS | \ | |
101 | XFS_SICK_FS_UQUOTA | \ | |
102 | XFS_SICK_FS_GQUOTA | \ | |
3d8f1426 | 103 | XFS_SICK_FS_PQUOTA | \ |
93687ee2 DW |
104 | XFS_SICK_FS_QUOTACHECK | \ |
105 | XFS_SICK_FS_NLINKS) | |
6772c1f1 DW |
106 | |
107 | #define XFS_SICK_RT_PRIMARY (XFS_SICK_RT_BITMAP | \ | |
108 | XFS_SICK_RT_SUMMARY) | |
109 | ||
110 | #define XFS_SICK_AG_PRIMARY (XFS_SICK_AG_SB | \ | |
111 | XFS_SICK_AG_AGF | \ | |
112 | XFS_SICK_AG_AGFL | \ | |
113 | XFS_SICK_AG_AGI | \ | |
114 | XFS_SICK_AG_BNOBT | \ | |
115 | XFS_SICK_AG_CNTBT | \ | |
116 | XFS_SICK_AG_INOBT | \ | |
117 | XFS_SICK_AG_FINOBT | \ | |
118 | XFS_SICK_AG_RMAPBT | \ | |
119 | XFS_SICK_AG_REFCNTBT) | |
120 | ||
121 | #define XFS_SICK_INO_PRIMARY (XFS_SICK_INO_CORE | \ | |
122 | XFS_SICK_INO_BMBTD | \ | |
123 | XFS_SICK_INO_BMBTA | \ | |
124 | XFS_SICK_INO_BMBTC | \ | |
125 | XFS_SICK_INO_DIR | \ | |
126 | XFS_SICK_INO_XATTR | \ | |
127 | XFS_SICK_INO_SYMLINK | \ | |
128 | XFS_SICK_INO_PARENT) | |
129 | ||
d9041681 DW |
130 | #define XFS_SICK_INO_ZAPPED (XFS_SICK_INO_BMBTD_ZAPPED | \ |
131 | XFS_SICK_INO_BMBTA_ZAPPED | \ | |
132 | XFS_SICK_INO_DIR_ZAPPED | \ | |
133 | XFS_SICK_INO_SYMLINK_ZAPPED) | |
134 | ||
4e587917 DW |
135 | /* Secondary state related to (but not primary evidence of) health problems. */ |
136 | #define XFS_SICK_FS_SECONDARY (0) | |
137 | #define XFS_SICK_RT_SECONDARY (0) | |
138 | #define XFS_SICK_AG_SECONDARY (0) | |
0e24ec3c | 139 | #define XFS_SICK_INO_SECONDARY (XFS_SICK_INO_FORGET) |
4e587917 DW |
140 | |
141 | /* Evidence of health problems elsewhere. */ | |
142 | #define XFS_SICK_FS_INDIRECT (0) | |
143 | #define XFS_SICK_RT_INDIRECT (0) | |
0e24ec3c | 144 | #define XFS_SICK_AG_INDIRECT (XFS_SICK_AG_INODES) |
4e587917 DW |
145 | #define XFS_SICK_INO_INDIRECT (0) |
146 | ||
147 | /* All health masks. */ | |
148 | #define XFS_SICK_FS_ALL (XFS_SICK_FS_PRIMARY | \ | |
149 | XFS_SICK_FS_SECONDARY | \ | |
150 | XFS_SICK_FS_INDIRECT) | |
151 | ||
152 | #define XFS_SICK_RT_ALL (XFS_SICK_RT_PRIMARY | \ | |
153 | XFS_SICK_RT_SECONDARY | \ | |
154 | XFS_SICK_RT_INDIRECT) | |
155 | ||
156 | #define XFS_SICK_AG_ALL (XFS_SICK_AG_PRIMARY | \ | |
157 | XFS_SICK_AG_SECONDARY | \ | |
158 | XFS_SICK_AG_INDIRECT) | |
159 | ||
160 | #define XFS_SICK_INO_ALL (XFS_SICK_INO_PRIMARY | \ | |
161 | XFS_SICK_INO_SECONDARY | \ | |
162 | XFS_SICK_INO_INDIRECT | \ | |
163 | XFS_SICK_INO_ZAPPED) | |
164 | ||
0b8686f1 DW |
165 | /* |
166 | * These functions must be provided by the xfs implementation. Function | |
167 | * behavior with respect to the first argument should be as follows: | |
168 | * | |
169 | * xfs_*_mark_sick: Set the sick flags and do not set checked flags. | |
170 | * Runtime code should call this upon encountering | |
171 | * a corruption. | |
172 | * | |
173 | * xfs_*_mark_corrupt: Set the sick and checked flags simultaneously. | |
174 | * Fsck tools should call this when corruption is | |
175 | * found. | |
176 | * | |
177 | * xfs_*_mark_healthy: Clear the sick flags and set the checked flags. | |
178 | * Fsck tools should call this after correcting errors. | |
179 | * | |
180 | * xfs_*_measure_sickness: Return the sick and check status in the provided | |
181 | * out parameters. | |
182 | */ | |
6772c1f1 DW |
183 | |
184 | void xfs_fs_mark_sick(struct xfs_mount *mp, unsigned int mask); | |
0b8686f1 | 185 | void xfs_fs_mark_corrupt(struct xfs_mount *mp, unsigned int mask); |
6772c1f1 DW |
186 | void xfs_fs_mark_healthy(struct xfs_mount *mp, unsigned int mask); |
187 | void xfs_fs_measure_sickness(struct xfs_mount *mp, unsigned int *sick, | |
188 | unsigned int *checked); | |
189 | ||
190 | void xfs_rt_mark_sick(struct xfs_mount *mp, unsigned int mask); | |
0b8686f1 | 191 | void xfs_rt_mark_corrupt(struct xfs_mount *mp, unsigned int mask); |
6772c1f1 DW |
192 | void xfs_rt_mark_healthy(struct xfs_mount *mp, unsigned int mask); |
193 | void xfs_rt_measure_sickness(struct xfs_mount *mp, unsigned int *sick, | |
194 | unsigned int *checked); | |
195 | ||
de6077ec DW |
196 | void xfs_agno_mark_sick(struct xfs_mount *mp, xfs_agnumber_t agno, |
197 | unsigned int mask); | |
6772c1f1 | 198 | void xfs_ag_mark_sick(struct xfs_perag *pag, unsigned int mask); |
0b8686f1 | 199 | void xfs_ag_mark_corrupt(struct xfs_perag *pag, unsigned int mask); |
6772c1f1 DW |
200 | void xfs_ag_mark_healthy(struct xfs_perag *pag, unsigned int mask); |
201 | void xfs_ag_measure_sickness(struct xfs_perag *pag, unsigned int *sick, | |
202 | unsigned int *checked); | |
203 | ||
204 | void xfs_inode_mark_sick(struct xfs_inode *ip, unsigned int mask); | |
0b8686f1 | 205 | void xfs_inode_mark_corrupt(struct xfs_inode *ip, unsigned int mask); |
6772c1f1 DW |
206 | void xfs_inode_mark_healthy(struct xfs_inode *ip, unsigned int mask); |
207 | void xfs_inode_measure_sickness(struct xfs_inode *ip, unsigned int *sick, | |
208 | unsigned int *checked); | |
209 | ||
519841c2 | 210 | void xfs_health_unmount(struct xfs_mount *mp); |
1196f3f5 | 211 | void xfs_bmap_mark_sick(struct xfs_inode *ip, int whichfork); |
a78d10f4 | 212 | void xfs_btree_mark_sick(struct xfs_btree_cur *cur); |
ca14c096 DW |
213 | void xfs_dirattr_mark_sick(struct xfs_inode *ip, int whichfork); |
214 | void xfs_da_mark_sick(struct xfs_da_args *args); | |
519841c2 | 215 | |
6772c1f1 DW |
216 | /* Now some helpers. */ |
217 | ||
218 | static inline bool | |
219 | xfs_fs_has_sickness(struct xfs_mount *mp, unsigned int mask) | |
220 | { | |
221 | unsigned int sick, checked; | |
222 | ||
223 | xfs_fs_measure_sickness(mp, &sick, &checked); | |
224 | return sick & mask; | |
225 | } | |
226 | ||
227 | static inline bool | |
228 | xfs_rt_has_sickness(struct xfs_mount *mp, unsigned int mask) | |
229 | { | |
230 | unsigned int sick, checked; | |
231 | ||
232 | xfs_rt_measure_sickness(mp, &sick, &checked); | |
233 | return sick & mask; | |
234 | } | |
235 | ||
236 | static inline bool | |
237 | xfs_ag_has_sickness(struct xfs_perag *pag, unsigned int mask) | |
238 | { | |
239 | unsigned int sick, checked; | |
240 | ||
241 | xfs_ag_measure_sickness(pag, &sick, &checked); | |
242 | return sick & mask; | |
243 | } | |
244 | ||
245 | static inline bool | |
246 | xfs_inode_has_sickness(struct xfs_inode *ip, unsigned int mask) | |
247 | { | |
248 | unsigned int sick, checked; | |
249 | ||
250 | xfs_inode_measure_sickness(ip, &sick, &checked); | |
251 | return sick & mask; | |
252 | } | |
253 | ||
254 | static inline bool | |
255 | xfs_fs_is_healthy(struct xfs_mount *mp) | |
256 | { | |
257 | return !xfs_fs_has_sickness(mp, -1U); | |
258 | } | |
259 | ||
260 | static inline bool | |
261 | xfs_rt_is_healthy(struct xfs_mount *mp) | |
262 | { | |
263 | return !xfs_rt_has_sickness(mp, -1U); | |
264 | } | |
265 | ||
266 | static inline bool | |
267 | xfs_ag_is_healthy(struct xfs_perag *pag) | |
268 | { | |
269 | return !xfs_ag_has_sickness(pag, -1U); | |
270 | } | |
271 | ||
272 | static inline bool | |
273 | xfs_inode_is_healthy(struct xfs_inode *ip) | |
274 | { | |
275 | return !xfs_inode_has_sickness(ip, -1U); | |
276 | } | |
277 | ||
c23232d4 | 278 | void xfs_fsop_geom_health(struct xfs_mount *mp, struct xfs_fsop_geom *geo); |
1302c6a2 | 279 | void xfs_ag_geom_health(struct xfs_perag *pag, struct xfs_ag_geometry *ageo); |
7035f972 | 280 | void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bulkstat *bs); |
c23232d4 | 281 | |
de6077ec DW |
282 | #define xfs_metadata_is_sick(error) \ |
283 | (unlikely((error) == -EFSCORRUPTED || (error) == -EFSBADCRC)) | |
284 | ||
6772c1f1 | 285 | #endif /* __XFS_HEALTH_H__ */ |