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 24110 : xfs_health_unmount(
29 : struct xfs_mount *mp)
30 : {
31 24110 : struct xfs_perag *pag;
32 24110 : xfs_agnumber_t agno;
33 24110 : unsigned int sick = 0;
34 24110 : unsigned int checked = 0;
35 24110 : bool warn = false;
36 :
37 48220 : if (xfs_is_shutdown(mp))
38 11771 : return;
39 :
40 : /* Measure AG corruption levels. */
41 98671 : for_each_perag(mp, agno, pag) {
42 86332 : xfs_ag_measure_sickness(pag, &sick, &checked);
43 86332 : if (sick) {
44 20 : trace_xfs_ag_unfixed_corruption(mp, agno, sick);
45 20 : warn = true;
46 : }
47 : }
48 :
49 : /* Measure realtime volume corruption levels. */
50 12339 : xfs_rt_measure_sickness(mp, &sick, &checked);
51 12339 : 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 12339 : xfs_fs_measure_sickness(mp, &sick, &checked);
61 12339 : if (sick & ~XFS_SICK_FS_COUNTERS) {
62 1 : trace_xfs_fs_unfixed_corruption(mp, sick);
63 1 : warn = true;
64 : }
65 :
66 12339 : if (warn) {
67 21 : 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 21 : 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 215962 : xfs_fs_mark_sick(
97 : struct xfs_mount *mp,
98 : unsigned int mask)
99 : {
100 215962 : ASSERT(!(mask & ~XFS_SICK_FS_ALL));
101 215962 : trace_xfs_fs_mark_sick(mp, mask);
102 :
103 215962 : spin_lock(&mp->m_sb_lock);
104 215962 : mp->m_fs_sick |= mask;
105 215962 : spin_unlock(&mp->m_sb_lock);
106 215962 : }
107 :
108 : /* Mark per-fs metadata as having been checked. */
109 : void
110 215954 : xfs_fs_mark_checked(
111 : struct xfs_mount *mp,
112 : unsigned int mask)
113 : {
114 215954 : ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
115 :
116 215954 : spin_lock(&mp->m_sb_lock);
117 215954 : mp->m_fs_checked |= mask;
118 215954 : spin_unlock(&mp->m_sb_lock);
119 215954 : }
120 :
121 : /* Mark a per-fs metadata healed. */
122 : void
123 197154 : xfs_fs_mark_healthy(
124 : struct xfs_mount *mp,
125 : unsigned int mask)
126 : {
127 197154 : ASSERT(!(mask & ~XFS_SICK_FS_ALL));
128 197154 : trace_xfs_fs_mark_healthy(mp, mask);
129 :
130 197154 : spin_lock(&mp->m_sb_lock);
131 197154 : mp->m_fs_sick &= ~mask;
132 197154 : if (!(mp->m_fs_sick & XFS_SICK_FS_PRIMARY))
133 : mp->m_fs_sick &= ~XFS_SICK_FS_SECONDARY;
134 197154 : mp->m_fs_checked |= mask;
135 197154 : spin_unlock(&mp->m_sb_lock);
136 197154 : }
137 :
138 : /* Sample which per-fs metadata are unhealthy. */
139 : void
140 40526 : xfs_fs_measure_sickness(
141 : struct xfs_mount *mp,
142 : unsigned int *sick,
143 : unsigned int *checked)
144 : {
145 52865 : spin_lock(&mp->m_sb_lock);
146 2073957 : *sick = mp->m_fs_sick;
147 2073957 : *checked = mp->m_fs_checked;
148 2073957 : spin_unlock(&mp->m_sb_lock);
149 40526 : }
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 60873 : xfs_rt_mark_healthy(
182 : struct xfs_mount *mp,
183 : unsigned int mask)
184 : {
185 60873 : ASSERT(!(mask & ~XFS_SICK_RT_ALL));
186 60873 : trace_xfs_rt_mark_healthy(mp, mask);
187 :
188 60873 : spin_lock(&mp->m_sb_lock);
189 60873 : mp->m_rt_sick &= ~mask;
190 60873 : if (!(mp->m_rt_sick & XFS_SICK_RT_PRIMARY))
191 : mp->m_rt_sick &= ~XFS_SICK_RT_SECONDARY;
192 60873 : mp->m_rt_checked |= mask;
193 60873 : spin_unlock(&mp->m_sb_lock);
194 60873 : }
195 :
196 : /* Sample which realtime metadata are unhealthy. */
197 : void
198 12873 : xfs_rt_measure_sickness(
199 : struct xfs_mount *mp,
200 : unsigned int *sick,
201 : unsigned int *checked)
202 : {
203 25212 : spin_lock(&mp->m_sb_lock);
204 2046304 : *sick = mp->m_rt_sick;
205 2046304 : *checked = mp->m_rt_checked;
206 2046304 : spin_unlock(&mp->m_sb_lock);
207 12873 : }
208 :
209 : /* Mark unhealthy per-ag metadata given a raw AG number. */
210 : void
211 400 : xfs_agno_mark_sick(
212 : struct xfs_mount *mp,
213 : xfs_agnumber_t agno,
214 : unsigned int mask)
215 : {
216 400 : struct xfs_perag *pag = xfs_perag_get(mp, agno);
217 :
218 : /* per-ag structure not set up yet? */
219 400 : if (!pag)
220 : return;
221 :
222 400 : xfs_ag_mark_sick(pag, mask);
223 400 : xfs_perag_put(pag);
224 : }
225 :
226 : /* Mark unhealthy per-ag metadata. */
227 : void
228 1871 : xfs_ag_mark_sick(
229 : struct xfs_perag *pag,
230 : unsigned int mask)
231 : {
232 1871 : ASSERT(!(mask & ~XFS_SICK_AG_ALL));
233 1871 : trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask);
234 :
235 1871 : spin_lock(&pag->pag_state_lock);
236 1871 : pag->pag_sick |= mask;
237 1871 : spin_unlock(&pag->pag_state_lock);
238 1871 : }
239 :
240 : /* Mark per-ag metadata as having been checked. */
241 : void
242 18 : xfs_ag_mark_checked(
243 : struct xfs_perag *pag,
244 : unsigned int mask)
245 : {
246 18 : ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
247 :
248 18 : spin_lock(&pag->pag_state_lock);
249 18 : pag->pag_checked |= mask;
250 18 : spin_unlock(&pag->pag_state_lock);
251 18 : }
252 :
253 : /* Mark per-ag metadata ok. */
254 : void
255 2513430 : xfs_ag_mark_healthy(
256 : struct xfs_perag *pag,
257 : unsigned int mask)
258 : {
259 2513430 : ASSERT(!(mask & ~XFS_SICK_AG_ALL));
260 2513430 : trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask);
261 :
262 2513422 : spin_lock(&pag->pag_state_lock);
263 2513414 : pag->pag_sick &= ~mask;
264 2513414 : if (!(pag->pag_sick & XFS_SICK_AG_PRIMARY))
265 : pag->pag_sick &= ~XFS_SICK_AG_SECONDARY;
266 2513414 : pag->pag_checked |= mask;
267 2513414 : spin_unlock(&pag->pag_state_lock);
268 2513380 : }
269 :
270 : /* Sample which per-ag metadata are unhealthy. */
271 : void
272 1621996279 : xfs_ag_measure_sickness(
273 : struct xfs_perag *pag,
274 : unsigned int *sick,
275 : unsigned int *checked)
276 : {
277 1622082611 : spin_lock(&pag->pag_state_lock);
278 1622265622 : *sick = pag->pag_sick;
279 1622265622 : *checked = pag->pag_checked;
280 1622265622 : spin_unlock(&pag->pag_state_lock);
281 1622046258 : }
282 :
283 : /* Mark the unhealthy parts of an inode. */
284 : void
285 466 : xfs_inode_mark_sick(
286 : struct xfs_inode *ip,
287 : unsigned int mask)
288 : {
289 466 : ASSERT(!(mask & ~XFS_SICK_INO_ALL));
290 466 : trace_xfs_inode_mark_sick(ip, mask);
291 :
292 466 : spin_lock(&ip->i_flags_lock);
293 466 : ip->i_sick |= mask;
294 466 : 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 466 : spin_lock(&VFS_I(ip)->i_lock);
302 466 : VFS_I(ip)->i_state &= ~I_DONTCACHE;
303 466 : spin_unlock(&VFS_I(ip)->i_lock);
304 466 : }
305 :
306 : /* Mark inode metadata as having been checked. */
307 : void
308 6 : xfs_inode_mark_checked(
309 : struct xfs_inode *ip,
310 : unsigned int mask)
311 : {
312 6 : ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
313 :
314 6 : spin_lock(&ip->i_flags_lock);
315 6 : ip->i_checked |= mask;
316 6 : spin_unlock(&ip->i_flags_lock);
317 6 : }
318 :
319 : /* Mark parts of an inode healed. */
320 : void
321 550102398 : xfs_inode_mark_healthy(
322 : struct xfs_inode *ip,
323 : unsigned int mask)
324 : {
325 550102398 : ASSERT(!(mask & ~XFS_SICK_INO_ALL));
326 550102398 : trace_xfs_inode_mark_healthy(ip, mask);
327 :
328 550105647 : spin_lock(&ip->i_flags_lock);
329 550142014 : ip->i_sick &= ~mask;
330 550142014 : if (!(ip->i_sick & XFS_SICK_INO_PRIMARY))
331 550142919 : ip->i_sick &= ~XFS_SICK_INO_SECONDARY;
332 550142014 : ip->i_checked |= mask;
333 550142014 : spin_unlock(&ip->i_flags_lock);
334 550041506 : }
335 :
336 : /* Sample which parts of an inode are unhealthy. */
337 : void
338 47743202 : xfs_inode_measure_sickness(
339 : struct xfs_inode *ip,
340 : unsigned int *sick,
341 : unsigned int *checked)
342 : {
343 47743202 : spin_lock(&ip->i_flags_lock);
344 60474178621 : *sick = ip->i_sick;
345 60474178621 : *checked = ip->i_checked;
346 60474178621 : spin_unlock(&ip->i_flags_lock);
347 47716871 : }
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 16096142 : 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 16096142 : if (checked & m->sick_mask)
380 1460829 : geo->checked |= m->ioctl_mask;
381 16096142 : if (sick & m->sick_mask)
382 55460 : geo->sick |= m->ioctl_mask;
383 16096142 : }
384 :
385 : /* Fill out fs geometry health info. */
386 : void
387 2014256 : xfs_fsop_geom_health(
388 : struct xfs_mount *mp,
389 : struct xfs_fsop_geom *geo)
390 : {
391 2014256 : const struct ioctl_sick_map *m;
392 2014256 : unsigned int sick;
393 2014256 : unsigned int checked;
394 :
395 2014256 : geo->sick = 0;
396 2014256 : geo->checked = 0;
397 :
398 2014256 : xfs_fs_measure_sickness(mp, &sick, &checked);
399 16068050 : for (m = fs_map; m->sick_mask; m++)
400 12033355 : xfgeo_health_tick(geo, sick, checked, m);
401 :
402 2013603 : xfs_rt_measure_sickness(mp, &sick, &checked);
403 8083477 : for (m = rt_map; m->sick_mask; m++)
404 4041490 : xfgeo_health_tick(geo, sick, checked, m);
405 2020895 : }
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 15411 : xfs_ag_geom_health(
425 : struct xfs_perag *pag,
426 : struct xfs_ag_geometry *ageo)
427 : {
428 15411 : const struct ioctl_sick_map *m;
429 15411 : unsigned int sick;
430 15411 : unsigned int checked;
431 :
432 15411 : ageo->ag_sick = 0;
433 15411 : ageo->ag_checked = 0;
434 :
435 15411 : xfs_ag_measure_sickness(pag, &sick, &checked);
436 200343 : for (m = ag_map; m->sick_mask; m++) {
437 169521 : if (checked & m->sick_mask)
438 168831 : ageo->ag_checked |= m->ioctl_mask;
439 169521 : if (sick & m->sick_mask)
440 2 : ageo->ag_sick |= m->ioctl_mask;
441 : }
442 15411 : }
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 60181201129 : xfs_bulkstat_health(
460 : struct xfs_inode *ip,
461 : struct xfs_bulkstat *bs)
462 : {
463 60181201129 : const struct ioctl_sick_map *m;
464 60181201129 : unsigned int sick;
465 60181201129 : unsigned int checked;
466 :
467 60181201129 : bs->bs_sick = 0;
468 60181201129 : bs->bs_checked = 0;
469 :
470 60181201129 : xfs_inode_measure_sickness(ip, &sick, &checked);
471 >65953*10^7 : for (m = ino_map; m->sick_mask; m++) {
472 >53867*10^7 : if (checked & m->sick_mask)
473 28464265370 : bs->bs_checked |= m->ioctl_mask;
474 >53867*10^7 : if (sick & m->sick_mask)
475 12 : bs->bs_sick |= m->ioctl_mask;
476 : }
477 60431492144 : }
478 :
479 : /* Mark a block mapping sick. */
480 : void
481 4 : xfs_bmap_mark_sick(
482 : struct xfs_inode *ip,
483 : int whichfork)
484 : {
485 4 : unsigned int mask;
486 :
487 4 : 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 4 : xfs_inode_mark_sick(ip, mask);
503 : }
504 :
505 : /* Record observations of btree corruption with the health tracking system. */
506 : void
507 274 : xfs_btree_mark_sick(
508 : struct xfs_btree_cur *cur)
509 : {
510 274 : unsigned int mask;
511 :
512 274 : if (cur->bc_flags & XFS_BTREE_IN_XFILE)
513 : return;
514 :
515 274 : switch (cur->bc_btnum) {
516 2 : case XFS_BTNUM_BMAP:
517 2 : xfs_bmap_mark_sick(cur->bc_ino.ip, cur->bc_ino.whichfork);
518 2 : return;
519 : case XFS_BTNUM_BNO:
520 : mask = XFS_SICK_AG_BNOBT;
521 : break;
522 128 : case XFS_BTNUM_CNT:
523 128 : mask = XFS_SICK_AG_CNTBT;
524 128 : break;
525 2 : case XFS_BTNUM_INO:
526 2 : mask = XFS_SICK_AG_INOBT;
527 2 : break;
528 2 : case XFS_BTNUM_FINO:
529 2 : mask = XFS_SICK_AG_FINOBT;
530 2 : break;
531 4 : case XFS_BTNUM_RMAP:
532 4 : mask = XFS_SICK_AG_RMAPBT;
533 4 : break;
534 8 : case XFS_BTNUM_REFC:
535 8 : mask = XFS_SICK_AG_REFCNTBT;
536 8 : break;
537 0 : default:
538 0 : ASSERT(0);
539 0 : return;
540 : }
541 :
542 272 : 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 252 : xfs_dirattr_mark_sick(
551 : struct xfs_inode *ip,
552 : int whichfork)
553 : {
554 252 : unsigned int mask;
555 :
556 252 : switch (whichfork) {
557 : case XFS_DATA_FORK:
558 : mask = XFS_SICK_INO_DIR;
559 : break;
560 210 : case XFS_ATTR_FORK:
561 210 : mask = XFS_SICK_INO_XATTR;
562 210 : break;
563 0 : default:
564 0 : ASSERT(0);
565 0 : return;
566 : }
567 :
568 252 : 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 : }
|