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 24331 : xfs_health_unmount(
30 : struct xfs_mount *mp)
31 : {
32 24331 : struct xfs_perag *pag;
33 24331 : struct xfs_rtgroup *rtg;
34 24331 : xfs_agnumber_t agno;
35 24331 : xfs_rgnumber_t rgno;
36 24331 : unsigned int sick = 0;
37 24331 : unsigned int checked = 0;
38 24331 : bool warn = false;
39 :
40 48662 : if (xfs_is_shutdown(mp))
41 11870 : return;
42 :
43 : /* Measure AG corruption levels. */
44 99279 : for_each_perag(mp, agno, pag) {
45 86818 : xfs_ag_measure_sickness(pag, &sick, &checked);
46 86818 : if (sick) {
47 24 : trace_xfs_ag_unfixed_corruption(mp, agno, sick);
48 24 : warn = true;
49 : }
50 : }
51 :
52 : /* Measure realtime group corruption levels. */
53 13692 : for_each_rtgroup(mp, rgno, rtg) {
54 1231 : xfs_rtgroup_measure_sickness(rtg, &sick, &checked);
55 1231 : 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 12461 : xfs_rt_measure_sickness(mp, &sick, &checked);
63 12461 : 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 12461 : xfs_fs_measure_sickness(mp, &sick, &checked);
73 12461 : if (sick & ~XFS_SICK_FS_COUNTERS) {
74 5 : trace_xfs_fs_unfixed_corruption(mp, sick);
75 5 : warn = true;
76 : }
77 :
78 12461 : if (warn) {
79 25 : 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 25 : 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 434593 : xfs_fs_mark_sick(
109 : struct xfs_mount *mp,
110 : unsigned int mask)
111 : {
112 434593 : ASSERT(!(mask & ~XFS_SICK_FS_ALL));
113 434593 : trace_xfs_fs_mark_sick(mp, mask);
114 :
115 434598 : spin_lock(&mp->m_sb_lock);
116 434598 : mp->m_fs_sick |= mask;
117 434598 : spin_unlock(&mp->m_sb_lock);
118 434596 : }
119 :
120 : /* Mark per-fs metadata as having been checked. */
121 : void
122 434585 : xfs_fs_mark_checked(
123 : struct xfs_mount *mp,
124 : unsigned int mask)
125 : {
126 434585 : ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
127 :
128 434585 : spin_lock(&mp->m_sb_lock);
129 434586 : mp->m_fs_checked |= mask;
130 434586 : spin_unlock(&mp->m_sb_lock);
131 434586 : }
132 :
133 : /* Mark a per-fs metadata healed. */
134 : void
135 268392 : xfs_fs_mark_healthy(
136 : struct xfs_mount *mp,
137 : unsigned int mask)
138 : {
139 268392 : ASSERT(!(mask & ~XFS_SICK_FS_ALL));
140 268392 : trace_xfs_fs_mark_healthy(mp, mask);
141 :
142 268392 : spin_lock(&mp->m_sb_lock);
143 268392 : mp->m_fs_sick &= ~mask;
144 268392 : if (!(mp->m_fs_sick & XFS_SICK_FS_PRIMARY))
145 : mp->m_fs_sick &= ~XFS_SICK_FS_SECONDARY;
146 268392 : mp->m_fs_checked |= mask;
147 268392 : spin_unlock(&mp->m_sb_lock);
148 268392 : }
149 :
150 : /* Sample which per-fs metadata are unhealthy. */
151 : void
152 38982 : xfs_fs_measure_sickness(
153 : struct xfs_mount *mp,
154 : unsigned int *sick,
155 : unsigned int *checked)
156 : {
157 51443 : spin_lock(&mp->m_sb_lock);
158 2111504 : *sick = mp->m_fs_sick;
159 2111504 : *checked = mp->m_fs_checked;
160 2111504 : spin_unlock(&mp->m_sb_lock);
161 38982 : }
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 106308 : xfs_rt_mark_healthy(
194 : struct xfs_mount *mp,
195 : unsigned int mask)
196 : {
197 106308 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
198 106308 : trace_xfs_rt_mark_healthy(mp, mask);
199 :
200 106308 : spin_lock(&mp->m_sb_lock);
201 106308 : mp->m_rt_sick &= ~mask;
202 106308 : if (!(mp->m_rt_sick & XFS_SICK_RT_PRIMARY))
203 : mp->m_rt_sick &= ~XFS_SICK_RT_SECONDARY;
204 106308 : mp->m_rt_checked |= mask;
205 106308 : spin_unlock(&mp->m_sb_lock);
206 106308 : }
207 :
208 : /* Sample which realtime metadata are unhealthy. */
209 : void
210 11155 : xfs_rt_measure_sickness(
211 : struct xfs_mount *mp,
212 : unsigned int *sick,
213 : unsigned int *checked)
214 : {
215 23616 : spin_lock(&mp->m_sb_lock);
216 2083677 : *sick = mp->m_rt_sick;
217 2083677 : *checked = mp->m_rt_checked;
218 2083677 : spin_unlock(&mp->m_sb_lock);
219 11155 : }
220 :
221 : /* Mark unhealthy per-ag metadata given a raw AG number. */
222 : void
223 400 : xfs_agno_mark_sick(
224 : struct xfs_mount *mp,
225 : xfs_agnumber_t agno,
226 : unsigned int mask)
227 : {
228 400 : struct xfs_perag *pag = xfs_perag_get(mp, agno);
229 :
230 : /* per-ag structure not set up yet? */
231 400 : if (!pag)
232 : return;
233 :
234 400 : xfs_ag_mark_sick(pag, mask);
235 400 : xfs_perag_put(pag);
236 : }
237 :
238 : /* Mark unhealthy per-ag metadata. */
239 : void
240 1806 : xfs_ag_mark_sick(
241 : struct xfs_perag *pag,
242 : unsigned int mask)
243 : {
244 1806 : ASSERT(!(mask & ~XFS_SICK_AG_ALL));
245 1806 : trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask);
246 :
247 1806 : spin_lock(&pag->pag_state_lock);
248 1806 : pag->pag_sick |= mask;
249 1806 : spin_unlock(&pag->pag_state_lock);
250 1806 : }
251 :
252 : /* Mark per-ag metadata as having been checked. */
253 : void
254 18 : xfs_ag_mark_checked(
255 : struct xfs_perag *pag,
256 : unsigned int mask)
257 : {
258 18 : ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
259 :
260 18 : spin_lock(&pag->pag_state_lock);
261 18 : pag->pag_checked |= mask;
262 18 : spin_unlock(&pag->pag_state_lock);
263 18 : }
264 :
265 : /* Mark per-ag metadata ok. */
266 : void
267 2979032 : xfs_ag_mark_healthy(
268 : struct xfs_perag *pag,
269 : unsigned int mask)
270 : {
271 2979032 : ASSERT(!(mask & ~XFS_SICK_AG_ALL));
272 2979032 : trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask);
273 :
274 2979035 : spin_lock(&pag->pag_state_lock);
275 2979035 : pag->pag_sick &= ~mask;
276 2979035 : if (!(pag->pag_sick & XFS_SICK_AG_PRIMARY))
277 : pag->pag_sick &= ~XFS_SICK_AG_SECONDARY;
278 2979035 : pag->pag_checked |= mask;
279 2979035 : spin_unlock(&pag->pag_state_lock);
280 2979035 : }
281 :
282 : /* Sample which per-ag metadata are unhealthy. */
283 : void
284 3585586215 : xfs_ag_measure_sickness(
285 : struct xfs_perag *pag,
286 : unsigned int *sick,
287 : unsigned int *checked)
288 : {
289 3585673033 : spin_lock(&pag->pag_state_lock);
290 3585853152 : *sick = pag->pag_sick;
291 3585853152 : *checked = pag->pag_checked;
292 3585853152 : spin_unlock(&pag->pag_state_lock);
293 3585683853 : }
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 0 : xfs_rtgroup_mark_sick(
315 : struct xfs_rtgroup *rtg,
316 : unsigned int mask)
317 : {
318 0 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
319 0 : trace_xfs_rtgroup_mark_sick(rtg, mask);
320 :
321 0 : spin_lock(&rtg->rtg_state_lock);
322 0 : rtg->rtg_sick |= mask;
323 0 : spin_unlock(&rtg->rtg_state_lock);
324 0 : }
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 156449 : xfs_rtgroup_mark_healthy(
342 : struct xfs_rtgroup *rtg,
343 : unsigned int mask)
344 : {
345 156449 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
346 156449 : trace_xfs_rtgroup_mark_healthy(rtg, mask);
347 :
348 156449 : spin_lock(&rtg->rtg_state_lock);
349 156449 : rtg->rtg_sick &= ~mask;
350 156449 : if (!(rtg->rtg_sick & XFS_SICK_RT_PRIMARY))
351 : rtg->rtg_sick &= ~XFS_SICK_RT_SECONDARY;
352 156449 : rtg->rtg_checked |= mask;
353 156449 : spin_unlock(&rtg->rtg_state_lock);
354 156449 : }
355 :
356 : /* Sample which per-rtgroup metadata are unhealthy. */
357 : void
358 18846 : xfs_rtgroup_measure_sickness(
359 : struct xfs_rtgroup *rtg,
360 : unsigned int *sick,
361 : unsigned int *checked)
362 : {
363 20077 : spin_lock(&rtg->rtg_state_lock);
364 20473 : *sick = rtg->rtg_sick;
365 20473 : *checked = rtg->rtg_checked;
366 20473 : spin_unlock(&rtg->rtg_state_lock);
367 18846 : }
368 :
369 : /* Mark the unhealthy parts of an inode. */
370 : void
371 466 : xfs_inode_mark_sick(
372 : struct xfs_inode *ip,
373 : unsigned int mask)
374 : {
375 466 : ASSERT(!(mask & ~XFS_SICK_INO_ALL));
376 466 : trace_xfs_inode_mark_sick(ip, mask);
377 :
378 466 : spin_lock(&ip->i_flags_lock);
379 466 : ip->i_sick |= mask;
380 466 : 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 466 : spin_lock(&VFS_I(ip)->i_lock);
388 466 : VFS_I(ip)->i_state &= ~I_DONTCACHE;
389 466 : spin_unlock(&VFS_I(ip)->i_lock);
390 466 : }
391 :
392 : /* Mark inode metadata as having been checked. */
393 : void
394 6 : xfs_inode_mark_checked(
395 : struct xfs_inode *ip,
396 : unsigned int mask)
397 : {
398 6 : ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
399 :
400 6 : spin_lock(&ip->i_flags_lock);
401 6 : ip->i_checked |= mask;
402 6 : spin_unlock(&ip->i_flags_lock);
403 6 : }
404 :
405 : /* Mark parts of an inode healed. */
406 : void
407 426692560 : xfs_inode_mark_healthy(
408 : struct xfs_inode *ip,
409 : unsigned int mask)
410 : {
411 426692560 : ASSERT(!(mask & ~XFS_SICK_INO_ALL));
412 426692560 : trace_xfs_inode_mark_healthy(ip, mask);
413 :
414 426709145 : spin_lock(&ip->i_flags_lock);
415 426893490 : ip->i_sick &= ~mask;
416 426893490 : if (!(ip->i_sick & XFS_SICK_INO_PRIMARY))
417 426887874 : ip->i_sick &= ~XFS_SICK_INO_SECONDARY;
418 426893490 : ip->i_checked |= mask;
419 426893490 : spin_unlock(&ip->i_flags_lock);
420 426718577 : }
421 :
422 : /* Sample which parts of an inode are unhealthy. */
423 : void
424 38270954 : xfs_inode_measure_sickness(
425 : struct xfs_inode *ip,
426 : unsigned int *sick,
427 : unsigned int *checked)
428 : {
429 38270954 : spin_lock(&ip->i_flags_lock);
430 69104030375 : *sick = ip->i_sick;
431 69104030375 : *checked = ip->i_checked;
432 69104030375 : spin_unlock(&ip->i_flags_lock);
433 38265744 : }
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 18528482 : 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 18528482 : if (checked & m->sick_mask)
467 1906629 : geo->checked |= m->ioctl_mask;
468 18528482 : if (sick & m->sick_mask)
469 108656 : geo->sick |= m->ioctl_mask;
470 18528482 : }
471 :
472 : /* Fill out fs geometry health info. */
473 : void
474 2058940 : xfs_fsop_geom_health(
475 : struct xfs_mount *mp,
476 : struct xfs_fsop_geom *geo)
477 : {
478 2058940 : const struct ioctl_sick_map *m;
479 2058940 : unsigned int sick;
480 2058940 : unsigned int checked;
481 :
482 2058940 : geo->sick = 0;
483 2058940 : geo->checked = 0;
484 :
485 2058940 : xfs_fs_measure_sickness(mp, &sick, &checked);
486 18520322 : for (m = fs_map; m->sick_mask; m++)
487 14401285 : xfgeo_health_tick(geo, sick, checked, m);
488 :
489 2058976 : xfs_rt_measure_sickness(mp, &sick, &checked);
490 8239298 : for (m = rt_map; m->sick_mask; m++)
491 4119199 : xfgeo_health_tick(geo, sick, checked, m);
492 2060038 : }
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 15595 : xfs_ag_geom_health(
512 : struct xfs_perag *pag,
513 : struct xfs_ag_geometry *ageo)
514 : {
515 15595 : const struct ioctl_sick_map *m;
516 15595 : unsigned int sick;
517 15595 : unsigned int checked;
518 :
519 15595 : ageo->ag_sick = 0;
520 15595 : ageo->ag_checked = 0;
521 :
522 15595 : xfs_ag_measure_sickness(pag, &sick, &checked);
523 202735 : for (m = ag_map; m->sick_mask; m++) {
524 171545 : if (checked & m->sick_mask)
525 171239 : ageo->ag_checked |= m->ioctl_mask;
526 171545 : if (sick & m->sick_mask)
527 2 : ageo->ag_sick |= m->ioctl_mask;
528 : }
529 15595 : }
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 396 : xfs_rtgroup_geom_health(
542 : struct xfs_rtgroup *rtg,
543 : struct xfs_rtgroup_geometry *rgeo)
544 : {
545 396 : const struct ioctl_sick_map *m;
546 396 : unsigned int sick;
547 396 : unsigned int checked;
548 :
549 396 : rgeo->rg_sick = 0;
550 396 : rgeo->rg_checked = 0;
551 :
552 396 : xfs_rtgroup_measure_sickness(rtg, &sick, &checked);
553 2376 : for (m = rtgroup_map; m->sick_mask; m++) {
554 1584 : if (checked & m->sick_mask)
555 1188 : rgeo->rg_checked |= m->ioctl_mask;
556 1584 : if (sick & m->sick_mask)
557 0 : rgeo->rg_sick |= m->ioctl_mask;
558 : }
559 396 : }
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 68927562983 : xfs_bulkstat_health(
577 : struct xfs_inode *ip,
578 : struct xfs_bulkstat *bs)
579 : {
580 68927562983 : const struct ioctl_sick_map *m;
581 68927562983 : unsigned int sick;
582 68927562983 : unsigned int checked;
583 :
584 68927562983 : bs->bs_sick = 0;
585 68927562983 : bs->bs_checked = 0;
586 :
587 68927562983 : xfs_inode_measure_sickness(ip, &sick, &checked);
588 >75391*10^7 : for (m = ino_map; m->sick_mask; m++) {
589 >61578*10^7 : if (checked & m->sick_mask)
590 13959227006 : bs->bs_checked |= m->ioctl_mask;
591 >61578*10^7 : if (sick & m->sick_mask)
592 12 : bs->bs_sick |= m->ioctl_mask;
593 : }
594 69069840086 : }
595 :
596 : /* Mark a block mapping sick. */
597 : void
598 4 : xfs_bmap_mark_sick(
599 : struct xfs_inode *ip,
600 : int whichfork)
601 : {
602 4 : unsigned int mask;
603 :
604 4 : 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 4 : xfs_inode_mark_sick(ip, mask);
620 : }
621 :
622 : /* Record observations of btree corruption with the health tracking system. */
623 : void
624 274 : xfs_btree_mark_sick(
625 : struct xfs_btree_cur *cur)
626 : {
627 274 : unsigned int mask;
628 :
629 274 : if (cur->bc_flags & XFS_BTREE_IN_XFILE)
630 : return;
631 :
632 274 : switch (cur->bc_btnum) {
633 2 : case XFS_BTNUM_BMAP:
634 2 : xfs_bmap_mark_sick(cur->bc_ino.ip, cur->bc_ino.whichfork);
635 2 : return;
636 0 : case XFS_BTNUM_RTRMAP:
637 0 : xfs_rtgroup_mark_sick(cur->bc_ino.rtg, XFS_SICK_RT_RMAPBT);
638 0 : 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 128 : case XFS_BTNUM_CNT:
646 128 : mask = XFS_SICK_AG_CNTBT;
647 128 : break;
648 2 : case XFS_BTNUM_INO:
649 2 : mask = XFS_SICK_AG_INOBT;
650 2 : break;
651 2 : case XFS_BTNUM_FINO:
652 2 : mask = XFS_SICK_AG_FINOBT;
653 2 : break;
654 4 : case XFS_BTNUM_RMAP:
655 4 : mask = XFS_SICK_AG_RMAPBT;
656 4 : break;
657 8 : case XFS_BTNUM_REFC:
658 8 : mask = XFS_SICK_AG_REFCNTBT;
659 8 : break;
660 0 : default:
661 0 : ASSERT(0);
662 0 : return;
663 : }
664 :
665 272 : 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 252 : xfs_dirattr_mark_sick(
674 : struct xfs_inode *ip,
675 : int whichfork)
676 : {
677 252 : unsigned int mask;
678 :
679 252 : switch (whichfork) {
680 : case XFS_DATA_FORK:
681 : mask = XFS_SICK_INO_DIR;
682 : break;
683 210 : case XFS_ATTR_FORK:
684 210 : mask = XFS_SICK_INO_XATTR;
685 210 : break;
686 0 : default:
687 0 : ASSERT(0);
688 0 : return;
689 : }
690 :
691 252 : 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 : }
|