Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0+
2 : /*
3 : * Copyright (C) 2019 Oracle. All Rights Reserved.
4 : * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 : */
6 : #include "xfs.h"
7 : #include "xfs_fs.h"
8 : #include "xfs_shared.h"
9 : #include "xfs_format.h"
10 : #include "xfs_log_format.h"
11 : #include "xfs_trans_resv.h"
12 : #include "xfs_mount.h"
13 : #include "xfs_inode.h"
14 : #include "xfs_trace.h"
15 : #include "xfs_health.h"
16 : #include "xfs_ag.h"
17 : #include "xfs_btree.h"
18 : #include "xfs_da_format.h"
19 : #include "xfs_da_btree.h"
20 : #include "xfs_quota_defs.h"
21 : #include "xfs_rtgroup.h"
22 :
23 : /*
24 : * Warn about metadata corruption that we detected but haven't fixed, and
25 : * make sure we're not sitting on anything that would get in the way of
26 : * recovery.
27 : */
28 : void
29 66825 : xfs_health_unmount(
30 : struct xfs_mount *mp)
31 : {
32 66825 : struct xfs_perag *pag;
33 66825 : struct xfs_rtgroup *rtg;
34 66825 : xfs_agnumber_t agno;
35 66825 : xfs_rgnumber_t rgno;
36 66825 : unsigned int sick = 0;
37 66825 : unsigned int checked = 0;
38 66825 : bool warn = false;
39 :
40 133650 : if (xfs_is_shutdown(mp))
41 12884 : return;
42 :
43 : /* Measure AG corruption levels. */
44 528649 : for_each_perag(mp, agno, pag) {
45 474708 : xfs_ag_measure_sickness(pag, &sick, &checked);
46 474708 : if (sick) {
47 129 : trace_xfs_ag_unfixed_corruption(mp, agno, sick);
48 129 : warn = true;
49 : }
50 : }
51 :
52 : /* Measure realtime group corruption levels. */
53 150493 : for_each_rtgroup(mp, rgno, rtg) {
54 96552 : xfs_rtgroup_measure_sickness(rtg, &sick, &checked);
55 96552 : if (sick) {
56 0 : trace_xfs_rtgroup_unfixed_corruption(rtg, sick);
57 0 : warn = true;
58 : }
59 : }
60 :
61 : /* Measure realtime volume corruption levels. */
62 53941 : xfs_rt_measure_sickness(mp, &sick, &checked);
63 53941 : if (sick) {
64 0 : trace_xfs_rt_unfixed_corruption(mp, sick);
65 0 : warn = true;
66 : }
67 :
68 : /*
69 : * Measure fs corruption and keep the sample around for the warning.
70 : * See the note below for why we exempt FS_COUNTERS.
71 : */
72 53941 : xfs_fs_measure_sickness(mp, &sick, &checked);
73 53941 : if (sick & ~XFS_SICK_FS_COUNTERS) {
74 26 : trace_xfs_fs_unfixed_corruption(mp, sick);
75 26 : warn = true;
76 : }
77 :
78 53941 : if (warn) {
79 136 : xfs_warn(mp,
80 : "Uncorrected metadata errors detected; please run xfs_repair.");
81 :
82 : /*
83 : * We discovered uncorrected metadata problems at some point
84 : * during this filesystem mount and have advised the
85 : * administrator to run repair once the unmount completes.
86 : *
87 : * However, we must be careful -- when FSCOUNTERS are flagged
88 : * unhealthy, the unmount procedure omits writing the clean
89 : * unmount record to the log so that the next mount will run
90 : * recovery and recompute the summary counters. In other
91 : * words, we leave a dirty log to get the counters fixed.
92 : *
93 : * Unfortunately, xfs_repair cannot recover dirty logs, so if
94 : * there were filesystem problems, FSCOUNTERS was flagged, and
95 : * the administrator takes our advice to run xfs_repair,
96 : * they'll have to zap the log before repairing structures.
97 : * We don't really want to encourage this, so we mark the
98 : * FSCOUNTERS healthy so that a subsequent repair run won't see
99 : * a dirty log.
100 : */
101 136 : if (sick & XFS_SICK_FS_COUNTERS)
102 0 : xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS);
103 : }
104 : }
105 :
106 : /* Mark unhealthy per-fs metadata. */
107 : void
108 813645 : xfs_fs_mark_sick(
109 : struct xfs_mount *mp,
110 : unsigned int mask)
111 : {
112 813645 : ASSERT(!(mask & ~XFS_SICK_FS_ALL));
113 813645 : trace_xfs_fs_mark_sick(mp, mask);
114 :
115 813363 : spin_lock(&mp->m_sb_lock);
116 814093 : mp->m_fs_sick |= mask;
117 814093 : spin_unlock(&mp->m_sb_lock);
118 814089 : }
119 :
120 : /* Mark per-fs metadata as having been checked. */
121 : void
122 814045 : xfs_fs_mark_checked(
123 : struct xfs_mount *mp,
124 : unsigned int mask)
125 : {
126 814045 : ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
127 :
128 814045 : spin_lock(&mp->m_sb_lock);
129 814051 : mp->m_fs_checked |= mask;
130 814051 : spin_unlock(&mp->m_sb_lock);
131 814044 : }
132 :
133 : /* Mark a per-fs metadata healed. */
134 : void
135 482078 : xfs_fs_mark_healthy(
136 : struct xfs_mount *mp,
137 : unsigned int mask)
138 : {
139 482078 : ASSERT(!(mask & ~XFS_SICK_FS_ALL));
140 482078 : trace_xfs_fs_mark_healthy(mp, mask);
141 :
142 482069 : spin_lock(&mp->m_sb_lock);
143 482100 : mp->m_fs_sick &= ~mask;
144 482100 : if (!(mp->m_fs_sick & XFS_SICK_FS_PRIMARY))
145 : mp->m_fs_sick &= ~XFS_SICK_FS_SECONDARY;
146 482100 : mp->m_fs_checked |= mask;
147 482100 : spin_unlock(&mp->m_sb_lock);
148 482100 : }
149 :
150 : /* Sample which per-fs metadata are unhealthy. */
151 : void
152 135103 : xfs_fs_measure_sickness(
153 : struct xfs_mount *mp,
154 : unsigned int *sick,
155 : unsigned int *checked)
156 : {
157 189044 : spin_lock(&mp->m_sb_lock);
158 7416347 : *sick = mp->m_fs_sick;
159 7416347 : *checked = mp->m_fs_checked;
160 7416347 : spin_unlock(&mp->m_sb_lock);
161 135103 : }
162 :
163 : /* Mark unhealthy realtime metadata. */
164 : void
165 0 : xfs_rt_mark_sick(
166 : struct xfs_mount *mp,
167 : unsigned int mask)
168 : {
169 0 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
170 0 : trace_xfs_rt_mark_sick(mp, mask);
171 :
172 0 : spin_lock(&mp->m_sb_lock);
173 0 : mp->m_rt_sick |= mask;
174 0 : spin_unlock(&mp->m_sb_lock);
175 0 : }
176 :
177 : /* Mark realtime metadata as having been checked. */
178 : void
179 0 : xfs_rt_mark_checked(
180 : struct xfs_mount *mp,
181 : unsigned int mask)
182 : {
183 0 : ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
184 0 : trace_xfs_rt_mark_sick(mp, mask);
185 :
186 0 : spin_lock(&mp->m_sb_lock);
187 0 : mp->m_rt_checked |= mask;
188 0 : spin_unlock(&mp->m_sb_lock);
189 0 : }
190 :
191 : /* Mark a realtime metadata healed. */
192 : void
193 197151 : xfs_rt_mark_healthy(
194 : struct xfs_mount *mp,
195 : unsigned int mask)
196 : {
197 197151 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
198 197151 : trace_xfs_rt_mark_healthy(mp, mask);
199 :
200 197151 : spin_lock(&mp->m_sb_lock);
201 197151 : mp->m_rt_sick &= ~mask;
202 197151 : if (!(mp->m_rt_sick & XFS_SICK_RT_PRIMARY))
203 : mp->m_rt_sick &= ~XFS_SICK_RT_SECONDARY;
204 197151 : mp->m_rt_checked |= mask;
205 197151 : spin_unlock(&mp->m_sb_lock);
206 197151 : }
207 :
208 : /* Sample which realtime metadata are unhealthy. */
209 : void
210 25682 : xfs_rt_measure_sickness(
211 : struct xfs_mount *mp,
212 : unsigned int *sick,
213 : unsigned int *checked)
214 : {
215 79623 : spin_lock(&mp->m_sb_lock);
216 7306926 : *sick = mp->m_rt_sick;
217 7306926 : *checked = mp->m_rt_checked;
218 7306926 : spin_unlock(&mp->m_sb_lock);
219 25682 : }
220 :
221 : /* Mark unhealthy per-ag metadata given a raw AG number. */
222 : void
223 2018 : xfs_agno_mark_sick(
224 : struct xfs_mount *mp,
225 : xfs_agnumber_t agno,
226 : unsigned int mask)
227 : {
228 2018 : struct xfs_perag *pag = xfs_perag_get(mp, agno);
229 :
230 : /* per-ag structure not set up yet? */
231 2018 : if (!pag)
232 : return;
233 :
234 2018 : xfs_ag_mark_sick(pag, mask);
235 2018 : xfs_perag_put(pag);
236 : }
237 :
238 : /* Mark unhealthy per-ag metadata. */
239 : void
240 5516 : xfs_ag_mark_sick(
241 : struct xfs_perag *pag,
242 : unsigned int mask)
243 : {
244 5516 : ASSERT(!(mask & ~XFS_SICK_AG_ALL));
245 5516 : trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask);
246 :
247 5516 : spin_lock(&pag->pag_state_lock);
248 5516 : pag->pag_sick |= mask;
249 5516 : spin_unlock(&pag->pag_state_lock);
250 5516 : }
251 :
252 : /* Mark per-ag metadata as having been checked. */
253 : void
254 100 : xfs_ag_mark_checked(
255 : struct xfs_perag *pag,
256 : unsigned int mask)
257 : {
258 100 : ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
259 :
260 100 : spin_lock(&pag->pag_state_lock);
261 100 : pag->pag_checked |= mask;
262 100 : spin_unlock(&pag->pag_state_lock);
263 100 : }
264 :
265 : /* Mark per-ag metadata ok. */
266 : void
267 6340352 : xfs_ag_mark_healthy(
268 : struct xfs_perag *pag,
269 : unsigned int mask)
270 : {
271 6340352 : ASSERT(!(mask & ~XFS_SICK_AG_ALL));
272 6340352 : trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask);
273 :
274 6338898 : spin_lock(&pag->pag_state_lock);
275 6340627 : pag->pag_sick &= ~mask;
276 6340627 : if (!(pag->pag_sick & XFS_SICK_AG_PRIMARY))
277 : pag->pag_sick &= ~XFS_SICK_AG_SECONDARY;
278 6340627 : pag->pag_checked |= mask;
279 6340627 : spin_unlock(&pag->pag_state_lock);
280 6340541 : }
281 :
282 : /* Sample which per-ag metadata are unhealthy. */
283 : void
284 4480215355 : xfs_ag_measure_sickness(
285 : struct xfs_perag *pag,
286 : unsigned int *sick,
287 : unsigned int *checked)
288 : {
289 4480690063 : spin_lock(&pag->pag_state_lock);
290 4482402661 : *sick = pag->pag_sick;
291 4482402661 : *checked = pag->pag_checked;
292 4482402661 : spin_unlock(&pag->pag_state_lock);
293 4482773548 : }
294 :
295 : /* Mark unhealthy per-rtgroup metadata given a raw rt group number. */
296 : void
297 0 : xfs_rgno_mark_sick(
298 : struct xfs_mount *mp,
299 : xfs_rgnumber_t rgno,
300 : unsigned int mask)
301 : {
302 0 : struct xfs_rtgroup *rtg = xfs_rtgroup_get(mp, rgno);
303 :
304 : /* per-rtgroup structure not set up yet? */
305 0 : if (!rtg)
306 : return;
307 :
308 0 : xfs_rtgroup_mark_sick(rtg, mask);
309 0 : xfs_rtgroup_put(rtg);
310 : }
311 :
312 : /* Mark unhealthy per-rtgroup metadata. */
313 : void
314 2 : xfs_rtgroup_mark_sick(
315 : struct xfs_rtgroup *rtg,
316 : unsigned int mask)
317 : {
318 2 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
319 2 : trace_xfs_rtgroup_mark_sick(rtg, mask);
320 :
321 2 : spin_lock(&rtg->rtg_state_lock);
322 2 : rtg->rtg_sick |= mask;
323 2 : spin_unlock(&rtg->rtg_state_lock);
324 2 : }
325 :
326 : /* Mark per-rtgroup metadata as having been checked. */
327 : void
328 0 : xfs_rtgroup_mark_checked(
329 : struct xfs_rtgroup *rtg,
330 : unsigned int mask)
331 : {
332 0 : ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
333 :
334 0 : spin_lock(&rtg->rtg_state_lock);
335 0 : rtg->rtg_checked |= mask;
336 0 : spin_unlock(&rtg->rtg_state_lock);
337 0 : }
338 :
339 : /* Mark per-rtgroup metadata ok. */
340 : void
341 385903 : xfs_rtgroup_mark_healthy(
342 : struct xfs_rtgroup *rtg,
343 : unsigned int mask)
344 : {
345 385903 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
346 385903 : trace_xfs_rtgroup_mark_healthy(rtg, mask);
347 :
348 385841 : spin_lock(&rtg->rtg_state_lock);
349 385927 : rtg->rtg_sick &= ~mask;
350 385927 : if (!(rtg->rtg_sick & XFS_SICK_RT_PRIMARY))
351 : rtg->rtg_sick &= ~XFS_SICK_RT_SECONDARY;
352 385927 : rtg->rtg_checked |= mask;
353 385927 : spin_unlock(&rtg->rtg_state_lock);
354 385939 : }
355 :
356 : /* Sample which per-rtgroup metadata are unhealthy. */
357 : void
358 55008 : xfs_rtgroup_measure_sickness(
359 : struct xfs_rtgroup *rtg,
360 : unsigned int *sick,
361 : unsigned int *checked)
362 : {
363 151560 : spin_lock(&rtg->rtg_state_lock);
364 171031 : *sick = rtg->rtg_sick;
365 171031 : *checked = rtg->rtg_checked;
366 171031 : spin_unlock(&rtg->rtg_state_lock);
367 55008 : }
368 :
369 : /* Mark the unhealthy parts of an inode. */
370 : void
371 1438 : xfs_inode_mark_sick(
372 : struct xfs_inode *ip,
373 : unsigned int mask)
374 : {
375 1438 : ASSERT(!(mask & ~XFS_SICK_INO_ALL));
376 1438 : trace_xfs_inode_mark_sick(ip, mask);
377 :
378 1438 : spin_lock(&ip->i_flags_lock);
379 1438 : ip->i_sick |= mask;
380 1438 : spin_unlock(&ip->i_flags_lock);
381 :
382 : /*
383 : * Keep this inode around so we don't lose the sickness report. Scrub
384 : * grabs inodes with DONTCACHE assuming that most inode are ok, which
385 : * is not the case here.
386 : */
387 1438 : spin_lock(&VFS_I(ip)->i_lock);
388 1438 : VFS_I(ip)->i_state &= ~I_DONTCACHE;
389 1438 : spin_unlock(&VFS_I(ip)->i_lock);
390 1438 : }
391 :
392 : /* Mark inode metadata as having been checked. */
393 : void
394 33 : xfs_inode_mark_checked(
395 : struct xfs_inode *ip,
396 : unsigned int mask)
397 : {
398 33 : ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
399 :
400 33 : spin_lock(&ip->i_flags_lock);
401 33 : ip->i_checked |= mask;
402 33 : spin_unlock(&ip->i_flags_lock);
403 33 : }
404 :
405 : /* Mark parts of an inode healed. */
406 : void
407 721728644 : xfs_inode_mark_healthy(
408 : struct xfs_inode *ip,
409 : unsigned int mask)
410 : {
411 721728644 : ASSERT(!(mask & ~XFS_SICK_INO_ALL));
412 721728644 : trace_xfs_inode_mark_healthy(ip, mask);
413 :
414 721529706 : spin_lock(&ip->i_flags_lock);
415 723486143 : ip->i_sick &= ~mask;
416 723486143 : if (!(ip->i_sick & XFS_SICK_INO_PRIMARY))
417 723381732 : ip->i_sick &= ~XFS_SICK_INO_SECONDARY;
418 723486143 : ip->i_checked |= mask;
419 723486143 : spin_unlock(&ip->i_flags_lock);
420 723463242 : }
421 :
422 : /* Sample which parts of an inode are unhealthy. */
423 : void
424 76215549 : xfs_inode_measure_sickness(
425 : struct xfs_inode *ip,
426 : unsigned int *sick,
427 : unsigned int *checked)
428 : {
429 76215549 : spin_lock(&ip->i_flags_lock);
430 82568607091 : *sick = ip->i_sick;
431 82568607091 : *checked = ip->i_checked;
432 82568607091 : spin_unlock(&ip->i_flags_lock);
433 76404548 : }
434 :
435 : /* Mappings between internal sick masks and ioctl sick masks. */
436 :
437 : struct ioctl_sick_map {
438 : unsigned int sick_mask;
439 : unsigned int ioctl_mask;
440 : };
441 :
442 : static const struct ioctl_sick_map fs_map[] = {
443 : { XFS_SICK_FS_COUNTERS, XFS_FSOP_GEOM_SICK_COUNTERS},
444 : { XFS_SICK_FS_UQUOTA, XFS_FSOP_GEOM_SICK_UQUOTA },
445 : { XFS_SICK_FS_GQUOTA, XFS_FSOP_GEOM_SICK_GQUOTA },
446 : { XFS_SICK_FS_PQUOTA, XFS_FSOP_GEOM_SICK_PQUOTA },
447 : { XFS_SICK_FS_QUOTACHECK, XFS_FSOP_GEOM_SICK_QUOTACHECK },
448 : { XFS_SICK_FS_NLINKS, XFS_FSOP_GEOM_SICK_NLINKS },
449 : { XFS_SICK_FS_METADIR, XFS_FSOP_GEOM_SICK_METADIR },
450 : { 0, 0 },
451 : };
452 :
453 : static const struct ioctl_sick_map rt_map[] = {
454 : { XFS_SICK_RT_BITMAP, XFS_FSOP_GEOM_SICK_RT_BITMAP },
455 : { XFS_SICK_RT_SUMMARY, XFS_FSOP_GEOM_SICK_RT_SUMMARY },
456 : { 0, 0 },
457 : };
458 :
459 : static inline void
460 64877824 : xfgeo_health_tick(
461 : struct xfs_fsop_geom *geo,
462 : unsigned int sick,
463 : unsigned int checked,
464 : const struct ioctl_sick_map *m)
465 : {
466 64877824 : if (checked & m->sick_mask)
467 4903936 : geo->checked |= m->ioctl_mask;
468 64877824 : if (sick & m->sick_mask)
469 167634 : geo->sick |= m->ioctl_mask;
470 64877824 : }
471 :
472 : /* Fill out fs geometry health info. */
473 : void
474 7207371 : xfs_fsop_geom_health(
475 : struct xfs_mount *mp,
476 : struct xfs_fsop_geom *geo)
477 : {
478 7207371 : const struct ioctl_sick_map *m;
479 7207371 : unsigned int sick;
480 7207371 : unsigned int checked;
481 :
482 7207371 : geo->sick = 0;
483 7207371 : geo->checked = 0;
484 :
485 7207371 : xfs_fs_measure_sickness(mp, &sick, &checked);
486 64905822 : for (m = fs_map; m->sick_mask; m++)
487 50459591 : xfgeo_health_tick(geo, sick, checked, m);
488 :
489 7218928 : xfs_rt_measure_sickness(mp, &sick, &checked);
490 28891450 : for (m = rt_map; m->sick_mask; m++)
491 14446857 : xfgeo_health_tick(geo, sick, checked, m);
492 7217290 : }
493 :
494 : static const struct ioctl_sick_map ag_map[] = {
495 : { XFS_SICK_AG_SB, XFS_AG_GEOM_SICK_SB },
496 : { XFS_SICK_AG_AGF, XFS_AG_GEOM_SICK_AGF },
497 : { XFS_SICK_AG_AGFL, XFS_AG_GEOM_SICK_AGFL },
498 : { XFS_SICK_AG_AGI, XFS_AG_GEOM_SICK_AGI },
499 : { XFS_SICK_AG_BNOBT, XFS_AG_GEOM_SICK_BNOBT },
500 : { XFS_SICK_AG_CNTBT, XFS_AG_GEOM_SICK_CNTBT },
501 : { XFS_SICK_AG_INOBT, XFS_AG_GEOM_SICK_INOBT },
502 : { XFS_SICK_AG_FINOBT, XFS_AG_GEOM_SICK_FINOBT },
503 : { XFS_SICK_AG_RMAPBT, XFS_AG_GEOM_SICK_RMAPBT },
504 : { XFS_SICK_AG_REFCNTBT, XFS_AG_GEOM_SICK_REFCNTBT },
505 : { XFS_SICK_AG_INODES, XFS_AG_GEOM_SICK_INODES },
506 : { 0, 0 },
507 : };
508 :
509 : /* Fill out ag geometry health info. */
510 : void
511 89454 : xfs_ag_geom_health(
512 : struct xfs_perag *pag,
513 : struct xfs_ag_geometry *ageo)
514 : {
515 89454 : const struct ioctl_sick_map *m;
516 89454 : unsigned int sick;
517 89454 : unsigned int checked;
518 :
519 89454 : ageo->ag_sick = 0;
520 89454 : ageo->ag_checked = 0;
521 :
522 89454 : xfs_ag_measure_sickness(pag, &sick, &checked);
523 1162902 : for (m = ag_map; m->sick_mask; m++) {
524 983994 : if (checked & m->sick_mask)
525 974833 : ageo->ag_checked |= m->ioctl_mask;
526 983994 : if (sick & m->sick_mask)
527 12 : ageo->ag_sick |= m->ioctl_mask;
528 : }
529 89454 : }
530 :
531 : static const struct ioctl_sick_map rtgroup_map[] = {
532 : { XFS_SICK_RT_SUPER, XFS_RTGROUP_GEOM_SICK_SUPER },
533 : { XFS_SICK_RT_BITMAP, XFS_RTGROUP_GEOM_SICK_BITMAP },
534 : { XFS_SICK_RT_RMAPBT, XFS_RTGROUP_GEOM_SICK_RMAPBT },
535 : { XFS_SICK_RT_REFCNTBT, XFS_RTGROUP_GEOM_SICK_REFCNTBT },
536 : { 0, 0 },
537 : };
538 :
539 : /* Fill out rtgroup geometry health info. */
540 : void
541 19471 : xfs_rtgroup_geom_health(
542 : struct xfs_rtgroup *rtg,
543 : struct xfs_rtgroup_geometry *rgeo)
544 : {
545 19471 : const struct ioctl_sick_map *m;
546 19471 : unsigned int sick;
547 19471 : unsigned int checked;
548 :
549 19471 : rgeo->rg_sick = 0;
550 19471 : rgeo->rg_checked = 0;
551 :
552 19471 : xfs_rtgroup_measure_sickness(rtg, &sick, &checked);
553 116826 : for (m = rtgroup_map; m->sick_mask; m++) {
554 77884 : if (checked & m->sick_mask)
555 58183 : rgeo->rg_checked |= m->ioctl_mask;
556 77884 : if (sick & m->sick_mask)
557 0 : rgeo->rg_sick |= m->ioctl_mask;
558 : }
559 19471 : }
560 :
561 : static const struct ioctl_sick_map ino_map[] = {
562 : { XFS_SICK_INO_CORE, XFS_BS_SICK_INODE },
563 : { XFS_SICK_INO_BMBTD, XFS_BS_SICK_BMBTD },
564 : { XFS_SICK_INO_BMBTA, XFS_BS_SICK_BMBTA },
565 : { XFS_SICK_INO_BMBTC, XFS_BS_SICK_BMBTC },
566 : { XFS_SICK_INO_DIR, XFS_BS_SICK_DIR },
567 : { XFS_SICK_INO_XATTR, XFS_BS_SICK_XATTR },
568 : { XFS_SICK_INO_SYMLINK, XFS_BS_SICK_SYMLINK },
569 : { XFS_SICK_INO_PARENT, XFS_BS_SICK_PARENT },
570 : { XFS_SICK_INO_DIRTREE, XFS_BS_SICK_DIRTREE },
571 : { 0, 0 },
572 : };
573 :
574 : /* Fill out bulkstat health info. */
575 : void
576 81727966102 : xfs_bulkstat_health(
577 : struct xfs_inode *ip,
578 : struct xfs_bulkstat *bs)
579 : {
580 81727966102 : const struct ioctl_sick_map *m;
581 81727966102 : unsigned int sick;
582 81727966102 : unsigned int checked;
583 :
584 81727966102 : bs->bs_sick = 0;
585 81727966102 : bs->bs_checked = 0;
586 :
587 81727966102 : xfs_inode_measure_sickness(ip, &sick, &checked);
588 >90213*10^7 : for (m = ino_map; m->sick_mask; m++) {
589 >73685*10^7 : if (checked & m->sick_mask)
590 15843569007 : bs->bs_checked |= m->ioctl_mask;
591 >73685*10^7 : if (sick & m->sick_mask)
592 66 : bs->bs_sick |= m->ioctl_mask;
593 : }
594 82786551135 : }
595 :
596 : /* Mark a block mapping sick. */
597 : void
598 20 : xfs_bmap_mark_sick(
599 : struct xfs_inode *ip,
600 : int whichfork)
601 : {
602 20 : unsigned int mask;
603 :
604 20 : switch (whichfork) {
605 : case XFS_DATA_FORK:
606 : mask = XFS_SICK_INO_BMBTD;
607 : break;
608 : case XFS_ATTR_FORK:
609 : mask = XFS_SICK_INO_BMBTA;
610 : break;
611 : case XFS_COW_FORK:
612 : mask = XFS_SICK_INO_BMBTC;
613 : break;
614 0 : default:
615 0 : ASSERT(0);
616 0 : return;
617 : }
618 :
619 20 : xfs_inode_mark_sick(ip, mask);
620 : }
621 :
622 : /* Record observations of btree corruption with the health tracking system. */
623 : void
624 1363 : xfs_btree_mark_sick(
625 : struct xfs_btree_cur *cur)
626 : {
627 1363 : unsigned int mask;
628 :
629 1363 : if (cur->bc_flags & XFS_BTREE_IN_XFILE)
630 : return;
631 :
632 1363 : switch (cur->bc_btnum) {
633 10 : case XFS_BTNUM_BMAP:
634 10 : xfs_bmap_mark_sick(cur->bc_ino.ip, cur->bc_ino.whichfork);
635 10 : return;
636 2 : case XFS_BTNUM_RTRMAP:
637 2 : xfs_rtgroup_mark_sick(cur->bc_ino.rtg, XFS_SICK_RT_RMAPBT);
638 2 : return;
639 0 : case XFS_BTNUM_RTREFC:
640 0 : xfs_rtgroup_mark_sick(cur->bc_ino.rtg, XFS_SICK_RT_REFCNTBT);
641 0 : return;
642 : case XFS_BTNUM_BNO:
643 : mask = XFS_SICK_AG_BNOBT;
644 : break;
645 640 : case XFS_BTNUM_CNT:
646 640 : mask = XFS_SICK_AG_CNTBT;
647 640 : break;
648 11 : case XFS_BTNUM_INO:
649 11 : mask = XFS_SICK_AG_INOBT;
650 11 : break;
651 10 : case XFS_BTNUM_FINO:
652 10 : mask = XFS_SICK_AG_FINOBT;
653 10 : break;
654 20 : case XFS_BTNUM_RMAP:
655 20 : mask = XFS_SICK_AG_RMAPBT;
656 20 : break;
657 30 : case XFS_BTNUM_REFC:
658 30 : mask = XFS_SICK_AG_REFCNTBT;
659 30 : break;
660 0 : default:
661 0 : ASSERT(0);
662 0 : return;
663 : }
664 :
665 1351 : xfs_ag_mark_sick(cur->bc_ag.pag, mask);
666 : }
667 :
668 : /*
669 : * Record observations of dir/attr btree corruption with the health tracking
670 : * system.
671 : */
672 : void
673 271 : xfs_dirattr_mark_sick(
674 : struct xfs_inode *ip,
675 : int whichfork)
676 : {
677 271 : unsigned int mask;
678 :
679 271 : switch (whichfork) {
680 : case XFS_DATA_FORK:
681 : mask = XFS_SICK_INO_DIR;
682 : break;
683 51 : case XFS_ATTR_FORK:
684 51 : mask = XFS_SICK_INO_XATTR;
685 51 : break;
686 0 : default:
687 0 : ASSERT(0);
688 0 : return;
689 : }
690 :
691 271 : xfs_inode_mark_sick(ip, mask);
692 : }
693 :
694 : /*
695 : * Record observations of dir/attr btree corruption with the health tracking
696 : * system.
697 : */
698 : void
699 0 : xfs_da_mark_sick(
700 : struct xfs_da_args *args)
701 : {
702 0 : xfs_dirattr_mark_sick(args->dp, args->whichfork);
703 0 : }
|