xref: /openbmc/linux/fs/xfs/xfs_health.c (revision 75c8c50f)
16772c1f1SDarrick J. Wong // SPDX-License-Identifier: GPL-2.0+
26772c1f1SDarrick J. Wong /*
36772c1f1SDarrick J. Wong  * Copyright (C) 2019 Oracle.  All Rights Reserved.
46772c1f1SDarrick J. Wong  * Author: Darrick J. Wong <darrick.wong@oracle.com>
56772c1f1SDarrick J. Wong  */
66772c1f1SDarrick J. Wong #include "xfs.h"
76772c1f1SDarrick J. Wong #include "xfs_fs.h"
86772c1f1SDarrick J. Wong #include "xfs_shared.h"
96772c1f1SDarrick J. Wong #include "xfs_format.h"
106772c1f1SDarrick J. Wong #include "xfs_log_format.h"
116772c1f1SDarrick J. Wong #include "xfs_trans_resv.h"
126772c1f1SDarrick J. Wong #include "xfs_mount.h"
136772c1f1SDarrick J. Wong #include "xfs_inode.h"
146772c1f1SDarrick J. Wong #include "xfs_trace.h"
156772c1f1SDarrick J. Wong #include "xfs_health.h"
169bbafc71SDave Chinner #include "xfs_ag.h"
176772c1f1SDarrick J. Wong 
18519841c2SDarrick J. Wong /*
19519841c2SDarrick J. Wong  * Warn about metadata corruption that we detected but haven't fixed, and
20519841c2SDarrick J. Wong  * make sure we're not sitting on anything that would get in the way of
21519841c2SDarrick J. Wong  * recovery.
22519841c2SDarrick J. Wong  */
23519841c2SDarrick J. Wong void
xfs_health_unmount(struct xfs_mount * mp)24519841c2SDarrick J. Wong xfs_health_unmount(
25519841c2SDarrick J. Wong 	struct xfs_mount	*mp)
26519841c2SDarrick J. Wong {
27519841c2SDarrick J. Wong 	struct xfs_perag	*pag;
28519841c2SDarrick J. Wong 	xfs_agnumber_t		agno;
29519841c2SDarrick J. Wong 	unsigned int		sick = 0;
30519841c2SDarrick J. Wong 	unsigned int		checked = 0;
31519841c2SDarrick J. Wong 	bool			warn = false;
32519841c2SDarrick J. Wong 
33*75c8c50fSDave Chinner 	if (xfs_is_shutdown(mp))
34519841c2SDarrick J. Wong 		return;
35519841c2SDarrick J. Wong 
36519841c2SDarrick J. Wong 	/* Measure AG corruption levels. */
37f250eedcSDave Chinner 	for_each_perag(mp, agno, pag) {
38519841c2SDarrick J. Wong 		xfs_ag_measure_sickness(pag, &sick, &checked);
39519841c2SDarrick J. Wong 		if (sick) {
40519841c2SDarrick J. Wong 			trace_xfs_ag_unfixed_corruption(mp, agno, sick);
41519841c2SDarrick J. Wong 			warn = true;
42519841c2SDarrick J. Wong 		}
43519841c2SDarrick J. Wong 	}
44519841c2SDarrick J. Wong 
45519841c2SDarrick J. Wong 	/* Measure realtime volume corruption levels. */
46519841c2SDarrick J. Wong 	xfs_rt_measure_sickness(mp, &sick, &checked);
47519841c2SDarrick J. Wong 	if (sick) {
48519841c2SDarrick J. Wong 		trace_xfs_rt_unfixed_corruption(mp, sick);
49519841c2SDarrick J. Wong 		warn = true;
50519841c2SDarrick J. Wong 	}
51519841c2SDarrick J. Wong 
52519841c2SDarrick J. Wong 	/*
53519841c2SDarrick J. Wong 	 * Measure fs corruption and keep the sample around for the warning.
54519841c2SDarrick J. Wong 	 * See the note below for why we exempt FS_COUNTERS.
55519841c2SDarrick J. Wong 	 */
56519841c2SDarrick J. Wong 	xfs_fs_measure_sickness(mp, &sick, &checked);
57519841c2SDarrick J. Wong 	if (sick & ~XFS_SICK_FS_COUNTERS) {
58519841c2SDarrick J. Wong 		trace_xfs_fs_unfixed_corruption(mp, sick);
59519841c2SDarrick J. Wong 		warn = true;
60519841c2SDarrick J. Wong 	}
61519841c2SDarrick J. Wong 
62519841c2SDarrick J. Wong 	if (warn) {
63519841c2SDarrick J. Wong 		xfs_warn(mp,
64519841c2SDarrick J. Wong "Uncorrected metadata errors detected; please run xfs_repair.");
65519841c2SDarrick J. Wong 
66519841c2SDarrick J. Wong 		/*
67519841c2SDarrick J. Wong 		 * We discovered uncorrected metadata problems at some point
68519841c2SDarrick J. Wong 		 * during this filesystem mount and have advised the
69519841c2SDarrick J. Wong 		 * administrator to run repair once the unmount completes.
70519841c2SDarrick J. Wong 		 *
71519841c2SDarrick J. Wong 		 * However, we must be careful -- when FSCOUNTERS are flagged
72519841c2SDarrick J. Wong 		 * unhealthy, the unmount procedure omits writing the clean
73519841c2SDarrick J. Wong 		 * unmount record to the log so that the next mount will run
74519841c2SDarrick J. Wong 		 * recovery and recompute the summary counters.  In other
75519841c2SDarrick J. Wong 		 * words, we leave a dirty log to get the counters fixed.
76519841c2SDarrick J. Wong 		 *
77519841c2SDarrick J. Wong 		 * Unfortunately, xfs_repair cannot recover dirty logs, so if
78519841c2SDarrick J. Wong 		 * there were filesystem problems, FSCOUNTERS was flagged, and
79519841c2SDarrick J. Wong 		 * the administrator takes our advice to run xfs_repair,
80519841c2SDarrick J. Wong 		 * they'll have to zap the log before repairing structures.
81519841c2SDarrick J. Wong 		 * We don't really want to encourage this, so we mark the
82519841c2SDarrick J. Wong 		 * FSCOUNTERS healthy so that a subsequent repair run won't see
83519841c2SDarrick J. Wong 		 * a dirty log.
84519841c2SDarrick J. Wong 		 */
85519841c2SDarrick J. Wong 		if (sick & XFS_SICK_FS_COUNTERS)
86519841c2SDarrick J. Wong 			xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS);
87519841c2SDarrick J. Wong 	}
88519841c2SDarrick J. Wong }
89519841c2SDarrick J. Wong 
906772c1f1SDarrick J. Wong /* Mark unhealthy per-fs metadata. */
916772c1f1SDarrick J. Wong void
xfs_fs_mark_sick(struct xfs_mount * mp,unsigned int mask)926772c1f1SDarrick J. Wong xfs_fs_mark_sick(
936772c1f1SDarrick J. Wong 	struct xfs_mount	*mp,
946772c1f1SDarrick J. Wong 	unsigned int		mask)
956772c1f1SDarrick J. Wong {
966772c1f1SDarrick J. Wong 	ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
976772c1f1SDarrick J. Wong 	trace_xfs_fs_mark_sick(mp, mask);
986772c1f1SDarrick J. Wong 
996772c1f1SDarrick J. Wong 	spin_lock(&mp->m_sb_lock);
1006772c1f1SDarrick J. Wong 	mp->m_fs_sick |= mask;
1016772c1f1SDarrick J. Wong 	mp->m_fs_checked |= mask;
1026772c1f1SDarrick J. Wong 	spin_unlock(&mp->m_sb_lock);
1036772c1f1SDarrick J. Wong }
1046772c1f1SDarrick J. Wong 
1056772c1f1SDarrick J. Wong /* Mark a per-fs metadata healed. */
1066772c1f1SDarrick J. Wong void
xfs_fs_mark_healthy(struct xfs_mount * mp,unsigned int mask)1076772c1f1SDarrick J. Wong xfs_fs_mark_healthy(
1086772c1f1SDarrick J. Wong 	struct xfs_mount	*mp,
1096772c1f1SDarrick J. Wong 	unsigned int		mask)
1106772c1f1SDarrick J. Wong {
1116772c1f1SDarrick J. Wong 	ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
1126772c1f1SDarrick J. Wong 	trace_xfs_fs_mark_healthy(mp, mask);
1136772c1f1SDarrick J. Wong 
1146772c1f1SDarrick J. Wong 	spin_lock(&mp->m_sb_lock);
1156772c1f1SDarrick J. Wong 	mp->m_fs_sick &= ~mask;
1166772c1f1SDarrick J. Wong 	mp->m_fs_checked |= mask;
1176772c1f1SDarrick J. Wong 	spin_unlock(&mp->m_sb_lock);
1186772c1f1SDarrick J. Wong }
1196772c1f1SDarrick J. Wong 
1206772c1f1SDarrick J. Wong /* Sample which per-fs metadata are unhealthy. */
1216772c1f1SDarrick J. Wong void
xfs_fs_measure_sickness(struct xfs_mount * mp,unsigned int * sick,unsigned int * checked)1226772c1f1SDarrick J. Wong xfs_fs_measure_sickness(
1236772c1f1SDarrick J. Wong 	struct xfs_mount	*mp,
1246772c1f1SDarrick J. Wong 	unsigned int		*sick,
1256772c1f1SDarrick J. Wong 	unsigned int		*checked)
1266772c1f1SDarrick J. Wong {
1276772c1f1SDarrick J. Wong 	spin_lock(&mp->m_sb_lock);
1286772c1f1SDarrick J. Wong 	*sick = mp->m_fs_sick;
1296772c1f1SDarrick J. Wong 	*checked = mp->m_fs_checked;
1306772c1f1SDarrick J. Wong 	spin_unlock(&mp->m_sb_lock);
1316772c1f1SDarrick J. Wong }
1326772c1f1SDarrick J. Wong 
1336772c1f1SDarrick J. Wong /* Mark unhealthy realtime metadata. */
1346772c1f1SDarrick J. Wong void
xfs_rt_mark_sick(struct xfs_mount * mp,unsigned int mask)1356772c1f1SDarrick J. Wong xfs_rt_mark_sick(
1366772c1f1SDarrick J. Wong 	struct xfs_mount	*mp,
1376772c1f1SDarrick J. Wong 	unsigned int		mask)
1386772c1f1SDarrick J. Wong {
1396772c1f1SDarrick J. Wong 	ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
1406772c1f1SDarrick J. Wong 	trace_xfs_rt_mark_sick(mp, mask);
1416772c1f1SDarrick J. Wong 
1426772c1f1SDarrick J. Wong 	spin_lock(&mp->m_sb_lock);
1436772c1f1SDarrick J. Wong 	mp->m_rt_sick |= mask;
1446772c1f1SDarrick J. Wong 	mp->m_rt_checked |= mask;
1456772c1f1SDarrick J. Wong 	spin_unlock(&mp->m_sb_lock);
1466772c1f1SDarrick J. Wong }
1476772c1f1SDarrick J. Wong 
1486772c1f1SDarrick J. Wong /* Mark a realtime metadata healed. */
1496772c1f1SDarrick J. Wong void
xfs_rt_mark_healthy(struct xfs_mount * mp,unsigned int mask)1506772c1f1SDarrick J. Wong xfs_rt_mark_healthy(
1516772c1f1SDarrick J. Wong 	struct xfs_mount	*mp,
1526772c1f1SDarrick J. Wong 	unsigned int		mask)
1536772c1f1SDarrick J. Wong {
1546772c1f1SDarrick J. Wong 	ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
1556772c1f1SDarrick J. Wong 	trace_xfs_rt_mark_healthy(mp, mask);
1566772c1f1SDarrick J. Wong 
1576772c1f1SDarrick J. Wong 	spin_lock(&mp->m_sb_lock);
1586772c1f1SDarrick J. Wong 	mp->m_rt_sick &= ~mask;
1596772c1f1SDarrick J. Wong 	mp->m_rt_checked |= mask;
1606772c1f1SDarrick J. Wong 	spin_unlock(&mp->m_sb_lock);
1616772c1f1SDarrick J. Wong }
1626772c1f1SDarrick J. Wong 
1636772c1f1SDarrick J. Wong /* Sample which realtime metadata are unhealthy. */
1646772c1f1SDarrick J. Wong void
xfs_rt_measure_sickness(struct xfs_mount * mp,unsigned int * sick,unsigned int * checked)1656772c1f1SDarrick J. Wong xfs_rt_measure_sickness(
1666772c1f1SDarrick J. Wong 	struct xfs_mount	*mp,
1676772c1f1SDarrick J. Wong 	unsigned int		*sick,
1686772c1f1SDarrick J. Wong 	unsigned int		*checked)
1696772c1f1SDarrick J. Wong {
1706772c1f1SDarrick J. Wong 	spin_lock(&mp->m_sb_lock);
1716772c1f1SDarrick J. Wong 	*sick = mp->m_rt_sick;
1726772c1f1SDarrick J. Wong 	*checked = mp->m_rt_checked;
1736772c1f1SDarrick J. Wong 	spin_unlock(&mp->m_sb_lock);
1746772c1f1SDarrick J. Wong }
1756772c1f1SDarrick J. Wong 
1766772c1f1SDarrick J. Wong /* Mark unhealthy per-ag metadata. */
1776772c1f1SDarrick J. Wong void
xfs_ag_mark_sick(struct xfs_perag * pag,unsigned int mask)1786772c1f1SDarrick J. Wong xfs_ag_mark_sick(
1796772c1f1SDarrick J. Wong 	struct xfs_perag	*pag,
1806772c1f1SDarrick J. Wong 	unsigned int		mask)
1816772c1f1SDarrick J. Wong {
1826772c1f1SDarrick J. Wong 	ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
1836772c1f1SDarrick J. Wong 	trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask);
1846772c1f1SDarrick J. Wong 
1856772c1f1SDarrick J. Wong 	spin_lock(&pag->pag_state_lock);
1866772c1f1SDarrick J. Wong 	pag->pag_sick |= mask;
1876772c1f1SDarrick J. Wong 	pag->pag_checked |= mask;
1886772c1f1SDarrick J. Wong 	spin_unlock(&pag->pag_state_lock);
1896772c1f1SDarrick J. Wong }
1906772c1f1SDarrick J. Wong 
1916772c1f1SDarrick J. Wong /* Mark per-ag metadata ok. */
1926772c1f1SDarrick J. Wong void
xfs_ag_mark_healthy(struct xfs_perag * pag,unsigned int mask)1936772c1f1SDarrick J. Wong xfs_ag_mark_healthy(
1946772c1f1SDarrick J. Wong 	struct xfs_perag	*pag,
1956772c1f1SDarrick J. Wong 	unsigned int		mask)
1966772c1f1SDarrick J. Wong {
1976772c1f1SDarrick J. Wong 	ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
1986772c1f1SDarrick J. Wong 	trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask);
1996772c1f1SDarrick J. Wong 
2006772c1f1SDarrick J. Wong 	spin_lock(&pag->pag_state_lock);
2016772c1f1SDarrick J. Wong 	pag->pag_sick &= ~mask;
2026772c1f1SDarrick J. Wong 	pag->pag_checked |= mask;
2036772c1f1SDarrick J. Wong 	spin_unlock(&pag->pag_state_lock);
2046772c1f1SDarrick J. Wong }
2056772c1f1SDarrick J. Wong 
2066772c1f1SDarrick J. Wong /* Sample which per-ag metadata are unhealthy. */
2076772c1f1SDarrick J. Wong void
xfs_ag_measure_sickness(struct xfs_perag * pag,unsigned int * sick,unsigned int * checked)2086772c1f1SDarrick J. Wong xfs_ag_measure_sickness(
2096772c1f1SDarrick J. Wong 	struct xfs_perag	*pag,
2106772c1f1SDarrick J. Wong 	unsigned int		*sick,
2116772c1f1SDarrick J. Wong 	unsigned int		*checked)
2126772c1f1SDarrick J. Wong {
2136772c1f1SDarrick J. Wong 	spin_lock(&pag->pag_state_lock);
2146772c1f1SDarrick J. Wong 	*sick = pag->pag_sick;
2156772c1f1SDarrick J. Wong 	*checked = pag->pag_checked;
2166772c1f1SDarrick J. Wong 	spin_unlock(&pag->pag_state_lock);
2176772c1f1SDarrick J. Wong }
2186772c1f1SDarrick J. Wong 
2196772c1f1SDarrick J. Wong /* Mark the unhealthy parts of an inode. */
2206772c1f1SDarrick J. Wong void
xfs_inode_mark_sick(struct xfs_inode * ip,unsigned int mask)2216772c1f1SDarrick J. Wong xfs_inode_mark_sick(
2226772c1f1SDarrick J. Wong 	struct xfs_inode	*ip,
2236772c1f1SDarrick J. Wong 	unsigned int		mask)
2246772c1f1SDarrick J. Wong {
2256772c1f1SDarrick J. Wong 	ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
2266772c1f1SDarrick J. Wong 	trace_xfs_inode_mark_sick(ip, mask);
2276772c1f1SDarrick J. Wong 
2286772c1f1SDarrick J. Wong 	spin_lock(&ip->i_flags_lock);
2296772c1f1SDarrick J. Wong 	ip->i_sick |= mask;
2306772c1f1SDarrick J. Wong 	ip->i_checked |= mask;
2316772c1f1SDarrick J. Wong 	spin_unlock(&ip->i_flags_lock);
2327975e465SDarrick J. Wong 
2337975e465SDarrick J. Wong 	/*
2347975e465SDarrick J. Wong 	 * Keep this inode around so we don't lose the sickness report.  Scrub
2357975e465SDarrick J. Wong 	 * grabs inodes with DONTCACHE assuming that most inode are ok, which
2367975e465SDarrick J. Wong 	 * is not the case here.
2377975e465SDarrick J. Wong 	 */
2387975e465SDarrick J. Wong 	spin_lock(&VFS_I(ip)->i_lock);
2397975e465SDarrick J. Wong 	VFS_I(ip)->i_state &= ~I_DONTCACHE;
2407975e465SDarrick J. Wong 	spin_unlock(&VFS_I(ip)->i_lock);
2416772c1f1SDarrick J. Wong }
2426772c1f1SDarrick J. Wong 
2436772c1f1SDarrick J. Wong /* Mark parts of an inode healed. */
2446772c1f1SDarrick J. Wong void
xfs_inode_mark_healthy(struct xfs_inode * ip,unsigned int mask)2456772c1f1SDarrick J. Wong xfs_inode_mark_healthy(
2466772c1f1SDarrick J. Wong 	struct xfs_inode	*ip,
2476772c1f1SDarrick J. Wong 	unsigned int		mask)
2486772c1f1SDarrick J. Wong {
2496772c1f1SDarrick J. Wong 	ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
2506772c1f1SDarrick J. Wong 	trace_xfs_inode_mark_healthy(ip, mask);
2516772c1f1SDarrick J. Wong 
2526772c1f1SDarrick J. Wong 	spin_lock(&ip->i_flags_lock);
2536772c1f1SDarrick J. Wong 	ip->i_sick &= ~mask;
2546772c1f1SDarrick J. Wong 	ip->i_checked |= mask;
2556772c1f1SDarrick J. Wong 	spin_unlock(&ip->i_flags_lock);
2566772c1f1SDarrick J. Wong }
2576772c1f1SDarrick J. Wong 
2586772c1f1SDarrick J. Wong /* Sample which parts of an inode are unhealthy. */
2596772c1f1SDarrick J. Wong void
xfs_inode_measure_sickness(struct xfs_inode * ip,unsigned int * sick,unsigned int * checked)2606772c1f1SDarrick J. Wong xfs_inode_measure_sickness(
2616772c1f1SDarrick J. Wong 	struct xfs_inode	*ip,
2626772c1f1SDarrick J. Wong 	unsigned int		*sick,
2636772c1f1SDarrick J. Wong 	unsigned int		*checked)
2646772c1f1SDarrick J. Wong {
2656772c1f1SDarrick J. Wong 	spin_lock(&ip->i_flags_lock);
2666772c1f1SDarrick J. Wong 	*sick = ip->i_sick;
2676772c1f1SDarrick J. Wong 	*checked = ip->i_checked;
2686772c1f1SDarrick J. Wong 	spin_unlock(&ip->i_flags_lock);
2696772c1f1SDarrick J. Wong }
270c23232d4SDarrick J. Wong 
271c23232d4SDarrick J. Wong /* Mappings between internal sick masks and ioctl sick masks. */
272c23232d4SDarrick J. Wong 
273c23232d4SDarrick J. Wong struct ioctl_sick_map {
274c23232d4SDarrick J. Wong 	unsigned int		sick_mask;
275c23232d4SDarrick J. Wong 	unsigned int		ioctl_mask;
276c23232d4SDarrick J. Wong };
277c23232d4SDarrick J. Wong 
278c23232d4SDarrick J. Wong static const struct ioctl_sick_map fs_map[] = {
279c23232d4SDarrick J. Wong 	{ XFS_SICK_FS_COUNTERS,	XFS_FSOP_GEOM_SICK_COUNTERS},
280c23232d4SDarrick J. Wong 	{ XFS_SICK_FS_UQUOTA,	XFS_FSOP_GEOM_SICK_UQUOTA },
281c23232d4SDarrick J. Wong 	{ XFS_SICK_FS_GQUOTA,	XFS_FSOP_GEOM_SICK_GQUOTA },
282c23232d4SDarrick J. Wong 	{ XFS_SICK_FS_PQUOTA,	XFS_FSOP_GEOM_SICK_PQUOTA },
283c23232d4SDarrick J. Wong 	{ 0, 0 },
284c23232d4SDarrick J. Wong };
285c23232d4SDarrick J. Wong 
286c23232d4SDarrick J. Wong static const struct ioctl_sick_map rt_map[] = {
287c23232d4SDarrick J. Wong 	{ XFS_SICK_RT_BITMAP,	XFS_FSOP_GEOM_SICK_RT_BITMAP },
288c23232d4SDarrick J. Wong 	{ XFS_SICK_RT_SUMMARY,	XFS_FSOP_GEOM_SICK_RT_SUMMARY },
289c23232d4SDarrick J. Wong 	{ 0, 0 },
290c23232d4SDarrick J. Wong };
291c23232d4SDarrick J. Wong 
292c23232d4SDarrick J. Wong static inline void
xfgeo_health_tick(struct xfs_fsop_geom * geo,unsigned int sick,unsigned int checked,const struct ioctl_sick_map * m)293c23232d4SDarrick J. Wong xfgeo_health_tick(
294c23232d4SDarrick J. Wong 	struct xfs_fsop_geom		*geo,
295c23232d4SDarrick J. Wong 	unsigned int			sick,
296c23232d4SDarrick J. Wong 	unsigned int			checked,
297c23232d4SDarrick J. Wong 	const struct ioctl_sick_map	*m)
298c23232d4SDarrick J. Wong {
299c23232d4SDarrick J. Wong 	if (checked & m->sick_mask)
300c23232d4SDarrick J. Wong 		geo->checked |= m->ioctl_mask;
301c23232d4SDarrick J. Wong 	if (sick & m->sick_mask)
302c23232d4SDarrick J. Wong 		geo->sick |= m->ioctl_mask;
303c23232d4SDarrick J. Wong }
304c23232d4SDarrick J. Wong 
305c23232d4SDarrick J. Wong /* Fill out fs geometry health info. */
306c23232d4SDarrick J. Wong void
xfs_fsop_geom_health(struct xfs_mount * mp,struct xfs_fsop_geom * geo)307c23232d4SDarrick J. Wong xfs_fsop_geom_health(
308c23232d4SDarrick J. Wong 	struct xfs_mount		*mp,
309c23232d4SDarrick J. Wong 	struct xfs_fsop_geom		*geo)
310c23232d4SDarrick J. Wong {
311c23232d4SDarrick J. Wong 	const struct ioctl_sick_map	*m;
312c23232d4SDarrick J. Wong 	unsigned int			sick;
313c23232d4SDarrick J. Wong 	unsigned int			checked;
314c23232d4SDarrick J. Wong 
315c23232d4SDarrick J. Wong 	geo->sick = 0;
316c23232d4SDarrick J. Wong 	geo->checked = 0;
317c23232d4SDarrick J. Wong 
318c23232d4SDarrick J. Wong 	xfs_fs_measure_sickness(mp, &sick, &checked);
319c23232d4SDarrick J. Wong 	for (m = fs_map; m->sick_mask; m++)
320c23232d4SDarrick J. Wong 		xfgeo_health_tick(geo, sick, checked, m);
321c23232d4SDarrick J. Wong 
322c23232d4SDarrick J. Wong 	xfs_rt_measure_sickness(mp, &sick, &checked);
323c23232d4SDarrick J. Wong 	for (m = rt_map; m->sick_mask; m++)
324c23232d4SDarrick J. Wong 		xfgeo_health_tick(geo, sick, checked, m);
325c23232d4SDarrick J. Wong }
3261302c6a2SDarrick J. Wong 
3271302c6a2SDarrick J. Wong static const struct ioctl_sick_map ag_map[] = {
3281302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_SB,	XFS_AG_GEOM_SICK_SB },
3291302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_AGF,	XFS_AG_GEOM_SICK_AGF },
3301302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_AGFL,	XFS_AG_GEOM_SICK_AGFL },
3311302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_AGI,	XFS_AG_GEOM_SICK_AGI },
3321302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_BNOBT,	XFS_AG_GEOM_SICK_BNOBT },
3331302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_CNTBT,	XFS_AG_GEOM_SICK_CNTBT },
3341302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_INOBT,	XFS_AG_GEOM_SICK_INOBT },
3351302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_FINOBT,	XFS_AG_GEOM_SICK_FINOBT },
3361302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_RMAPBT,	XFS_AG_GEOM_SICK_RMAPBT },
3371302c6a2SDarrick J. Wong 	{ XFS_SICK_AG_REFCNTBT,	XFS_AG_GEOM_SICK_REFCNTBT },
3381302c6a2SDarrick J. Wong 	{ 0, 0 },
3391302c6a2SDarrick J. Wong };
3401302c6a2SDarrick J. Wong 
3411302c6a2SDarrick J. Wong /* Fill out ag geometry health info. */
3421302c6a2SDarrick J. Wong void
xfs_ag_geom_health(struct xfs_perag * pag,struct xfs_ag_geometry * ageo)3431302c6a2SDarrick J. Wong xfs_ag_geom_health(
3441302c6a2SDarrick J. Wong 	struct xfs_perag		*pag,
3451302c6a2SDarrick J. Wong 	struct xfs_ag_geometry		*ageo)
3461302c6a2SDarrick J. Wong {
3471302c6a2SDarrick J. Wong 	const struct ioctl_sick_map	*m;
3481302c6a2SDarrick J. Wong 	unsigned int			sick;
3491302c6a2SDarrick J. Wong 	unsigned int			checked;
3501302c6a2SDarrick J. Wong 
3511302c6a2SDarrick J. Wong 	ageo->ag_sick = 0;
3521302c6a2SDarrick J. Wong 	ageo->ag_checked = 0;
3531302c6a2SDarrick J. Wong 
3541302c6a2SDarrick J. Wong 	xfs_ag_measure_sickness(pag, &sick, &checked);
3551302c6a2SDarrick J. Wong 	for (m = ag_map; m->sick_mask; m++) {
3561302c6a2SDarrick J. Wong 		if (checked & m->sick_mask)
3571302c6a2SDarrick J. Wong 			ageo->ag_checked |= m->ioctl_mask;
3581302c6a2SDarrick J. Wong 		if (sick & m->sick_mask)
3591302c6a2SDarrick J. Wong 			ageo->ag_sick |= m->ioctl_mask;
3601302c6a2SDarrick J. Wong 	}
3611302c6a2SDarrick J. Wong }
36289d139d5SDarrick J. Wong 
36389d139d5SDarrick J. Wong static const struct ioctl_sick_map ino_map[] = {
36489d139d5SDarrick J. Wong 	{ XFS_SICK_INO_CORE,	XFS_BS_SICK_INODE },
36589d139d5SDarrick J. Wong 	{ XFS_SICK_INO_BMBTD,	XFS_BS_SICK_BMBTD },
36689d139d5SDarrick J. Wong 	{ XFS_SICK_INO_BMBTA,	XFS_BS_SICK_BMBTA },
36789d139d5SDarrick J. Wong 	{ XFS_SICK_INO_BMBTC,	XFS_BS_SICK_BMBTC },
36889d139d5SDarrick J. Wong 	{ XFS_SICK_INO_DIR,	XFS_BS_SICK_DIR },
36989d139d5SDarrick J. Wong 	{ XFS_SICK_INO_XATTR,	XFS_BS_SICK_XATTR },
37089d139d5SDarrick J. Wong 	{ XFS_SICK_INO_SYMLINK,	XFS_BS_SICK_SYMLINK },
37189d139d5SDarrick J. Wong 	{ XFS_SICK_INO_PARENT,	XFS_BS_SICK_PARENT },
37289d139d5SDarrick J. Wong 	{ 0, 0 },
37389d139d5SDarrick J. Wong };
37489d139d5SDarrick J. Wong 
37589d139d5SDarrick J. Wong /* Fill out bulkstat health info. */
37689d139d5SDarrick J. Wong void
xfs_bulkstat_health(struct xfs_inode * ip,struct xfs_bulkstat * bs)37789d139d5SDarrick J. Wong xfs_bulkstat_health(
37889d139d5SDarrick J. Wong 	struct xfs_inode		*ip,
3797035f972SDarrick J. Wong 	struct xfs_bulkstat		*bs)
38089d139d5SDarrick J. Wong {
38189d139d5SDarrick J. Wong 	const struct ioctl_sick_map	*m;
38289d139d5SDarrick J. Wong 	unsigned int			sick;
38389d139d5SDarrick J. Wong 	unsigned int			checked;
38489d139d5SDarrick J. Wong 
38589d139d5SDarrick J. Wong 	bs->bs_sick = 0;
38689d139d5SDarrick J. Wong 	bs->bs_checked = 0;
38789d139d5SDarrick J. Wong 
38889d139d5SDarrick J. Wong 	xfs_inode_measure_sickness(ip, &sick, &checked);
38989d139d5SDarrick J. Wong 	for (m = ino_map; m->sick_mask; m++) {
39089d139d5SDarrick J. Wong 		if (checked & m->sick_mask)
39189d139d5SDarrick J. Wong 			bs->bs_checked |= m->ioctl_mask;
39289d139d5SDarrick J. Wong 		if (sick & m->sick_mask)
39389d139d5SDarrick J. Wong 			bs->bs_sick |= m->ioctl_mask;
39489d139d5SDarrick J. Wong 	}
39589d139d5SDarrick J. Wong }
396