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"
19 * Warn about metadata corruption that we detected but haven't fixed, and
20 * make sure we're not sitting on anything that would get in the way of
27 struct xfs_perag
*pag
;
29 unsigned int sick
= 0;
30 unsigned int checked
= 0;
33 if (XFS_FORCED_SHUTDOWN(mp
))
36 /* Measure AG corruption levels. */
37 for_each_perag(mp
, agno
, pag
) {
38 xfs_ag_measure_sickness(pag
, &sick
, &checked
);
40 trace_xfs_ag_unfixed_corruption(mp
, agno
, sick
);
45 /* Measure realtime volume corruption levels. */
46 xfs_rt_measure_sickness(mp
, &sick
, &checked
);
48 trace_xfs_rt_unfixed_corruption(mp
, sick
);
53 * Measure fs corruption and keep the sample around for the warning.
54 * See the note below for why we exempt FS_COUNTERS.
56 xfs_fs_measure_sickness(mp
, &sick
, &checked
);
57 if (sick
& ~XFS_SICK_FS_COUNTERS
) {
58 trace_xfs_fs_unfixed_corruption(mp
, sick
);
64 "Uncorrected metadata errors detected; please run xfs_repair.");
67 * We discovered uncorrected metadata problems at some point
68 * during this filesystem mount and have advised the
69 * administrator to run repair once the unmount completes.
71 * However, we must be careful -- when FSCOUNTERS are flagged
72 * unhealthy, the unmount procedure omits writing the clean
73 * unmount record to the log so that the next mount will run
74 * recovery and recompute the summary counters. In other
75 * words, we leave a dirty log to get the counters fixed.
77 * Unfortunately, xfs_repair cannot recover dirty logs, so if
78 * there were filesystem problems, FSCOUNTERS was flagged, and
79 * the administrator takes our advice to run xfs_repair,
80 * they'll have to zap the log before repairing structures.
81 * We don't really want to encourage this, so we mark the
82 * FSCOUNTERS healthy so that a subsequent repair run won't see
85 if (sick
& XFS_SICK_FS_COUNTERS
)
86 xfs_fs_mark_healthy(mp
, XFS_SICK_FS_COUNTERS
);
90 /* Mark unhealthy per-fs metadata. */
96 ASSERT(!(mask
& ~XFS_SICK_FS_PRIMARY
));
97 trace_xfs_fs_mark_sick(mp
, mask
);
99 spin_lock(&mp
->m_sb_lock
);
100 mp
->m_fs_sick
|= mask
;
101 mp
->m_fs_checked
|= mask
;
102 spin_unlock(&mp
->m_sb_lock
);
105 /* Mark a per-fs metadata healed. */
108 struct xfs_mount
*mp
,
111 ASSERT(!(mask
& ~XFS_SICK_FS_PRIMARY
));
112 trace_xfs_fs_mark_healthy(mp
, mask
);
114 spin_lock(&mp
->m_sb_lock
);
115 mp
->m_fs_sick
&= ~mask
;
116 mp
->m_fs_checked
|= mask
;
117 spin_unlock(&mp
->m_sb_lock
);
120 /* Sample which per-fs metadata are unhealthy. */
122 xfs_fs_measure_sickness(
123 struct xfs_mount
*mp
,
125 unsigned int *checked
)
127 spin_lock(&mp
->m_sb_lock
);
128 *sick
= mp
->m_fs_sick
;
129 *checked
= mp
->m_fs_checked
;
130 spin_unlock(&mp
->m_sb_lock
);
133 /* Mark unhealthy realtime metadata. */
136 struct xfs_mount
*mp
,
139 ASSERT(!(mask
& ~XFS_SICK_RT_PRIMARY
));
140 trace_xfs_rt_mark_sick(mp
, mask
);
142 spin_lock(&mp
->m_sb_lock
);
143 mp
->m_rt_sick
|= mask
;
144 mp
->m_rt_checked
|= mask
;
145 spin_unlock(&mp
->m_sb_lock
);
148 /* Mark a realtime metadata healed. */
151 struct xfs_mount
*mp
,
154 ASSERT(!(mask
& ~XFS_SICK_RT_PRIMARY
));
155 trace_xfs_rt_mark_healthy(mp
, mask
);
157 spin_lock(&mp
->m_sb_lock
);
158 mp
->m_rt_sick
&= ~mask
;
159 mp
->m_rt_checked
|= mask
;
160 spin_unlock(&mp
->m_sb_lock
);
163 /* Sample which realtime metadata are unhealthy. */
165 xfs_rt_measure_sickness(
166 struct xfs_mount
*mp
,
168 unsigned int *checked
)
170 spin_lock(&mp
->m_sb_lock
);
171 *sick
= mp
->m_rt_sick
;
172 *checked
= mp
->m_rt_checked
;
173 spin_unlock(&mp
->m_sb_lock
);
176 /* Mark unhealthy per-ag metadata. */
179 struct xfs_perag
*pag
,
182 ASSERT(!(mask
& ~XFS_SICK_AG_PRIMARY
));
183 trace_xfs_ag_mark_sick(pag
->pag_mount
, pag
->pag_agno
, mask
);
185 spin_lock(&pag
->pag_state_lock
);
186 pag
->pag_sick
|= mask
;
187 pag
->pag_checked
|= mask
;
188 spin_unlock(&pag
->pag_state_lock
);
191 /* Mark per-ag metadata ok. */
194 struct xfs_perag
*pag
,
197 ASSERT(!(mask
& ~XFS_SICK_AG_PRIMARY
));
198 trace_xfs_ag_mark_healthy(pag
->pag_mount
, pag
->pag_agno
, mask
);
200 spin_lock(&pag
->pag_state_lock
);
201 pag
->pag_sick
&= ~mask
;
202 pag
->pag_checked
|= mask
;
203 spin_unlock(&pag
->pag_state_lock
);
206 /* Sample which per-ag metadata are unhealthy. */
208 xfs_ag_measure_sickness(
209 struct xfs_perag
*pag
,
211 unsigned int *checked
)
213 spin_lock(&pag
->pag_state_lock
);
214 *sick
= pag
->pag_sick
;
215 *checked
= pag
->pag_checked
;
216 spin_unlock(&pag
->pag_state_lock
);
219 /* Mark the unhealthy parts of an inode. */
222 struct xfs_inode
*ip
,
225 ASSERT(!(mask
& ~XFS_SICK_INO_PRIMARY
));
226 trace_xfs_inode_mark_sick(ip
, mask
);
228 spin_lock(&ip
->i_flags_lock
);
230 ip
->i_checked
|= mask
;
231 spin_unlock(&ip
->i_flags_lock
);
234 * Keep this inode around so we don't lose the sickness report. Scrub
235 * grabs inodes with DONTCACHE assuming that most inode are ok, which
236 * is not the case here.
238 spin_lock(&VFS_I(ip
)->i_lock
);
239 VFS_I(ip
)->i_state
&= ~I_DONTCACHE
;
240 spin_unlock(&VFS_I(ip
)->i_lock
);
243 /* Mark parts of an inode healed. */
245 xfs_inode_mark_healthy(
246 struct xfs_inode
*ip
,
249 ASSERT(!(mask
& ~XFS_SICK_INO_PRIMARY
));
250 trace_xfs_inode_mark_healthy(ip
, mask
);
252 spin_lock(&ip
->i_flags_lock
);
254 ip
->i_checked
|= mask
;
255 spin_unlock(&ip
->i_flags_lock
);
258 /* Sample which parts of an inode are unhealthy. */
260 xfs_inode_measure_sickness(
261 struct xfs_inode
*ip
,
263 unsigned int *checked
)
265 spin_lock(&ip
->i_flags_lock
);
267 *checked
= ip
->i_checked
;
268 spin_unlock(&ip
->i_flags_lock
);
271 /* Mappings between internal sick masks and ioctl sick masks. */
273 struct ioctl_sick_map
{
274 unsigned int sick_mask
;
275 unsigned int ioctl_mask
;
278 static const struct ioctl_sick_map fs_map
[] = {
279 { XFS_SICK_FS_COUNTERS
, XFS_FSOP_GEOM_SICK_COUNTERS
},
280 { XFS_SICK_FS_UQUOTA
, XFS_FSOP_GEOM_SICK_UQUOTA
},
281 { XFS_SICK_FS_GQUOTA
, XFS_FSOP_GEOM_SICK_GQUOTA
},
282 { XFS_SICK_FS_PQUOTA
, XFS_FSOP_GEOM_SICK_PQUOTA
},
286 static const struct ioctl_sick_map rt_map
[] = {
287 { XFS_SICK_RT_BITMAP
, XFS_FSOP_GEOM_SICK_RT_BITMAP
},
288 { XFS_SICK_RT_SUMMARY
, XFS_FSOP_GEOM_SICK_RT_SUMMARY
},
294 struct xfs_fsop_geom
*geo
,
296 unsigned int checked
,
297 const struct ioctl_sick_map
*m
)
299 if (checked
& m
->sick_mask
)
300 geo
->checked
|= m
->ioctl_mask
;
301 if (sick
& m
->sick_mask
)
302 geo
->sick
|= m
->ioctl_mask
;
305 /* Fill out fs geometry health info. */
307 xfs_fsop_geom_health(
308 struct xfs_mount
*mp
,
309 struct xfs_fsop_geom
*geo
)
311 const struct ioctl_sick_map
*m
;
313 unsigned int checked
;
318 xfs_fs_measure_sickness(mp
, &sick
, &checked
);
319 for (m
= fs_map
; m
->sick_mask
; m
++)
320 xfgeo_health_tick(geo
, sick
, checked
, m
);
322 xfs_rt_measure_sickness(mp
, &sick
, &checked
);
323 for (m
= rt_map
; m
->sick_mask
; m
++)
324 xfgeo_health_tick(geo
, sick
, checked
, m
);
327 static const struct ioctl_sick_map ag_map
[] = {
328 { XFS_SICK_AG_SB
, XFS_AG_GEOM_SICK_SB
},
329 { XFS_SICK_AG_AGF
, XFS_AG_GEOM_SICK_AGF
},
330 { XFS_SICK_AG_AGFL
, XFS_AG_GEOM_SICK_AGFL
},
331 { XFS_SICK_AG_AGI
, XFS_AG_GEOM_SICK_AGI
},
332 { XFS_SICK_AG_BNOBT
, XFS_AG_GEOM_SICK_BNOBT
},
333 { XFS_SICK_AG_CNTBT
, XFS_AG_GEOM_SICK_CNTBT
},
334 { XFS_SICK_AG_INOBT
, XFS_AG_GEOM_SICK_INOBT
},
335 { XFS_SICK_AG_FINOBT
, XFS_AG_GEOM_SICK_FINOBT
},
336 { XFS_SICK_AG_RMAPBT
, XFS_AG_GEOM_SICK_RMAPBT
},
337 { XFS_SICK_AG_REFCNTBT
, XFS_AG_GEOM_SICK_REFCNTBT
},
341 /* Fill out ag geometry health info. */
344 struct xfs_perag
*pag
,
345 struct xfs_ag_geometry
*ageo
)
347 const struct ioctl_sick_map
*m
;
349 unsigned int checked
;
352 ageo
->ag_checked
= 0;
354 xfs_ag_measure_sickness(pag
, &sick
, &checked
);
355 for (m
= ag_map
; m
->sick_mask
; m
++) {
356 if (checked
& m
->sick_mask
)
357 ageo
->ag_checked
|= m
->ioctl_mask
;
358 if (sick
& m
->sick_mask
)
359 ageo
->ag_sick
|= m
->ioctl_mask
;
363 static const struct ioctl_sick_map ino_map
[] = {
364 { XFS_SICK_INO_CORE
, XFS_BS_SICK_INODE
},
365 { XFS_SICK_INO_BMBTD
, XFS_BS_SICK_BMBTD
},
366 { XFS_SICK_INO_BMBTA
, XFS_BS_SICK_BMBTA
},
367 { XFS_SICK_INO_BMBTC
, XFS_BS_SICK_BMBTC
},
368 { XFS_SICK_INO_DIR
, XFS_BS_SICK_DIR
},
369 { XFS_SICK_INO_XATTR
, XFS_BS_SICK_XATTR
},
370 { XFS_SICK_INO_SYMLINK
, XFS_BS_SICK_SYMLINK
},
371 { XFS_SICK_INO_PARENT
, XFS_BS_SICK_PARENT
},
375 /* Fill out bulkstat health info. */
378 struct xfs_inode
*ip
,
379 struct xfs_bulkstat
*bs
)
381 const struct ioctl_sick_map
*m
;
383 unsigned int checked
;
388 xfs_inode_measure_sickness(ip
, &sick
, &checked
);
389 for (m
= ino_map
; m
->sick_mask
; m
++) {
390 if (checked
& m
->sick_mask
)
391 bs
->bs_checked
|= m
->ioctl_mask
;
392 if (sick
& m
->sick_mask
)
393 bs
->bs_sick
|= m
->ioctl_mask
;