1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2019 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
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"
17 #include "xfs_btree.h"
18 #include "xfs_da_format.h"
19 #include "xfs_da_btree.h"
20 #include "xfs_quota_defs.h"
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
31 struct xfs_perag
*pag
;
33 unsigned int sick
= 0;
34 unsigned int checked
= 0;
37 if (xfs_is_shutdown(mp
))
40 /* Measure AG corruption levels. */
41 for_each_perag(mp
, agno
, pag
) {
42 xfs_ag_measure_sickness(pag
, &sick
, &checked
);
44 trace_xfs_ag_unfixed_corruption(mp
, agno
, sick
);
49 /* Measure realtime volume corruption levels. */
50 xfs_rt_measure_sickness(mp
, &sick
, &checked
);
52 trace_xfs_rt_unfixed_corruption(mp
, sick
);
57 * Measure fs corruption and keep the sample around for the warning.
58 * See the note below for why we exempt FS_COUNTERS.
60 xfs_fs_measure_sickness(mp
, &sick
, &checked
);
61 if (sick
& ~XFS_SICK_FS_COUNTERS
) {
62 trace_xfs_fs_unfixed_corruption(mp
, sick
);
68 "Uncorrected metadata errors detected; please run xfs_repair.");
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.
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.
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
89 if (sick
& XFS_SICK_FS_COUNTERS
)
90 xfs_fs_mark_healthy(mp
, XFS_SICK_FS_COUNTERS
);
94 /* Mark unhealthy per-fs metadata. */
100 ASSERT(!(mask
& ~XFS_SICK_FS_ALL
));
101 trace_xfs_fs_mark_sick(mp
, mask
);
103 spin_lock(&mp
->m_sb_lock
);
104 mp
->m_fs_sick
|= mask
;
105 spin_unlock(&mp
->m_sb_lock
);
108 /* Mark per-fs metadata as having been checked and found unhealthy by fsck. */
111 struct xfs_mount
*mp
,
114 ASSERT(!(mask
& ~XFS_SICK_FS_ALL
));
115 trace_xfs_fs_mark_corrupt(mp
, mask
);
117 spin_lock(&mp
->m_sb_lock
);
118 mp
->m_fs_sick
|= mask
;
119 mp
->m_fs_checked
|= mask
;
120 spin_unlock(&mp
->m_sb_lock
);
123 /* Mark a per-fs metadata healed. */
126 struct xfs_mount
*mp
,
129 ASSERT(!(mask
& ~XFS_SICK_FS_ALL
));
130 trace_xfs_fs_mark_healthy(mp
, mask
);
132 spin_lock(&mp
->m_sb_lock
);
133 mp
->m_fs_sick
&= ~mask
;
134 if (!(mp
->m_fs_sick
& XFS_SICK_FS_PRIMARY
))
135 mp
->m_fs_sick
&= ~XFS_SICK_FS_SECONDARY
;
136 mp
->m_fs_checked
|= mask
;
137 spin_unlock(&mp
->m_sb_lock
);
140 /* Sample which per-fs metadata are unhealthy. */
142 xfs_fs_measure_sickness(
143 struct xfs_mount
*mp
,
145 unsigned int *checked
)
147 spin_lock(&mp
->m_sb_lock
);
148 *sick
= mp
->m_fs_sick
;
149 *checked
= mp
->m_fs_checked
;
150 spin_unlock(&mp
->m_sb_lock
);
153 /* Mark unhealthy realtime metadata. */
156 struct xfs_mount
*mp
,
159 ASSERT(!(mask
& ~XFS_SICK_RT_ALL
));
160 trace_xfs_rt_mark_sick(mp
, mask
);
162 spin_lock(&mp
->m_sb_lock
);
163 mp
->m_rt_sick
|= mask
;
164 spin_unlock(&mp
->m_sb_lock
);
167 /* Mark realtime metadata as having been checked and found unhealthy by fsck. */
170 struct xfs_mount
*mp
,
173 ASSERT(!(mask
& ~XFS_SICK_RT_ALL
));
174 trace_xfs_rt_mark_corrupt(mp
, mask
);
176 spin_lock(&mp
->m_sb_lock
);
177 mp
->m_rt_sick
|= mask
;
178 mp
->m_rt_checked
|= mask
;
179 spin_unlock(&mp
->m_sb_lock
);
182 /* Mark a realtime metadata healed. */
185 struct xfs_mount
*mp
,
188 ASSERT(!(mask
& ~XFS_SICK_RT_ALL
));
189 trace_xfs_rt_mark_healthy(mp
, mask
);
191 spin_lock(&mp
->m_sb_lock
);
192 mp
->m_rt_sick
&= ~mask
;
193 if (!(mp
->m_rt_sick
& XFS_SICK_RT_PRIMARY
))
194 mp
->m_rt_sick
&= ~XFS_SICK_RT_SECONDARY
;
195 mp
->m_rt_checked
|= mask
;
196 spin_unlock(&mp
->m_sb_lock
);
199 /* Sample which realtime metadata are unhealthy. */
201 xfs_rt_measure_sickness(
202 struct xfs_mount
*mp
,
204 unsigned int *checked
)
206 spin_lock(&mp
->m_sb_lock
);
207 *sick
= mp
->m_rt_sick
;
208 *checked
= mp
->m_rt_checked
;
209 spin_unlock(&mp
->m_sb_lock
);
212 /* Mark unhealthy per-ag metadata given a raw AG number. */
215 struct xfs_mount
*mp
,
219 struct xfs_perag
*pag
= xfs_perag_get(mp
, agno
);
221 /* per-ag structure not set up yet? */
225 xfs_ag_mark_sick(pag
, mask
);
229 /* Mark unhealthy per-ag metadata. */
232 struct xfs_perag
*pag
,
235 ASSERT(!(mask
& ~XFS_SICK_AG_ALL
));
236 trace_xfs_ag_mark_sick(pag
->pag_mount
, pag
->pag_agno
, mask
);
238 spin_lock(&pag
->pag_state_lock
);
239 pag
->pag_sick
|= mask
;
240 spin_unlock(&pag
->pag_state_lock
);
243 /* Mark per-ag metadata as having been checked and found unhealthy by fsck. */
246 struct xfs_perag
*pag
,
249 ASSERT(!(mask
& ~XFS_SICK_AG_ALL
));
250 trace_xfs_ag_mark_corrupt(pag
->pag_mount
, pag
->pag_agno
, mask
);
252 spin_lock(&pag
->pag_state_lock
);
253 pag
->pag_sick
|= mask
;
254 pag
->pag_checked
|= mask
;
255 spin_unlock(&pag
->pag_state_lock
);
258 /* Mark per-ag metadata ok. */
261 struct xfs_perag
*pag
,
264 ASSERT(!(mask
& ~XFS_SICK_AG_ALL
));
265 trace_xfs_ag_mark_healthy(pag
->pag_mount
, pag
->pag_agno
, mask
);
267 spin_lock(&pag
->pag_state_lock
);
268 pag
->pag_sick
&= ~mask
;
269 if (!(pag
->pag_sick
& XFS_SICK_AG_PRIMARY
))
270 pag
->pag_sick
&= ~XFS_SICK_AG_SECONDARY
;
271 pag
->pag_checked
|= mask
;
272 spin_unlock(&pag
->pag_state_lock
);
275 /* Sample which per-ag metadata are unhealthy. */
277 xfs_ag_measure_sickness(
278 struct xfs_perag
*pag
,
280 unsigned int *checked
)
282 spin_lock(&pag
->pag_state_lock
);
283 *sick
= pag
->pag_sick
;
284 *checked
= pag
->pag_checked
;
285 spin_unlock(&pag
->pag_state_lock
);
288 /* Mark the unhealthy parts of an inode. */
291 struct xfs_inode
*ip
,
294 ASSERT(!(mask
& ~XFS_SICK_INO_ALL
));
295 trace_xfs_inode_mark_sick(ip
, mask
);
297 spin_lock(&ip
->i_flags_lock
);
299 spin_unlock(&ip
->i_flags_lock
);
302 * Keep this inode around so we don't lose the sickness report. Scrub
303 * grabs inodes with DONTCACHE assuming that most inode are ok, which
304 * is not the case here.
306 spin_lock(&VFS_I(ip
)->i_lock
);
307 VFS_I(ip
)->i_state
&= ~I_DONTCACHE
;
308 spin_unlock(&VFS_I(ip
)->i_lock
);
311 /* Mark inode metadata as having been checked and found unhealthy by fsck. */
313 xfs_inode_mark_corrupt(
314 struct xfs_inode
*ip
,
317 ASSERT(!(mask
& ~XFS_SICK_INO_ALL
));
318 trace_xfs_inode_mark_corrupt(ip
, mask
);
320 spin_lock(&ip
->i_flags_lock
);
322 ip
->i_checked
|= mask
;
323 spin_unlock(&ip
->i_flags_lock
);
326 * Keep this inode around so we don't lose the sickness report. Scrub
327 * grabs inodes with DONTCACHE assuming that most inode are ok, which
328 * is not the case here.
330 spin_lock(&VFS_I(ip
)->i_lock
);
331 VFS_I(ip
)->i_state
&= ~I_DONTCACHE
;
332 spin_unlock(&VFS_I(ip
)->i_lock
);
335 /* Mark parts of an inode healed. */
337 xfs_inode_mark_healthy(
338 struct xfs_inode
*ip
,
341 ASSERT(!(mask
& ~XFS_SICK_INO_ALL
));
342 trace_xfs_inode_mark_healthy(ip
, mask
);
344 spin_lock(&ip
->i_flags_lock
);
346 if (!(ip
->i_sick
& XFS_SICK_INO_PRIMARY
))
347 ip
->i_sick
&= ~XFS_SICK_INO_SECONDARY
;
348 ip
->i_checked
|= mask
;
349 spin_unlock(&ip
->i_flags_lock
);
352 /* Sample which parts of an inode are unhealthy. */
354 xfs_inode_measure_sickness(
355 struct xfs_inode
*ip
,
357 unsigned int *checked
)
359 spin_lock(&ip
->i_flags_lock
);
361 *checked
= ip
->i_checked
;
362 spin_unlock(&ip
->i_flags_lock
);
365 /* Mappings between internal sick masks and ioctl sick masks. */
367 struct ioctl_sick_map
{
368 unsigned int sick_mask
;
369 unsigned int ioctl_mask
;
372 static const struct ioctl_sick_map fs_map
[] = {
373 { XFS_SICK_FS_COUNTERS
, XFS_FSOP_GEOM_SICK_COUNTERS
},
374 { XFS_SICK_FS_UQUOTA
, XFS_FSOP_GEOM_SICK_UQUOTA
},
375 { XFS_SICK_FS_GQUOTA
, XFS_FSOP_GEOM_SICK_GQUOTA
},
376 { XFS_SICK_FS_PQUOTA
, XFS_FSOP_GEOM_SICK_PQUOTA
},
377 { XFS_SICK_FS_QUOTACHECK
, XFS_FSOP_GEOM_SICK_QUOTACHECK
},
378 { XFS_SICK_FS_NLINKS
, XFS_FSOP_GEOM_SICK_NLINKS
},
382 static const struct ioctl_sick_map rt_map
[] = {
383 { XFS_SICK_RT_BITMAP
, XFS_FSOP_GEOM_SICK_RT_BITMAP
},
384 { XFS_SICK_RT_SUMMARY
, XFS_FSOP_GEOM_SICK_RT_SUMMARY
},
390 struct xfs_fsop_geom
*geo
,
392 unsigned int checked
,
393 const struct ioctl_sick_map
*m
)
395 if (checked
& m
->sick_mask
)
396 geo
->checked
|= m
->ioctl_mask
;
397 if (sick
& m
->sick_mask
)
398 geo
->sick
|= m
->ioctl_mask
;
401 /* Fill out fs geometry health info. */
403 xfs_fsop_geom_health(
404 struct xfs_mount
*mp
,
405 struct xfs_fsop_geom
*geo
)
407 const struct ioctl_sick_map
*m
;
409 unsigned int checked
;
414 xfs_fs_measure_sickness(mp
, &sick
, &checked
);
415 for (m
= fs_map
; m
->sick_mask
; m
++)
416 xfgeo_health_tick(geo
, sick
, checked
, m
);
418 xfs_rt_measure_sickness(mp
, &sick
, &checked
);
419 for (m
= rt_map
; m
->sick_mask
; m
++)
420 xfgeo_health_tick(geo
, sick
, checked
, m
);
423 static const struct ioctl_sick_map ag_map
[] = {
424 { XFS_SICK_AG_SB
, XFS_AG_GEOM_SICK_SB
},
425 { XFS_SICK_AG_AGF
, XFS_AG_GEOM_SICK_AGF
},
426 { XFS_SICK_AG_AGFL
, XFS_AG_GEOM_SICK_AGFL
},
427 { XFS_SICK_AG_AGI
, XFS_AG_GEOM_SICK_AGI
},
428 { XFS_SICK_AG_BNOBT
, XFS_AG_GEOM_SICK_BNOBT
},
429 { XFS_SICK_AG_CNTBT
, XFS_AG_GEOM_SICK_CNTBT
},
430 { XFS_SICK_AG_INOBT
, XFS_AG_GEOM_SICK_INOBT
},
431 { XFS_SICK_AG_FINOBT
, XFS_AG_GEOM_SICK_FINOBT
},
432 { XFS_SICK_AG_RMAPBT
, XFS_AG_GEOM_SICK_RMAPBT
},
433 { XFS_SICK_AG_REFCNTBT
, XFS_AG_GEOM_SICK_REFCNTBT
},
434 { XFS_SICK_AG_INODES
, XFS_AG_GEOM_SICK_INODES
},
438 /* Fill out ag geometry health info. */
441 struct xfs_perag
*pag
,
442 struct xfs_ag_geometry
*ageo
)
444 const struct ioctl_sick_map
*m
;
446 unsigned int checked
;
449 ageo
->ag_checked
= 0;
451 xfs_ag_measure_sickness(pag
, &sick
, &checked
);
452 for (m
= ag_map
; m
->sick_mask
; m
++) {
453 if (checked
& m
->sick_mask
)
454 ageo
->ag_checked
|= m
->ioctl_mask
;
455 if (sick
& m
->sick_mask
)
456 ageo
->ag_sick
|= m
->ioctl_mask
;
460 static const struct ioctl_sick_map ino_map
[] = {
461 { XFS_SICK_INO_CORE
, XFS_BS_SICK_INODE
},
462 { XFS_SICK_INO_BMBTD
, XFS_BS_SICK_BMBTD
},
463 { XFS_SICK_INO_BMBTA
, XFS_BS_SICK_BMBTA
},
464 { XFS_SICK_INO_BMBTC
, XFS_BS_SICK_BMBTC
},
465 { XFS_SICK_INO_DIR
, XFS_BS_SICK_DIR
},
466 { XFS_SICK_INO_XATTR
, XFS_BS_SICK_XATTR
},
467 { XFS_SICK_INO_SYMLINK
, XFS_BS_SICK_SYMLINK
},
468 { XFS_SICK_INO_PARENT
, XFS_BS_SICK_PARENT
},
469 { XFS_SICK_INO_BMBTD_ZAPPED
, XFS_BS_SICK_BMBTD
},
470 { XFS_SICK_INO_BMBTA_ZAPPED
, XFS_BS_SICK_BMBTA
},
471 { XFS_SICK_INO_DIR_ZAPPED
, XFS_BS_SICK_DIR
},
472 { XFS_SICK_INO_SYMLINK_ZAPPED
, XFS_BS_SICK_SYMLINK
},
473 { XFS_SICK_INO_DIRTREE
, XFS_BS_SICK_DIRTREE
},
477 /* Fill out bulkstat health info. */
480 struct xfs_inode
*ip
,
481 struct xfs_bulkstat
*bs
)
483 const struct ioctl_sick_map
*m
;
485 unsigned int checked
;
490 xfs_inode_measure_sickness(ip
, &sick
, &checked
);
491 for (m
= ino_map
; m
->sick_mask
; m
++) {
492 if (checked
& m
->sick_mask
)
493 bs
->bs_checked
|= m
->ioctl_mask
;
494 if (sick
& m
->sick_mask
)
495 bs
->bs_sick
|= m
->ioctl_mask
;
499 /* Mark a block mapping sick. */
502 struct xfs_inode
*ip
,
509 mask
= XFS_SICK_INO_BMBTD
;
512 mask
= XFS_SICK_INO_BMBTA
;
515 mask
= XFS_SICK_INO_BMBTC
;
522 xfs_inode_mark_sick(ip
, mask
);
525 /* Record observations of btree corruption with the health tracking system. */
528 struct xfs_btree_cur
*cur
)
530 switch (cur
->bc_ops
->type
) {
531 case XFS_BTREE_TYPE_MEM
:
532 /* no health state tracking for ephemeral btrees */
534 case XFS_BTREE_TYPE_AG
:
535 ASSERT(cur
->bc_ops
->sick_mask
);
536 xfs_ag_mark_sick(cur
->bc_ag
.pag
, cur
->bc_ops
->sick_mask
);
538 case XFS_BTREE_TYPE_INODE
:
539 if (xfs_btree_is_bmap(cur
->bc_ops
)) {
540 xfs_bmap_mark_sick(cur
->bc_ino
.ip
,
541 cur
->bc_ino
.whichfork
);
552 * Record observations of dir/attr btree corruption with the health tracking
556 xfs_dirattr_mark_sick(
557 struct xfs_inode
*ip
,
564 mask
= XFS_SICK_INO_DIR
;
567 mask
= XFS_SICK_INO_XATTR
;
574 xfs_inode_mark_sick(ip
, mask
);
578 * Record observations of dir/attr btree corruption with the health tracking
583 struct xfs_da_args
*args
)
585 xfs_dirattr_mark_sick(args
->dp
, args
->whichfork
);