162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2019 Oracle.  All Rights Reserved.
462306a36Sopenharmony_ci * Author: Darrick J. Wong <darrick.wong@oracle.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#include "xfs.h"
762306a36Sopenharmony_ci#include "xfs_fs.h"
862306a36Sopenharmony_ci#include "xfs_shared.h"
962306a36Sopenharmony_ci#include "xfs_format.h"
1062306a36Sopenharmony_ci#include "xfs_log_format.h"
1162306a36Sopenharmony_ci#include "xfs_trans_resv.h"
1262306a36Sopenharmony_ci#include "xfs_mount.h"
1362306a36Sopenharmony_ci#include "xfs_inode.h"
1462306a36Sopenharmony_ci#include "xfs_trace.h"
1562306a36Sopenharmony_ci#include "xfs_health.h"
1662306a36Sopenharmony_ci#include "xfs_ag.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/*
1962306a36Sopenharmony_ci * Warn about metadata corruption that we detected but haven't fixed, and
2062306a36Sopenharmony_ci * make sure we're not sitting on anything that would get in the way of
2162306a36Sopenharmony_ci * recovery.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_civoid
2462306a36Sopenharmony_cixfs_health_unmount(
2562306a36Sopenharmony_ci	struct xfs_mount	*mp)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	struct xfs_perag	*pag;
2862306a36Sopenharmony_ci	xfs_agnumber_t		agno;
2962306a36Sopenharmony_ci	unsigned int		sick = 0;
3062306a36Sopenharmony_ci	unsigned int		checked = 0;
3162306a36Sopenharmony_ci	bool			warn = false;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	if (xfs_is_shutdown(mp))
3462306a36Sopenharmony_ci		return;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	/* Measure AG corruption levels. */
3762306a36Sopenharmony_ci	for_each_perag(mp, agno, pag) {
3862306a36Sopenharmony_ci		xfs_ag_measure_sickness(pag, &sick, &checked);
3962306a36Sopenharmony_ci		if (sick) {
4062306a36Sopenharmony_ci			trace_xfs_ag_unfixed_corruption(mp, agno, sick);
4162306a36Sopenharmony_ci			warn = true;
4262306a36Sopenharmony_ci		}
4362306a36Sopenharmony_ci	}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	/* Measure realtime volume corruption levels. */
4662306a36Sopenharmony_ci	xfs_rt_measure_sickness(mp, &sick, &checked);
4762306a36Sopenharmony_ci	if (sick) {
4862306a36Sopenharmony_ci		trace_xfs_rt_unfixed_corruption(mp, sick);
4962306a36Sopenharmony_ci		warn = true;
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/*
5362306a36Sopenharmony_ci	 * Measure fs corruption and keep the sample around for the warning.
5462306a36Sopenharmony_ci	 * See the note below for why we exempt FS_COUNTERS.
5562306a36Sopenharmony_ci	 */
5662306a36Sopenharmony_ci	xfs_fs_measure_sickness(mp, &sick, &checked);
5762306a36Sopenharmony_ci	if (sick & ~XFS_SICK_FS_COUNTERS) {
5862306a36Sopenharmony_ci		trace_xfs_fs_unfixed_corruption(mp, sick);
5962306a36Sopenharmony_ci		warn = true;
6062306a36Sopenharmony_ci	}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	if (warn) {
6362306a36Sopenharmony_ci		xfs_warn(mp,
6462306a36Sopenharmony_ci"Uncorrected metadata errors detected; please run xfs_repair.");
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci		/*
6762306a36Sopenharmony_ci		 * We discovered uncorrected metadata problems at some point
6862306a36Sopenharmony_ci		 * during this filesystem mount and have advised the
6962306a36Sopenharmony_ci		 * administrator to run repair once the unmount completes.
7062306a36Sopenharmony_ci		 *
7162306a36Sopenharmony_ci		 * However, we must be careful -- when FSCOUNTERS are flagged
7262306a36Sopenharmony_ci		 * unhealthy, the unmount procedure omits writing the clean
7362306a36Sopenharmony_ci		 * unmount record to the log so that the next mount will run
7462306a36Sopenharmony_ci		 * recovery and recompute the summary counters.  In other
7562306a36Sopenharmony_ci		 * words, we leave a dirty log to get the counters fixed.
7662306a36Sopenharmony_ci		 *
7762306a36Sopenharmony_ci		 * Unfortunately, xfs_repair cannot recover dirty logs, so if
7862306a36Sopenharmony_ci		 * there were filesystem problems, FSCOUNTERS was flagged, and
7962306a36Sopenharmony_ci		 * the administrator takes our advice to run xfs_repair,
8062306a36Sopenharmony_ci		 * they'll have to zap the log before repairing structures.
8162306a36Sopenharmony_ci		 * We don't really want to encourage this, so we mark the
8262306a36Sopenharmony_ci		 * FSCOUNTERS healthy so that a subsequent repair run won't see
8362306a36Sopenharmony_ci		 * a dirty log.
8462306a36Sopenharmony_ci		 */
8562306a36Sopenharmony_ci		if (sick & XFS_SICK_FS_COUNTERS)
8662306a36Sopenharmony_ci			xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS);
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/* Mark unhealthy per-fs metadata. */
9162306a36Sopenharmony_civoid
9262306a36Sopenharmony_cixfs_fs_mark_sick(
9362306a36Sopenharmony_ci	struct xfs_mount	*mp,
9462306a36Sopenharmony_ci	unsigned int		mask)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
9762306a36Sopenharmony_ci	trace_xfs_fs_mark_sick(mp, mask);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	spin_lock(&mp->m_sb_lock);
10062306a36Sopenharmony_ci	mp->m_fs_sick |= mask;
10162306a36Sopenharmony_ci	mp->m_fs_checked |= mask;
10262306a36Sopenharmony_ci	spin_unlock(&mp->m_sb_lock);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/* Mark a per-fs metadata healed. */
10662306a36Sopenharmony_civoid
10762306a36Sopenharmony_cixfs_fs_mark_healthy(
10862306a36Sopenharmony_ci	struct xfs_mount	*mp,
10962306a36Sopenharmony_ci	unsigned int		mask)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
11262306a36Sopenharmony_ci	trace_xfs_fs_mark_healthy(mp, mask);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	spin_lock(&mp->m_sb_lock);
11562306a36Sopenharmony_ci	mp->m_fs_sick &= ~mask;
11662306a36Sopenharmony_ci	mp->m_fs_checked |= mask;
11762306a36Sopenharmony_ci	spin_unlock(&mp->m_sb_lock);
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/* Sample which per-fs metadata are unhealthy. */
12162306a36Sopenharmony_civoid
12262306a36Sopenharmony_cixfs_fs_measure_sickness(
12362306a36Sopenharmony_ci	struct xfs_mount	*mp,
12462306a36Sopenharmony_ci	unsigned int		*sick,
12562306a36Sopenharmony_ci	unsigned int		*checked)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	spin_lock(&mp->m_sb_lock);
12862306a36Sopenharmony_ci	*sick = mp->m_fs_sick;
12962306a36Sopenharmony_ci	*checked = mp->m_fs_checked;
13062306a36Sopenharmony_ci	spin_unlock(&mp->m_sb_lock);
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/* Mark unhealthy realtime metadata. */
13462306a36Sopenharmony_civoid
13562306a36Sopenharmony_cixfs_rt_mark_sick(
13662306a36Sopenharmony_ci	struct xfs_mount	*mp,
13762306a36Sopenharmony_ci	unsigned int		mask)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
14062306a36Sopenharmony_ci	trace_xfs_rt_mark_sick(mp, mask);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	spin_lock(&mp->m_sb_lock);
14362306a36Sopenharmony_ci	mp->m_rt_sick |= mask;
14462306a36Sopenharmony_ci	mp->m_rt_checked |= mask;
14562306a36Sopenharmony_ci	spin_unlock(&mp->m_sb_lock);
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/* Mark a realtime metadata healed. */
14962306a36Sopenharmony_civoid
15062306a36Sopenharmony_cixfs_rt_mark_healthy(
15162306a36Sopenharmony_ci	struct xfs_mount	*mp,
15262306a36Sopenharmony_ci	unsigned int		mask)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
15562306a36Sopenharmony_ci	trace_xfs_rt_mark_healthy(mp, mask);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	spin_lock(&mp->m_sb_lock);
15862306a36Sopenharmony_ci	mp->m_rt_sick &= ~mask;
15962306a36Sopenharmony_ci	mp->m_rt_checked |= mask;
16062306a36Sopenharmony_ci	spin_unlock(&mp->m_sb_lock);
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci/* Sample which realtime metadata are unhealthy. */
16462306a36Sopenharmony_civoid
16562306a36Sopenharmony_cixfs_rt_measure_sickness(
16662306a36Sopenharmony_ci	struct xfs_mount	*mp,
16762306a36Sopenharmony_ci	unsigned int		*sick,
16862306a36Sopenharmony_ci	unsigned int		*checked)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	spin_lock(&mp->m_sb_lock);
17162306a36Sopenharmony_ci	*sick = mp->m_rt_sick;
17262306a36Sopenharmony_ci	*checked = mp->m_rt_checked;
17362306a36Sopenharmony_ci	spin_unlock(&mp->m_sb_lock);
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci/* Mark unhealthy per-ag metadata. */
17762306a36Sopenharmony_civoid
17862306a36Sopenharmony_cixfs_ag_mark_sick(
17962306a36Sopenharmony_ci	struct xfs_perag	*pag,
18062306a36Sopenharmony_ci	unsigned int		mask)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
18362306a36Sopenharmony_ci	trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	spin_lock(&pag->pag_state_lock);
18662306a36Sopenharmony_ci	pag->pag_sick |= mask;
18762306a36Sopenharmony_ci	pag->pag_checked |= mask;
18862306a36Sopenharmony_ci	spin_unlock(&pag->pag_state_lock);
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/* Mark per-ag metadata ok. */
19262306a36Sopenharmony_civoid
19362306a36Sopenharmony_cixfs_ag_mark_healthy(
19462306a36Sopenharmony_ci	struct xfs_perag	*pag,
19562306a36Sopenharmony_ci	unsigned int		mask)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
19862306a36Sopenharmony_ci	trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	spin_lock(&pag->pag_state_lock);
20162306a36Sopenharmony_ci	pag->pag_sick &= ~mask;
20262306a36Sopenharmony_ci	pag->pag_checked |= mask;
20362306a36Sopenharmony_ci	spin_unlock(&pag->pag_state_lock);
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci/* Sample which per-ag metadata are unhealthy. */
20762306a36Sopenharmony_civoid
20862306a36Sopenharmony_cixfs_ag_measure_sickness(
20962306a36Sopenharmony_ci	struct xfs_perag	*pag,
21062306a36Sopenharmony_ci	unsigned int		*sick,
21162306a36Sopenharmony_ci	unsigned int		*checked)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	spin_lock(&pag->pag_state_lock);
21462306a36Sopenharmony_ci	*sick = pag->pag_sick;
21562306a36Sopenharmony_ci	*checked = pag->pag_checked;
21662306a36Sopenharmony_ci	spin_unlock(&pag->pag_state_lock);
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci/* Mark the unhealthy parts of an inode. */
22062306a36Sopenharmony_civoid
22162306a36Sopenharmony_cixfs_inode_mark_sick(
22262306a36Sopenharmony_ci	struct xfs_inode	*ip,
22362306a36Sopenharmony_ci	unsigned int		mask)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
22662306a36Sopenharmony_ci	trace_xfs_inode_mark_sick(ip, mask);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	spin_lock(&ip->i_flags_lock);
22962306a36Sopenharmony_ci	ip->i_sick |= mask;
23062306a36Sopenharmony_ci	ip->i_checked |= mask;
23162306a36Sopenharmony_ci	spin_unlock(&ip->i_flags_lock);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	/*
23462306a36Sopenharmony_ci	 * Keep this inode around so we don't lose the sickness report.  Scrub
23562306a36Sopenharmony_ci	 * grabs inodes with DONTCACHE assuming that most inode are ok, which
23662306a36Sopenharmony_ci	 * is not the case here.
23762306a36Sopenharmony_ci	 */
23862306a36Sopenharmony_ci	spin_lock(&VFS_I(ip)->i_lock);
23962306a36Sopenharmony_ci	VFS_I(ip)->i_state &= ~I_DONTCACHE;
24062306a36Sopenharmony_ci	spin_unlock(&VFS_I(ip)->i_lock);
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci/* Mark parts of an inode healed. */
24462306a36Sopenharmony_civoid
24562306a36Sopenharmony_cixfs_inode_mark_healthy(
24662306a36Sopenharmony_ci	struct xfs_inode	*ip,
24762306a36Sopenharmony_ci	unsigned int		mask)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
25062306a36Sopenharmony_ci	trace_xfs_inode_mark_healthy(ip, mask);
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	spin_lock(&ip->i_flags_lock);
25362306a36Sopenharmony_ci	ip->i_sick &= ~mask;
25462306a36Sopenharmony_ci	ip->i_checked |= mask;
25562306a36Sopenharmony_ci	spin_unlock(&ip->i_flags_lock);
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci/* Sample which parts of an inode are unhealthy. */
25962306a36Sopenharmony_civoid
26062306a36Sopenharmony_cixfs_inode_measure_sickness(
26162306a36Sopenharmony_ci	struct xfs_inode	*ip,
26262306a36Sopenharmony_ci	unsigned int		*sick,
26362306a36Sopenharmony_ci	unsigned int		*checked)
26462306a36Sopenharmony_ci{
26562306a36Sopenharmony_ci	spin_lock(&ip->i_flags_lock);
26662306a36Sopenharmony_ci	*sick = ip->i_sick;
26762306a36Sopenharmony_ci	*checked = ip->i_checked;
26862306a36Sopenharmony_ci	spin_unlock(&ip->i_flags_lock);
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/* Mappings between internal sick masks and ioctl sick masks. */
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistruct ioctl_sick_map {
27462306a36Sopenharmony_ci	unsigned int		sick_mask;
27562306a36Sopenharmony_ci	unsigned int		ioctl_mask;
27662306a36Sopenharmony_ci};
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic const struct ioctl_sick_map fs_map[] = {
27962306a36Sopenharmony_ci	{ XFS_SICK_FS_COUNTERS,	XFS_FSOP_GEOM_SICK_COUNTERS},
28062306a36Sopenharmony_ci	{ XFS_SICK_FS_UQUOTA,	XFS_FSOP_GEOM_SICK_UQUOTA },
28162306a36Sopenharmony_ci	{ XFS_SICK_FS_GQUOTA,	XFS_FSOP_GEOM_SICK_GQUOTA },
28262306a36Sopenharmony_ci	{ XFS_SICK_FS_PQUOTA,	XFS_FSOP_GEOM_SICK_PQUOTA },
28362306a36Sopenharmony_ci	{ 0, 0 },
28462306a36Sopenharmony_ci};
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cistatic const struct ioctl_sick_map rt_map[] = {
28762306a36Sopenharmony_ci	{ XFS_SICK_RT_BITMAP,	XFS_FSOP_GEOM_SICK_RT_BITMAP },
28862306a36Sopenharmony_ci	{ XFS_SICK_RT_SUMMARY,	XFS_FSOP_GEOM_SICK_RT_SUMMARY },
28962306a36Sopenharmony_ci	{ 0, 0 },
29062306a36Sopenharmony_ci};
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cistatic inline void
29362306a36Sopenharmony_cixfgeo_health_tick(
29462306a36Sopenharmony_ci	struct xfs_fsop_geom		*geo,
29562306a36Sopenharmony_ci	unsigned int			sick,
29662306a36Sopenharmony_ci	unsigned int			checked,
29762306a36Sopenharmony_ci	const struct ioctl_sick_map	*m)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	if (checked & m->sick_mask)
30062306a36Sopenharmony_ci		geo->checked |= m->ioctl_mask;
30162306a36Sopenharmony_ci	if (sick & m->sick_mask)
30262306a36Sopenharmony_ci		geo->sick |= m->ioctl_mask;
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci/* Fill out fs geometry health info. */
30662306a36Sopenharmony_civoid
30762306a36Sopenharmony_cixfs_fsop_geom_health(
30862306a36Sopenharmony_ci	struct xfs_mount		*mp,
30962306a36Sopenharmony_ci	struct xfs_fsop_geom		*geo)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci	const struct ioctl_sick_map	*m;
31262306a36Sopenharmony_ci	unsigned int			sick;
31362306a36Sopenharmony_ci	unsigned int			checked;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	geo->sick = 0;
31662306a36Sopenharmony_ci	geo->checked = 0;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	xfs_fs_measure_sickness(mp, &sick, &checked);
31962306a36Sopenharmony_ci	for (m = fs_map; m->sick_mask; m++)
32062306a36Sopenharmony_ci		xfgeo_health_tick(geo, sick, checked, m);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	xfs_rt_measure_sickness(mp, &sick, &checked);
32362306a36Sopenharmony_ci	for (m = rt_map; m->sick_mask; m++)
32462306a36Sopenharmony_ci		xfgeo_health_tick(geo, sick, checked, m);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic const struct ioctl_sick_map ag_map[] = {
32862306a36Sopenharmony_ci	{ XFS_SICK_AG_SB,	XFS_AG_GEOM_SICK_SB },
32962306a36Sopenharmony_ci	{ XFS_SICK_AG_AGF,	XFS_AG_GEOM_SICK_AGF },
33062306a36Sopenharmony_ci	{ XFS_SICK_AG_AGFL,	XFS_AG_GEOM_SICK_AGFL },
33162306a36Sopenharmony_ci	{ XFS_SICK_AG_AGI,	XFS_AG_GEOM_SICK_AGI },
33262306a36Sopenharmony_ci	{ XFS_SICK_AG_BNOBT,	XFS_AG_GEOM_SICK_BNOBT },
33362306a36Sopenharmony_ci	{ XFS_SICK_AG_CNTBT,	XFS_AG_GEOM_SICK_CNTBT },
33462306a36Sopenharmony_ci	{ XFS_SICK_AG_INOBT,	XFS_AG_GEOM_SICK_INOBT },
33562306a36Sopenharmony_ci	{ XFS_SICK_AG_FINOBT,	XFS_AG_GEOM_SICK_FINOBT },
33662306a36Sopenharmony_ci	{ XFS_SICK_AG_RMAPBT,	XFS_AG_GEOM_SICK_RMAPBT },
33762306a36Sopenharmony_ci	{ XFS_SICK_AG_REFCNTBT,	XFS_AG_GEOM_SICK_REFCNTBT },
33862306a36Sopenharmony_ci	{ 0, 0 },
33962306a36Sopenharmony_ci};
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci/* Fill out ag geometry health info. */
34262306a36Sopenharmony_civoid
34362306a36Sopenharmony_cixfs_ag_geom_health(
34462306a36Sopenharmony_ci	struct xfs_perag		*pag,
34562306a36Sopenharmony_ci	struct xfs_ag_geometry		*ageo)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	const struct ioctl_sick_map	*m;
34862306a36Sopenharmony_ci	unsigned int			sick;
34962306a36Sopenharmony_ci	unsigned int			checked;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	ageo->ag_sick = 0;
35262306a36Sopenharmony_ci	ageo->ag_checked = 0;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	xfs_ag_measure_sickness(pag, &sick, &checked);
35562306a36Sopenharmony_ci	for (m = ag_map; m->sick_mask; m++) {
35662306a36Sopenharmony_ci		if (checked & m->sick_mask)
35762306a36Sopenharmony_ci			ageo->ag_checked |= m->ioctl_mask;
35862306a36Sopenharmony_ci		if (sick & m->sick_mask)
35962306a36Sopenharmony_ci			ageo->ag_sick |= m->ioctl_mask;
36062306a36Sopenharmony_ci	}
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic const struct ioctl_sick_map ino_map[] = {
36462306a36Sopenharmony_ci	{ XFS_SICK_INO_CORE,	XFS_BS_SICK_INODE },
36562306a36Sopenharmony_ci	{ XFS_SICK_INO_BMBTD,	XFS_BS_SICK_BMBTD },
36662306a36Sopenharmony_ci	{ XFS_SICK_INO_BMBTA,	XFS_BS_SICK_BMBTA },
36762306a36Sopenharmony_ci	{ XFS_SICK_INO_BMBTC,	XFS_BS_SICK_BMBTC },
36862306a36Sopenharmony_ci	{ XFS_SICK_INO_DIR,	XFS_BS_SICK_DIR },
36962306a36Sopenharmony_ci	{ XFS_SICK_INO_XATTR,	XFS_BS_SICK_XATTR },
37062306a36Sopenharmony_ci	{ XFS_SICK_INO_SYMLINK,	XFS_BS_SICK_SYMLINK },
37162306a36Sopenharmony_ci	{ XFS_SICK_INO_PARENT,	XFS_BS_SICK_PARENT },
37262306a36Sopenharmony_ci	{ 0, 0 },
37362306a36Sopenharmony_ci};
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci/* Fill out bulkstat health info. */
37662306a36Sopenharmony_civoid
37762306a36Sopenharmony_cixfs_bulkstat_health(
37862306a36Sopenharmony_ci	struct xfs_inode		*ip,
37962306a36Sopenharmony_ci	struct xfs_bulkstat		*bs)
38062306a36Sopenharmony_ci{
38162306a36Sopenharmony_ci	const struct ioctl_sick_map	*m;
38262306a36Sopenharmony_ci	unsigned int			sick;
38362306a36Sopenharmony_ci	unsigned int			checked;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	bs->bs_sick = 0;
38662306a36Sopenharmony_ci	bs->bs_checked = 0;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	xfs_inode_measure_sickness(ip, &sick, &checked);
38962306a36Sopenharmony_ci	for (m = ino_map; m->sick_mask; m++) {
39062306a36Sopenharmony_ci		if (checked & m->sick_mask)
39162306a36Sopenharmony_ci			bs->bs_checked |= m->ioctl_mask;
39262306a36Sopenharmony_ci		if (sick & m->sick_mask)
39362306a36Sopenharmony_ci			bs->bs_sick |= m->ioctl_mask;
39462306a36Sopenharmony_ci	}
39562306a36Sopenharmony_ci}
396