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 :
22 : /*
23 : * Warn about metadata corruption that we detected but haven't fixed, and
24 : * make sure we're not sitting on anything that would get in the way of
25 : * recovery.
26 : */
27 : void
28 60712 : xfs_health_unmount(
29 : struct xfs_mount *mp)
30 : {
31 60712 : struct xfs_perag *pag;
32 60712 : xfs_agnumber_t agno;
33 60712 : unsigned int sick = 0;
34 60712 : unsigned int checked = 0;
35 60712 : bool warn = false;
36 :
37 121424 : if (xfs_is_shutdown(mp))
38 13174 : return;
39 :
40 : /* Measure AG corruption levels. */
41 445146 : for_each_perag(mp, agno, pag) {
42 397608 : xfs_ag_measure_sickness(pag, &sick, &checked);
43 397608 : if (sick) {
44 115 : trace_xfs_ag_unfixed_corruption(mp, agno, sick);
45 115 : warn = true;
46 : }
47 : }
48 :
49 : /* Measure realtime volume corruption levels. */
50 47538 : xfs_rt_measure_sickness(mp, &sick, &checked);
51 47538 : if (sick) {
52 0 : trace_xfs_rt_unfixed_corruption(mp, sick);
53 0 : warn = true;
54 : }
55 :
56 : /*
57 : * Measure fs corruption and keep the sample around for the warning.
58 : * See the note below for why we exempt FS_COUNTERS.
59 : */
60 47538 : xfs_fs_measure_sickness(mp, &sick, &checked);
61 47538 : if (sick & ~XFS_SICK_FS_COUNTERS) {
62 1 : trace_xfs_fs_unfixed_corruption(mp, sick);
63 1 : warn = true;
64 : }
65 :
66 47538 : if (warn) {
67 116 : xfs_warn(mp,
68 : "Uncorrected metadata errors detected; please run xfs_repair.");
69 :
70 : /*
71 : * We discovered uncorrected metadata problems at some point
72 : * during this filesystem mount and have advised the
73 : * administrator to run repair once the unmount completes.
74 : *
75 : * However, we must be careful -- when FSCOUNTERS are flagged
76 : * unhealthy, the unmount procedure omits writing the clean
77 : * unmount record to the log so that the next mount will run
78 : * recovery and recompute the summary counters. In other
79 : * words, we leave a dirty log to get the counters fixed.
80 : *
81 : * Unfortunately, xfs_repair cannot recover dirty logs, so if
82 : * there were filesystem problems, FSCOUNTERS was flagged, and
83 : * the administrator takes our advice to run xfs_repair,
84 : * they'll have to zap the log before repairing structures.
85 : * We don't really want to encourage this, so we mark the
86 : * FSCOUNTERS healthy so that a subsequent repair run won't see
87 : * a dirty log.
88 : */
89 116 : if (sick & XFS_SICK_FS_COUNTERS)
90 0 : xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS);
91 : }
92 : }
93 :
94 : /* Mark unhealthy per-fs metadata. */
95 : void
96 353729 : xfs_fs_mark_sick(
97 : struct xfs_mount *mp,
98 : unsigned int mask)
99 : {
100 353729 : ASSERT(!(mask & ~XFS_SICK_FS_ALL));
101 353729 : trace_xfs_fs_mark_sick(mp, mask);
102 :
103 353683 : spin_lock(&mp->m_sb_lock);
104 353775 : mp->m_fs_sick |= mask;
105 353775 : spin_unlock(&mp->m_sb_lock);
106 353773 : }
107 :
108 : /* Mark per-fs metadata as having been checked. */
109 : void
110 353757 : xfs_fs_mark_checked(
111 : struct xfs_mount *mp,
112 : unsigned int mask)
113 : {
114 353757 : ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
115 :
116 353757 : spin_lock(&mp->m_sb_lock);
117 353758 : mp->m_fs_checked |= mask;
118 353758 : spin_unlock(&mp->m_sb_lock);
119 353754 : }
120 :
121 : /* Mark a per-fs metadata healed. */
122 : void
123 300165 : xfs_fs_mark_healthy(
124 : struct xfs_mount *mp,
125 : unsigned int mask)
126 : {
127 300165 : ASSERT(!(mask & ~XFS_SICK_FS_ALL));
128 300165 : trace_xfs_fs_mark_healthy(mp, mask);
129 :
130 300163 : spin_lock(&mp->m_sb_lock);
131 300171 : mp->m_fs_sick &= ~mask;
132 300171 : if (!(mp->m_fs_sick & XFS_SICK_FS_PRIMARY))
133 : mp->m_fs_sick &= ~XFS_SICK_FS_SECONDARY;
134 300171 : mp->m_fs_checked |= mask;
135 300171 : spin_unlock(&mp->m_sb_lock);
136 300171 : }
137 :
138 : /* Sample which per-fs metadata are unhealthy. */
139 : void
140 122634 : xfs_fs_measure_sickness(
141 : struct xfs_mount *mp,
142 : unsigned int *sick,
143 : unsigned int *checked)
144 : {
145 170172 : spin_lock(&mp->m_sb_lock);
146 5836794 : *sick = mp->m_fs_sick;
147 5836794 : *checked = mp->m_fs_checked;
148 5836794 : spin_unlock(&mp->m_sb_lock);
149 122634 : }
150 :
151 : /* Mark unhealthy realtime metadata. */
152 : void
153 0 : xfs_rt_mark_sick(
154 : struct xfs_mount *mp,
155 : unsigned int mask)
156 : {
157 0 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
158 0 : trace_xfs_rt_mark_sick(mp, mask);
159 :
160 0 : spin_lock(&mp->m_sb_lock);
161 0 : mp->m_rt_sick |= mask;
162 0 : spin_unlock(&mp->m_sb_lock);
163 0 : }
164 :
165 : /* Mark realtime metadata as having been checked. */
166 : void
167 0 : xfs_rt_mark_checked(
168 : struct xfs_mount *mp,
169 : unsigned int mask)
170 : {
171 0 : ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
172 0 : trace_xfs_rt_mark_sick(mp, mask);
173 :
174 0 : spin_lock(&mp->m_sb_lock);
175 0 : mp->m_rt_checked |= mask;
176 0 : spin_unlock(&mp->m_sb_lock);
177 0 : }
178 :
179 : /* Mark a realtime metadata healed. */
180 : void
181 103825 : xfs_rt_mark_healthy(
182 : struct xfs_mount *mp,
183 : unsigned int mask)
184 : {
185 103825 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
186 103825 : trace_xfs_rt_mark_healthy(mp, mask);
187 :
188 103825 : spin_lock(&mp->m_sb_lock);
189 103825 : mp->m_rt_sick &= ~mask;
190 103825 : if (!(mp->m_rt_sick & XFS_SICK_RT_PRIMARY))
191 : mp->m_rt_sick &= ~XFS_SICK_RT_SECONDARY;
192 103825 : mp->m_rt_checked |= mask;
193 103825 : spin_unlock(&mp->m_sb_lock);
194 103825 : }
195 :
196 : /* Sample which realtime metadata are unhealthy. */
197 : void
198 25693 : xfs_rt_measure_sickness(
199 : struct xfs_mount *mp,
200 : unsigned int *sick,
201 : unsigned int *checked)
202 : {
203 73231 : spin_lock(&mp->m_sb_lock);
204 5739853 : *sick = mp->m_rt_sick;
205 5739853 : *checked = mp->m_rt_checked;
206 5739853 : spin_unlock(&mp->m_sb_lock);
207 25693 : }
208 :
209 : /* Mark unhealthy per-ag metadata given a raw AG number. */
210 : void
211 2017 : xfs_agno_mark_sick(
212 : struct xfs_mount *mp,
213 : xfs_agnumber_t agno,
214 : unsigned int mask)
215 : {
216 2017 : struct xfs_perag *pag = xfs_perag_get(mp, agno);
217 :
218 : /* per-ag structure not set up yet? */
219 2017 : if (!pag)
220 : return;
221 :
222 2017 : xfs_ag_mark_sick(pag, mask);
223 2017 : xfs_perag_put(pag);
224 : }
225 :
226 : /* Mark unhealthy per-ag metadata. */
227 : void
228 5723 : xfs_ag_mark_sick(
229 : struct xfs_perag *pag,
230 : unsigned int mask)
231 : {
232 5723 : ASSERT(!(mask & ~XFS_SICK_AG_ALL));
233 5723 : trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask);
234 :
235 5723 : spin_lock(&pag->pag_state_lock);
236 5724 : pag->pag_sick |= mask;
237 5724 : spin_unlock(&pag->pag_state_lock);
238 5724 : }
239 :
240 : /* Mark per-ag metadata as having been checked. */
241 : void
242 99 : xfs_ag_mark_checked(
243 : struct xfs_perag *pag,
244 : unsigned int mask)
245 : {
246 99 : ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
247 :
248 99 : spin_lock(&pag->pag_state_lock);
249 99 : pag->pag_checked |= mask;
250 99 : spin_unlock(&pag->pag_state_lock);
251 99 : }
252 :
253 : /* Mark per-ag metadata ok. */
254 : void
255 4604895 : xfs_ag_mark_healthy(
256 : struct xfs_perag *pag,
257 : unsigned int mask)
258 : {
259 4604895 : ASSERT(!(mask & ~XFS_SICK_AG_ALL));
260 4604895 : trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask);
261 :
262 4603484 : spin_lock(&pag->pag_state_lock);
263 4605363 : pag->pag_sick &= ~mask;
264 4605363 : if (!(pag->pag_sick & XFS_SICK_AG_PRIMARY))
265 : pag->pag_sick &= ~XFS_SICK_AG_SECONDARY;
266 4605363 : pag->pag_checked |= mask;
267 4605363 : spin_unlock(&pag->pag_state_lock);
268 4605415 : }
269 :
270 : /* Sample which per-ag metadata are unhealthy. */
271 : void
272 2559329689 : xfs_ag_measure_sickness(
273 : struct xfs_perag *pag,
274 : unsigned int *sick,
275 : unsigned int *checked)
276 : {
277 2559727297 : spin_lock(&pag->pag_state_lock);
278 2561704104 : *sick = pag->pag_sick;
279 2561704104 : *checked = pag->pag_checked;
280 2561704104 : spin_unlock(&pag->pag_state_lock);
281 2561889105 : }
282 :
283 : /* Mark the unhealthy parts of an inode. */
284 : void
285 1428 : xfs_inode_mark_sick(
286 : struct xfs_inode *ip,
287 : unsigned int mask)
288 : {
289 1428 : ASSERT(!(mask & ~XFS_SICK_INO_ALL));
290 1428 : trace_xfs_inode_mark_sick(ip, mask);
291 :
292 1428 : spin_lock(&ip->i_flags_lock);
293 1428 : ip->i_sick |= mask;
294 1428 : spin_unlock(&ip->i_flags_lock);
295 :
296 : /*
297 : * Keep this inode around so we don't lose the sickness report. Scrub
298 : * grabs inodes with DONTCACHE assuming that most inode are ok, which
299 : * is not the case here.
300 : */
301 1428 : spin_lock(&VFS_I(ip)->i_lock);
302 1428 : VFS_I(ip)->i_state &= ~I_DONTCACHE;
303 1428 : spin_unlock(&VFS_I(ip)->i_lock);
304 1428 : }
305 :
306 : /* Mark inode metadata as having been checked. */
307 : void
308 33 : xfs_inode_mark_checked(
309 : struct xfs_inode *ip,
310 : unsigned int mask)
311 : {
312 33 : ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
313 :
314 33 : spin_lock(&ip->i_flags_lock);
315 33 : ip->i_checked |= mask;
316 33 : spin_unlock(&ip->i_flags_lock);
317 33 : }
318 :
319 : /* Mark parts of an inode healed. */
320 : void
321 918158288 : xfs_inode_mark_healthy(
322 : struct xfs_inode *ip,
323 : unsigned int mask)
324 : {
325 918158288 : ASSERT(!(mask & ~XFS_SICK_INO_ALL));
326 918158288 : trace_xfs_inode_mark_healthy(ip, mask);
327 :
328 917313906 : spin_lock(&ip->i_flags_lock);
329 920876133 : ip->i_sick &= ~mask;
330 920876133 : if (!(ip->i_sick & XFS_SICK_INO_PRIMARY))
331 921178388 : ip->i_sick &= ~XFS_SICK_INO_SECONDARY;
332 920876133 : ip->i_checked |= mask;
333 920876133 : spin_unlock(&ip->i_flags_lock);
334 921688424 : }
335 :
336 : /* Sample which parts of an inode are unhealthy. */
337 : void
338 86339373 : xfs_inode_measure_sickness(
339 : struct xfs_inode *ip,
340 : unsigned int *sick,
341 : unsigned int *checked)
342 : {
343 86339373 : spin_lock(&ip->i_flags_lock);
344 73338397449 : *sick = ip->i_sick;
345 73338397449 : *checked = ip->i_checked;
346 73338397449 : spin_unlock(&ip->i_flags_lock);
347 86499582 : }
348 :
349 : /* Mappings between internal sick masks and ioctl sick masks. */
350 :
351 : struct ioctl_sick_map {
352 : unsigned int sick_mask;
353 : unsigned int ioctl_mask;
354 : };
355 :
356 : static const struct ioctl_sick_map fs_map[] = {
357 : { XFS_SICK_FS_COUNTERS, XFS_FSOP_GEOM_SICK_COUNTERS},
358 : { XFS_SICK_FS_UQUOTA, XFS_FSOP_GEOM_SICK_UQUOTA },
359 : { XFS_SICK_FS_GQUOTA, XFS_FSOP_GEOM_SICK_GQUOTA },
360 : { XFS_SICK_FS_PQUOTA, XFS_FSOP_GEOM_SICK_PQUOTA },
361 : { XFS_SICK_FS_QUOTACHECK, XFS_FSOP_GEOM_SICK_QUOTACHECK },
362 : { XFS_SICK_FS_NLINKS, XFS_FSOP_GEOM_SICK_NLINKS },
363 : { 0, 0 },
364 : };
365 :
366 : static const struct ioctl_sick_map rt_map[] = {
367 : { XFS_SICK_RT_BITMAP, XFS_FSOP_GEOM_SICK_RT_BITMAP },
368 : { XFS_SICK_RT_SUMMARY, XFS_FSOP_GEOM_SICK_RT_SUMMARY },
369 : { 0, 0 },
370 : };
371 :
372 : static inline void
373 45159412 : xfgeo_health_tick(
374 : struct xfs_fsop_geom *geo,
375 : unsigned int sick,
376 : unsigned int checked,
377 : const struct ioctl_sick_map *m)
378 : {
379 45159412 : if (checked & m->sick_mask)
380 2680393 : geo->checked |= m->ioctl_mask;
381 45159412 : if (sick & m->sick_mask)
382 68453 : geo->sick |= m->ioctl_mask;
383 45159412 : }
384 :
385 : /* Fill out fs geometry health info. */
386 : void
387 5647267 : xfs_fsop_geom_health(
388 : struct xfs_mount *mp,
389 : struct xfs_fsop_geom *geo)
390 : {
391 5647267 : const struct ioctl_sick_map *m;
392 5647267 : unsigned int sick;
393 5647267 : unsigned int checked;
394 :
395 5647267 : geo->sick = 0;
396 5647267 : geo->checked = 0;
397 :
398 5647267 : xfs_fs_measure_sickness(mp, &sick, &checked);
399 45171035 : for (m = fs_map; m->sick_mask; m++)
400 33857917 : xfgeo_health_tick(geo, sick, checked, m);
401 :
402 5646496 : xfs_rt_measure_sickness(mp, &sick, &checked);
403 22656682 : for (m = rt_map; m->sick_mask; m++)
404 11327621 : xfgeo_health_tick(geo, sick, checked, m);
405 5662439 : }
406 :
407 : static const struct ioctl_sick_map ag_map[] = {
408 : { XFS_SICK_AG_SB, XFS_AG_GEOM_SICK_SB },
409 : { XFS_SICK_AG_AGF, XFS_AG_GEOM_SICK_AGF },
410 : { XFS_SICK_AG_AGFL, XFS_AG_GEOM_SICK_AGFL },
411 : { XFS_SICK_AG_AGI, XFS_AG_GEOM_SICK_AGI },
412 : { XFS_SICK_AG_BNOBT, XFS_AG_GEOM_SICK_BNOBT },
413 : { XFS_SICK_AG_CNTBT, XFS_AG_GEOM_SICK_CNTBT },
414 : { XFS_SICK_AG_INOBT, XFS_AG_GEOM_SICK_INOBT },
415 : { XFS_SICK_AG_FINOBT, XFS_AG_GEOM_SICK_FINOBT },
416 : { XFS_SICK_AG_RMAPBT, XFS_AG_GEOM_SICK_RMAPBT },
417 : { XFS_SICK_AG_REFCNTBT, XFS_AG_GEOM_SICK_REFCNTBT },
418 : { XFS_SICK_AG_INODES, XFS_AG_GEOM_SICK_INODES },
419 : { 0, 0 },
420 : };
421 :
422 : /* Fill out ag geometry health info. */
423 : void
424 70463 : xfs_ag_geom_health(
425 : struct xfs_perag *pag,
426 : struct xfs_ag_geometry *ageo)
427 : {
428 70463 : const struct ioctl_sick_map *m;
429 70463 : unsigned int sick;
430 70463 : unsigned int checked;
431 :
432 70463 : ageo->ag_sick = 0;
433 70463 : ageo->ag_checked = 0;
434 :
435 70463 : xfs_ag_measure_sickness(pag, &sick, &checked);
436 916019 : for (m = ag_map; m->sick_mask; m++) {
437 775093 : if (checked & m->sick_mask)
438 747274 : ageo->ag_checked |= m->ioctl_mask;
439 775093 : if (sick & m->sick_mask)
440 11 : ageo->ag_sick |= m->ioctl_mask;
441 : }
442 70463 : }
443 :
444 : static const struct ioctl_sick_map ino_map[] = {
445 : { XFS_SICK_INO_CORE, XFS_BS_SICK_INODE },
446 : { XFS_SICK_INO_BMBTD, XFS_BS_SICK_BMBTD },
447 : { XFS_SICK_INO_BMBTA, XFS_BS_SICK_BMBTA },
448 : { XFS_SICK_INO_BMBTC, XFS_BS_SICK_BMBTC },
449 : { XFS_SICK_INO_DIR, XFS_BS_SICK_DIR },
450 : { XFS_SICK_INO_XATTR, XFS_BS_SICK_XATTR },
451 : { XFS_SICK_INO_SYMLINK, XFS_BS_SICK_SYMLINK },
452 : { XFS_SICK_INO_PARENT, XFS_BS_SICK_PARENT },
453 : { XFS_SICK_INO_DIRTREE, XFS_BS_SICK_DIRTREE },
454 : { 0, 0 },
455 : };
456 :
457 : /* Fill out bulkstat health info. */
458 : void
459 72410228750 : xfs_bulkstat_health(
460 : struct xfs_inode *ip,
461 : struct xfs_bulkstat *bs)
462 : {
463 72410228750 : const struct ioctl_sick_map *m;
464 72410228750 : unsigned int sick;
465 72410228750 : unsigned int checked;
466 :
467 72410228750 : bs->bs_sick = 0;
468 72410228750 : bs->bs_checked = 0;
469 :
470 72410228750 : xfs_inode_measure_sickness(ip, &sick, &checked);
471 >78754*10^7 : for (m = ino_map; m->sick_mask; m++) {
472 >64237*10^7 : if (checked & m->sick_mask)
473 36561703693 : bs->bs_checked |= m->ioctl_mask;
474 >64237*10^7 : if (sick & m->sick_mask)
475 66 : bs->bs_sick |= m->ioctl_mask;
476 : }
477 71913902067 : }
478 :
479 : /* Mark a block mapping sick. */
480 : void
481 20 : xfs_bmap_mark_sick(
482 : struct xfs_inode *ip,
483 : int whichfork)
484 : {
485 20 : unsigned int mask;
486 :
487 20 : switch (whichfork) {
488 : case XFS_DATA_FORK:
489 : mask = XFS_SICK_INO_BMBTD;
490 : break;
491 : case XFS_ATTR_FORK:
492 : mask = XFS_SICK_INO_BMBTA;
493 : break;
494 : case XFS_COW_FORK:
495 : mask = XFS_SICK_INO_BMBTC;
496 : break;
497 0 : default:
498 0 : ASSERT(0);
499 0 : return;
500 : }
501 :
502 20 : xfs_inode_mark_sick(ip, mask);
503 : }
504 :
505 : /* Record observations of btree corruption with the health tracking system. */
506 : void
507 1365 : xfs_btree_mark_sick(
508 : struct xfs_btree_cur *cur)
509 : {
510 1365 : unsigned int mask;
511 :
512 1365 : if (cur->bc_flags & XFS_BTREE_IN_XFILE)
513 : return;
514 :
515 1365 : switch (cur->bc_btnum) {
516 10 : case XFS_BTNUM_BMAP:
517 10 : xfs_bmap_mark_sick(cur->bc_ino.ip, cur->bc_ino.whichfork);
518 10 : return;
519 : case XFS_BTNUM_BNO:
520 : mask = XFS_SICK_AG_BNOBT;
521 : break;
522 640 : case XFS_BTNUM_CNT:
523 640 : mask = XFS_SICK_AG_CNTBT;
524 640 : break;
525 16 : case XFS_BTNUM_INO:
526 16 : mask = XFS_SICK_AG_INOBT;
527 16 : break;
528 25 : case XFS_BTNUM_FINO:
529 25 : mask = XFS_SICK_AG_FINOBT;
530 25 : break;
531 12 : case XFS_BTNUM_RMAP:
532 12 : mask = XFS_SICK_AG_RMAPBT;
533 12 : break;
534 22 : case XFS_BTNUM_REFC:
535 22 : mask = XFS_SICK_AG_REFCNTBT;
536 22 : break;
537 0 : default:
538 0 : ASSERT(0);
539 0 : return;
540 : }
541 :
542 1355 : xfs_ag_mark_sick(cur->bc_ag.pag, mask);
543 : }
544 :
545 : /*
546 : * Record observations of dir/attr btree corruption with the health tracking
547 : * system.
548 : */
549 : void
550 263 : xfs_dirattr_mark_sick(
551 : struct xfs_inode *ip,
552 : int whichfork)
553 : {
554 263 : unsigned int mask;
555 :
556 263 : switch (whichfork) {
557 : case XFS_DATA_FORK:
558 : mask = XFS_SICK_INO_DIR;
559 : break;
560 51 : case XFS_ATTR_FORK:
561 51 : mask = XFS_SICK_INO_XATTR;
562 51 : break;
563 0 : default:
564 0 : ASSERT(0);
565 0 : return;
566 : }
567 :
568 263 : xfs_inode_mark_sick(ip, mask);
569 : }
570 :
571 : /*
572 : * Record observations of dir/attr btree corruption with the health tracking
573 : * system.
574 : */
575 : void
576 0 : xfs_da_mark_sick(
577 : struct xfs_da_args *args)
578 : {
579 0 : xfs_dirattr_mark_sick(args->dp, args->whichfork);
580 0 : }
|