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"
21 #include "xfs_rtgroup.h"
24 xfs_health_unmount_group(
28 unsigned int sick
= 0;
29 unsigned int checked
= 0;
31 xfs_group_measure_sickness(xg
, &sick
, &checked
);
33 trace_xfs_group_unfixed_corruption(xg
, sick
);
39 * Warn about metadata corruption that we detected but haven't fixed, and
40 * make sure we're not sitting on anything that would get in the way of
47 struct xfs_perag
*pag
= NULL
;
48 struct xfs_rtgroup
*rtg
= NULL
;
49 unsigned int sick
= 0;
50 unsigned int checked
= 0;
53 if (xfs_is_shutdown(mp
))
56 /* Measure AG corruption levels. */
57 while ((pag
= xfs_perag_next(mp
, pag
)))
58 xfs_health_unmount_group(pag_group(pag
), &warn
);
60 /* Measure realtime group corruption levels. */
61 while ((rtg
= xfs_rtgroup_next(mp
, rtg
)))
62 xfs_health_unmount_group(rtg_group(rtg
), &warn
);
65 * Measure fs corruption and keep the sample around for the warning.
66 * See the note below for why we exempt FS_COUNTERS.
68 xfs_fs_measure_sickness(mp
, &sick
, &checked
);
69 if (sick
& ~XFS_SICK_FS_COUNTERS
) {
70 trace_xfs_fs_unfixed_corruption(mp
, sick
);
76 "Uncorrected metadata errors detected; please run xfs_repair.");
79 * We discovered uncorrected metadata problems at some point
80 * during this filesystem mount and have advised the
81 * administrator to run repair once the unmount completes.
83 * However, we must be careful -- when FSCOUNTERS are flagged
84 * unhealthy, the unmount procedure omits writing the clean
85 * unmount record to the log so that the next mount will run
86 * recovery and recompute the summary counters. In other
87 * words, we leave a dirty log to get the counters fixed.
89 * Unfortunately, xfs_repair cannot recover dirty logs, so if
90 * there were filesystem problems, FSCOUNTERS was flagged, and
91 * the administrator takes our advice to run xfs_repair,
92 * they'll have to zap the log before repairing structures.
93 * We don't really want to encourage this, so we mark the
94 * FSCOUNTERS healthy so that a subsequent repair run won't see
97 if (sick
& XFS_SICK_FS_COUNTERS
)
98 xfs_fs_mark_healthy(mp
, XFS_SICK_FS_COUNTERS
);
102 /* Mark unhealthy per-fs metadata. */
105 struct xfs_mount
*mp
,
108 ASSERT(!(mask
& ~XFS_SICK_FS_ALL
));
109 trace_xfs_fs_mark_sick(mp
, mask
);
111 spin_lock(&mp
->m_sb_lock
);
112 mp
->m_fs_sick
|= mask
;
113 spin_unlock(&mp
->m_sb_lock
);
116 /* Mark per-fs metadata as having been checked and found unhealthy by fsck. */
119 struct xfs_mount
*mp
,
122 ASSERT(!(mask
& ~XFS_SICK_FS_ALL
));
123 trace_xfs_fs_mark_corrupt(mp
, mask
);
125 spin_lock(&mp
->m_sb_lock
);
126 mp
->m_fs_sick
|= mask
;
127 mp
->m_fs_checked
|= mask
;
128 spin_unlock(&mp
->m_sb_lock
);
131 /* Mark a per-fs metadata healed. */
134 struct xfs_mount
*mp
,
137 ASSERT(!(mask
& ~XFS_SICK_FS_ALL
));
138 trace_xfs_fs_mark_healthy(mp
, mask
);
140 spin_lock(&mp
->m_sb_lock
);
141 mp
->m_fs_sick
&= ~mask
;
142 if (!(mp
->m_fs_sick
& XFS_SICK_FS_PRIMARY
))
143 mp
->m_fs_sick
&= ~XFS_SICK_FS_SECONDARY
;
144 mp
->m_fs_checked
|= mask
;
145 spin_unlock(&mp
->m_sb_lock
);
148 /* Sample which per-fs metadata are unhealthy. */
150 xfs_fs_measure_sickness(
151 struct xfs_mount
*mp
,
153 unsigned int *checked
)
155 spin_lock(&mp
->m_sb_lock
);
156 *sick
= mp
->m_fs_sick
;
157 *checked
= mp
->m_fs_checked
;
158 spin_unlock(&mp
->m_sb_lock
);
161 /* Mark unhealthy per-ag metadata given a raw AG number. */
164 struct xfs_mount
*mp
,
168 struct xfs_perag
*pag
= xfs_perag_get(mp
, agno
);
170 /* per-ag structure not set up yet? */
174 xfs_ag_mark_sick(pag
, mask
);
179 xfs_group_check_mask(
180 struct xfs_group
*xg
,
183 if (xg
->xg_type
== XG_TYPE_AG
)
184 ASSERT(!(mask
& ~XFS_SICK_AG_ALL
));
186 ASSERT(!(mask
& ~XFS_SICK_RG_ALL
));
189 /* Mark unhealthy per-ag metadata. */
192 struct xfs_group
*xg
,
195 xfs_group_check_mask(xg
, mask
);
196 trace_xfs_group_mark_sick(xg
, mask
);
198 spin_lock(&xg
->xg_state_lock
);
200 spin_unlock(&xg
->xg_state_lock
);
204 * Mark per-group metadata as having been checked and found unhealthy by fsck.
207 xfs_group_mark_corrupt(
208 struct xfs_group
*xg
,
211 xfs_group_check_mask(xg
, mask
);
212 trace_xfs_group_mark_corrupt(xg
, mask
);
214 spin_lock(&xg
->xg_state_lock
);
216 xg
->xg_checked
|= mask
;
217 spin_unlock(&xg
->xg_state_lock
);
221 * Mark per-group metadata ok.
224 xfs_group_mark_healthy(
225 struct xfs_group
*xg
,
228 xfs_group_check_mask(xg
, mask
);
229 trace_xfs_group_mark_healthy(xg
, mask
);
231 spin_lock(&xg
->xg_state_lock
);
232 xg
->xg_sick
&= ~mask
;
233 if (!(xg
->xg_sick
& XFS_SICK_AG_PRIMARY
))
234 xg
->xg_sick
&= ~XFS_SICK_AG_SECONDARY
;
235 xg
->xg_checked
|= mask
;
236 spin_unlock(&xg
->xg_state_lock
);
239 /* Sample which per-ag metadata are unhealthy. */
241 xfs_group_measure_sickness(
242 struct xfs_group
*xg
,
244 unsigned int *checked
)
246 spin_lock(&xg
->xg_state_lock
);
248 *checked
= xg
->xg_checked
;
249 spin_unlock(&xg
->xg_state_lock
);
252 /* Mark unhealthy per-rtgroup metadata given a raw rt group number. */
255 struct xfs_mount
*mp
,
259 struct xfs_rtgroup
*rtg
= xfs_rtgroup_get(mp
, rgno
);
261 /* per-rtgroup structure not set up yet? */
265 xfs_group_mark_sick(rtg_group(rtg
), mask
);
266 xfs_rtgroup_put(rtg
);
269 /* Mark the unhealthy parts of an inode. */
272 struct xfs_inode
*ip
,
275 ASSERT(!(mask
& ~XFS_SICK_INO_ALL
));
276 trace_xfs_inode_mark_sick(ip
, mask
);
278 spin_lock(&ip
->i_flags_lock
);
280 spin_unlock(&ip
->i_flags_lock
);
283 * Keep this inode around so we don't lose the sickness report. Scrub
284 * grabs inodes with DONTCACHE assuming that most inode are ok, which
285 * is not the case here.
287 spin_lock(&VFS_I(ip
)->i_lock
);
288 VFS_I(ip
)->i_state
&= ~I_DONTCACHE
;
289 spin_unlock(&VFS_I(ip
)->i_lock
);
292 /* Mark inode metadata as having been checked and found unhealthy by fsck. */
294 xfs_inode_mark_corrupt(
295 struct xfs_inode
*ip
,
298 ASSERT(!(mask
& ~XFS_SICK_INO_ALL
));
299 trace_xfs_inode_mark_corrupt(ip
, mask
);
301 spin_lock(&ip
->i_flags_lock
);
303 ip
->i_checked
|= mask
;
304 spin_unlock(&ip
->i_flags_lock
);
307 * Keep this inode around so we don't lose the sickness report. Scrub
308 * grabs inodes with DONTCACHE assuming that most inode are ok, which
309 * is not the case here.
311 spin_lock(&VFS_I(ip
)->i_lock
);
312 VFS_I(ip
)->i_state
&= ~I_DONTCACHE
;
313 spin_unlock(&VFS_I(ip
)->i_lock
);
316 /* Mark parts of an inode healed. */
318 xfs_inode_mark_healthy(
319 struct xfs_inode
*ip
,
322 ASSERT(!(mask
& ~XFS_SICK_INO_ALL
));
323 trace_xfs_inode_mark_healthy(ip
, mask
);
325 spin_lock(&ip
->i_flags_lock
);
327 if (!(ip
->i_sick
& XFS_SICK_INO_PRIMARY
))
328 ip
->i_sick
&= ~XFS_SICK_INO_SECONDARY
;
329 ip
->i_checked
|= mask
;
330 spin_unlock(&ip
->i_flags_lock
);
333 /* Sample which parts of an inode are unhealthy. */
335 xfs_inode_measure_sickness(
336 struct xfs_inode
*ip
,
338 unsigned int *checked
)
340 spin_lock(&ip
->i_flags_lock
);
342 *checked
= ip
->i_checked
;
343 spin_unlock(&ip
->i_flags_lock
);
346 /* Mappings between internal sick masks and ioctl sick masks. */
348 struct ioctl_sick_map
{
349 unsigned int sick_mask
;
350 unsigned int ioctl_mask
;
353 #define for_each_sick_map(map, m) \
354 for ((m) = (map); (m) < (map) + ARRAY_SIZE(map); (m)++)
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 { XFS_SICK_FS_METADIR
, XFS_FSOP_GEOM_SICK_METADIR
},
364 { XFS_SICK_FS_METAPATH
, XFS_FSOP_GEOM_SICK_METAPATH
},
367 static const struct ioctl_sick_map rt_map
[] = {
368 { XFS_SICK_RG_BITMAP
, XFS_FSOP_GEOM_SICK_RT_BITMAP
},
369 { XFS_SICK_RG_SUMMARY
, XFS_FSOP_GEOM_SICK_RT_SUMMARY
},
374 struct xfs_fsop_geom
*geo
,
376 unsigned int checked
,
377 const struct ioctl_sick_map
*m
)
379 if (checked
& m
->sick_mask
)
380 geo
->checked
|= m
->ioctl_mask
;
381 if (sick
& m
->sick_mask
)
382 geo
->sick
|= m
->ioctl_mask
;
385 /* Fill out fs geometry health info. */
387 xfs_fsop_geom_health(
388 struct xfs_mount
*mp
,
389 struct xfs_fsop_geom
*geo
)
391 struct xfs_rtgroup
*rtg
= NULL
;
392 const struct ioctl_sick_map
*m
;
394 unsigned int checked
;
399 xfs_fs_measure_sickness(mp
, &sick
, &checked
);
400 for_each_sick_map(fs_map
, m
)
401 xfgeo_health_tick(geo
, sick
, checked
, m
);
403 while ((rtg
= xfs_rtgroup_next(mp
, rtg
))) {
404 xfs_group_measure_sickness(rtg_group(rtg
), &sick
, &checked
);
405 for_each_sick_map(rt_map
, m
)
406 xfgeo_health_tick(geo
, sick
, checked
, m
);
410 static const struct ioctl_sick_map ag_map
[] = {
411 { XFS_SICK_AG_SB
, XFS_AG_GEOM_SICK_SB
},
412 { XFS_SICK_AG_AGF
, XFS_AG_GEOM_SICK_AGF
},
413 { XFS_SICK_AG_AGFL
, XFS_AG_GEOM_SICK_AGFL
},
414 { XFS_SICK_AG_AGI
, XFS_AG_GEOM_SICK_AGI
},
415 { XFS_SICK_AG_BNOBT
, XFS_AG_GEOM_SICK_BNOBT
},
416 { XFS_SICK_AG_CNTBT
, XFS_AG_GEOM_SICK_CNTBT
},
417 { XFS_SICK_AG_INOBT
, XFS_AG_GEOM_SICK_INOBT
},
418 { XFS_SICK_AG_FINOBT
, XFS_AG_GEOM_SICK_FINOBT
},
419 { XFS_SICK_AG_RMAPBT
, XFS_AG_GEOM_SICK_RMAPBT
},
420 { XFS_SICK_AG_REFCNTBT
, XFS_AG_GEOM_SICK_REFCNTBT
},
421 { XFS_SICK_AG_INODES
, XFS_AG_GEOM_SICK_INODES
},
424 /* Fill out ag geometry health info. */
427 struct xfs_perag
*pag
,
428 struct xfs_ag_geometry
*ageo
)
430 const struct ioctl_sick_map
*m
;
432 unsigned int checked
;
435 ageo
->ag_checked
= 0;
437 xfs_group_measure_sickness(pag_group(pag
), &sick
, &checked
);
438 for_each_sick_map(ag_map
, m
) {
439 if (checked
& m
->sick_mask
)
440 ageo
->ag_checked
|= m
->ioctl_mask
;
441 if (sick
& m
->sick_mask
)
442 ageo
->ag_sick
|= m
->ioctl_mask
;
446 static const struct ioctl_sick_map rtgroup_map
[] = {
447 { XFS_SICK_RG_SUPER
, XFS_RTGROUP_GEOM_SICK_SUPER
},
448 { XFS_SICK_RG_BITMAP
, XFS_RTGROUP_GEOM_SICK_BITMAP
},
449 { XFS_SICK_RG_SUMMARY
, XFS_RTGROUP_GEOM_SICK_SUMMARY
},
452 /* Fill out rtgroup geometry health info. */
454 xfs_rtgroup_geom_health(
455 struct xfs_rtgroup
*rtg
,
456 struct xfs_rtgroup_geometry
*rgeo
)
458 const struct ioctl_sick_map
*m
;
460 unsigned int checked
;
463 rgeo
->rg_checked
= 0;
465 xfs_group_measure_sickness(rtg_group(rtg
), &sick
, &checked
);
466 for_each_sick_map(rtgroup_map
, m
) {
467 if (checked
& m
->sick_mask
)
468 rgeo
->rg_checked
|= m
->ioctl_mask
;
469 if (sick
& m
->sick_mask
)
470 rgeo
->rg_sick
|= m
->ioctl_mask
;
474 static const struct ioctl_sick_map ino_map
[] = {
475 { XFS_SICK_INO_CORE
, XFS_BS_SICK_INODE
},
476 { XFS_SICK_INO_BMBTD
, XFS_BS_SICK_BMBTD
},
477 { XFS_SICK_INO_BMBTA
, XFS_BS_SICK_BMBTA
},
478 { XFS_SICK_INO_BMBTC
, XFS_BS_SICK_BMBTC
},
479 { XFS_SICK_INO_DIR
, XFS_BS_SICK_DIR
},
480 { XFS_SICK_INO_XATTR
, XFS_BS_SICK_XATTR
},
481 { XFS_SICK_INO_SYMLINK
, XFS_BS_SICK_SYMLINK
},
482 { XFS_SICK_INO_PARENT
, XFS_BS_SICK_PARENT
},
483 { XFS_SICK_INO_BMBTD_ZAPPED
, XFS_BS_SICK_BMBTD
},
484 { XFS_SICK_INO_BMBTA_ZAPPED
, XFS_BS_SICK_BMBTA
},
485 { XFS_SICK_INO_DIR_ZAPPED
, XFS_BS_SICK_DIR
},
486 { XFS_SICK_INO_SYMLINK_ZAPPED
, XFS_BS_SICK_SYMLINK
},
487 { XFS_SICK_INO_DIRTREE
, XFS_BS_SICK_DIRTREE
},
490 /* Fill out bulkstat health info. */
493 struct xfs_inode
*ip
,
494 struct xfs_bulkstat
*bs
)
496 const struct ioctl_sick_map
*m
;
498 unsigned int checked
;
503 xfs_inode_measure_sickness(ip
, &sick
, &checked
);
504 for_each_sick_map(ino_map
, m
) {
505 if (checked
& m
->sick_mask
)
506 bs
->bs_checked
|= m
->ioctl_mask
;
507 if (sick
& m
->sick_mask
)
508 bs
->bs_sick
|= m
->ioctl_mask
;
512 /* Mark a block mapping sick. */
515 struct xfs_inode
*ip
,
522 mask
= XFS_SICK_INO_BMBTD
;
525 mask
= XFS_SICK_INO_BMBTA
;
528 mask
= XFS_SICK_INO_BMBTC
;
535 xfs_inode_mark_sick(ip
, mask
);
538 /* Record observations of btree corruption with the health tracking system. */
541 struct xfs_btree_cur
*cur
)
543 if (xfs_btree_is_bmap(cur
->bc_ops
)) {
544 xfs_bmap_mark_sick(cur
->bc_ino
.ip
, cur
->bc_ino
.whichfork
);
545 /* no health state tracking for ephemeral btrees */
546 } else if (cur
->bc_ops
->type
!= XFS_BTREE_TYPE_MEM
) {
547 ASSERT(cur
->bc_group
);
548 ASSERT(cur
->bc_ops
->sick_mask
);
549 xfs_group_mark_sick(cur
->bc_group
, cur
->bc_ops
->sick_mask
);
554 * Record observations of dir/attr btree corruption with the health tracking
558 xfs_dirattr_mark_sick(
559 struct xfs_inode
*ip
,
566 mask
= XFS_SICK_INO_DIR
;
569 mask
= XFS_SICK_INO_XATTR
;
576 xfs_inode_mark_sick(ip
, mask
);
580 * Record observations of dir/attr btree corruption with the health tracking
585 struct xfs_da_args
*args
)
587 xfs_dirattr_mark_sick(args
->dp
, args
->whichfork
);