Linux Audio

Check our new training course

Loading...
v6.9.4
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2019-2023 Oracle.  All Rights Reserved.
  4 * Author: Darrick J. Wong <djwong@kernel.org>
  5 */
  6#include "xfs.h"
  7#include "xfs_fs.h"
  8#include "xfs_shared.h"
  9#include "xfs_format.h"
 10#include "xfs_trans_resv.h"
 11#include "xfs_mount.h"
 12#include "xfs_btree.h"
 13#include "xfs_ag.h"
 14#include "xfs_health.h"
 15#include "scrub/scrub.h"
 16#include "scrub/health.h"
 17#include "scrub/common.h"
 18
 19/*
 20 * Scrub and In-Core Filesystem Health Assessments
 21 * ===============================================
 22 *
 23 * Online scrub and repair have the time and the ability to perform stronger
 24 * checks than we can do from the metadata verifiers, because they can
 25 * cross-reference records between data structures.  Therefore, scrub is in a
 26 * good position to update the online filesystem health assessments to reflect
 27 * the good/bad state of the data structure.
 28 *
 29 * We therefore extend scrub in the following ways to achieve this:
 30 *
 31 * 1. Create a "sick_mask" field in the scrub context.  When we're setting up a
 32 * scrub call, set this to the default XFS_SICK_* flag(s) for the selected
 33 * scrub type (call it A).  Scrub and repair functions can override the default
 34 * sick_mask value if they choose.
 35 *
 36 * 2. If the scrubber returns a runtime error code, we exit making no changes
 37 * to the incore sick state.
 38 *
 39 * 3. If the scrubber finds that A is clean, use sick_mask to clear the incore
 40 * sick flags before exiting.
 41 *
 42 * 4. If the scrubber finds that A is corrupt, use sick_mask to set the incore
 43 * sick flags.  If the user didn't want to repair then we exit, leaving the
 44 * metadata structure unfixed and the sick flag set.
 45 *
 46 * 5. Now we know that A is corrupt and the user wants to repair, so run the
 47 * repairer.  If the repairer returns an error code, we exit with that error
 48 * code, having made no further changes to the incore sick state.
 49 *
 50 * 6. If repair rebuilds A correctly and the subsequent re-scrub of A is clean,
 51 * use sick_mask to clear the incore sick flags.  This should have the effect
 52 * that A is no longer marked sick.
 53 *
 54 * 7. If repair rebuilds A incorrectly, the re-scrub will find it corrupt and
 55 * use sick_mask to set the incore sick flags.  This should have no externally
 56 * visible effect since we already set them in step (4).
 57 *
 58 * There are some complications to this story, however.  For certain types of
 59 * complementary metadata indices (e.g. inobt/finobt), it is easier to rebuild
 60 * both structures at the same time.  The following principles apply to this
 61 * type of repair strategy:
 62 *
 63 * 8. Any repair function that rebuilds multiple structures should update
 64 * sick_mask_visible to reflect whatever other structures are rebuilt, and
 65 * verify that all the rebuilt structures can pass a scrub check.  The outcomes
 66 * of 5-7 still apply, but with a sick_mask that covers everything being
 67 * rebuilt.
 68 */
 69
 70/* Map our scrub type to a sick mask and a set of health update functions. */
 71
 72enum xchk_health_group {
 73	XHG_FS = 1,
 74	XHG_RT,
 75	XHG_AG,
 76	XHG_INO,
 77};
 78
 79struct xchk_health_map {
 80	enum xchk_health_group	group;
 81	unsigned int		sick_mask;
 82};
 83
 84static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = {
 85	[XFS_SCRUB_TYPE_SB]		= { XHG_AG,  XFS_SICK_AG_SB },
 86	[XFS_SCRUB_TYPE_AGF]		= { XHG_AG,  XFS_SICK_AG_AGF },
 87	[XFS_SCRUB_TYPE_AGFL]		= { XHG_AG,  XFS_SICK_AG_AGFL },
 88	[XFS_SCRUB_TYPE_AGI]		= { XHG_AG,  XFS_SICK_AG_AGI },
 89	[XFS_SCRUB_TYPE_BNOBT]		= { XHG_AG,  XFS_SICK_AG_BNOBT },
 90	[XFS_SCRUB_TYPE_CNTBT]		= { XHG_AG,  XFS_SICK_AG_CNTBT },
 91	[XFS_SCRUB_TYPE_INOBT]		= { XHG_AG,  XFS_SICK_AG_INOBT },
 92	[XFS_SCRUB_TYPE_FINOBT]		= { XHG_AG,  XFS_SICK_AG_FINOBT },
 93	[XFS_SCRUB_TYPE_RMAPBT]		= { XHG_AG,  XFS_SICK_AG_RMAPBT },
 94	[XFS_SCRUB_TYPE_REFCNTBT]	= { XHG_AG,  XFS_SICK_AG_REFCNTBT },
 95	[XFS_SCRUB_TYPE_INODE]		= { XHG_INO, XFS_SICK_INO_CORE },
 96	[XFS_SCRUB_TYPE_BMBTD]		= { XHG_INO, XFS_SICK_INO_BMBTD },
 97	[XFS_SCRUB_TYPE_BMBTA]		= { XHG_INO, XFS_SICK_INO_BMBTA },
 98	[XFS_SCRUB_TYPE_BMBTC]		= { XHG_INO, XFS_SICK_INO_BMBTC },
 99	[XFS_SCRUB_TYPE_DIR]		= { XHG_INO, XFS_SICK_INO_DIR },
100	[XFS_SCRUB_TYPE_XATTR]		= { XHG_INO, XFS_SICK_INO_XATTR },
101	[XFS_SCRUB_TYPE_SYMLINK]	= { XHG_INO, XFS_SICK_INO_SYMLINK },
102	[XFS_SCRUB_TYPE_PARENT]		= { XHG_INO, XFS_SICK_INO_PARENT },
103	[XFS_SCRUB_TYPE_RTBITMAP]	= { XHG_RT,  XFS_SICK_RT_BITMAP },
104	[XFS_SCRUB_TYPE_RTSUM]		= { XHG_RT,  XFS_SICK_RT_SUMMARY },
105	[XFS_SCRUB_TYPE_UQUOTA]		= { XHG_FS,  XFS_SICK_FS_UQUOTA },
106	[XFS_SCRUB_TYPE_GQUOTA]		= { XHG_FS,  XFS_SICK_FS_GQUOTA },
107	[XFS_SCRUB_TYPE_PQUOTA]		= { XHG_FS,  XFS_SICK_FS_PQUOTA },
108	[XFS_SCRUB_TYPE_FSCOUNTERS]	= { XHG_FS,  XFS_SICK_FS_COUNTERS },
109	[XFS_SCRUB_TYPE_QUOTACHECK]	= { XHG_FS,  XFS_SICK_FS_QUOTACHECK },
110	[XFS_SCRUB_TYPE_NLINKS]		= { XHG_FS,  XFS_SICK_FS_NLINKS },
111};
112
113/* Return the health status mask for this scrub type. */
114unsigned int
115xchk_health_mask_for_scrub_type(
116	__u32			scrub_type)
117{
118	return type_to_health_flag[scrub_type].sick_mask;
119}
120
121/*
122 * If the scrub state is clean, add @mask to the scrub sick mask to clear
123 * additional sick flags from the metadata object's sick state.
124 */
125void
126xchk_mark_healthy_if_clean(
127	struct xfs_scrub	*sc,
128	unsigned int		mask)
129{
130	if (!(sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
131				  XFS_SCRUB_OFLAG_XCORRUPT)))
132		sc->sick_mask |= mask;
133}
134
135/*
136 * If we're scrubbing a piece of file metadata for the first time, does it look
137 * like it has been zapped?  Skip the check if we just repaired the metadata
138 * and are revalidating it.
139 */
140bool
141xchk_file_looks_zapped(
142	struct xfs_scrub	*sc,
143	unsigned int		mask)
144{
145	ASSERT((mask & ~XFS_SICK_INO_ZAPPED) == 0);
146
147	if (sc->flags & XREP_ALREADY_FIXED)
148		return false;
149
150	return xfs_inode_has_sickness(sc->ip, mask);
151}
152
153/*
154 * Scrub gave the filesystem a clean bill of health, so clear all the indirect
155 * markers of past problems (at least for the fs and ags) so that we can be
156 * healthy again.
157 */
158STATIC void
159xchk_mark_all_healthy(
160	struct xfs_mount	*mp)
161{
162	struct xfs_perag	*pag;
163	xfs_agnumber_t		agno;
164
165	xfs_fs_mark_healthy(mp, XFS_SICK_FS_INDIRECT);
166	xfs_rt_mark_healthy(mp, XFS_SICK_RT_INDIRECT);
167	for_each_perag(mp, agno, pag)
168		xfs_ag_mark_healthy(pag, XFS_SICK_AG_INDIRECT);
169}
170
171/*
172 * Update filesystem health assessments based on what we found and did.
173 *
174 * If the scrubber finds errors, we mark sick whatever's mentioned in
175 * sick_mask, no matter whether this is a first scan or an
176 * evaluation of repair effectiveness.
177 *
178 * Otherwise, no direct corruption was found, so mark whatever's in
179 * sick_mask as healthy.
180 */
181void
182xchk_update_health(
183	struct xfs_scrub	*sc)
184{
185	struct xfs_perag	*pag;
186	bool			bad;
187
188	/*
189	 * The HEALTHY scrub type is a request from userspace to clear all the
190	 * indirect flags after a clean scan of the entire filesystem.  As such
191	 * there's no sick flag defined for it, so we branch here ahead of the
192	 * mask check.
193	 */
194	if (sc->sm->sm_type == XFS_SCRUB_TYPE_HEALTHY &&
195	    !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
196		xchk_mark_all_healthy(sc->mp);
197		return;
198	}
199
200	if (!sc->sick_mask)
201		return;
202
203	bad = (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
204				   XFS_SCRUB_OFLAG_XCORRUPT));
205	switch (type_to_health_flag[sc->sm->sm_type].group) {
206	case XHG_AG:
207		pag = xfs_perag_get(sc->mp, sc->sm->sm_agno);
208		if (bad)
209			xfs_ag_mark_corrupt(pag, sc->sick_mask);
210		else
211			xfs_ag_mark_healthy(pag, sc->sick_mask);
212		xfs_perag_put(pag);
213		break;
214	case XHG_INO:
215		if (!sc->ip)
216			return;
217		if (bad) {
218			unsigned int	mask = sc->sick_mask;
219
220			/*
221			 * If we're coming in for repairs then we don't want
222			 * sickness flags to propagate to the incore health
223			 * status if the inode gets inactivated before we can
224			 * fix it.
225			 */
226			if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)
227				mask |= XFS_SICK_INO_FORGET;
228			xfs_inode_mark_corrupt(sc->ip, mask);
229		} else
230			xfs_inode_mark_healthy(sc->ip, sc->sick_mask);
231		break;
232	case XHG_FS:
233		if (bad)
234			xfs_fs_mark_corrupt(sc->mp, sc->sick_mask);
235		else
236			xfs_fs_mark_healthy(sc->mp, sc->sick_mask);
237		break;
238	case XHG_RT:
239		if (bad)
240			xfs_rt_mark_corrupt(sc->mp, sc->sick_mask);
241		else
242			xfs_rt_mark_healthy(sc->mp, sc->sick_mask);
243		break;
244	default:
245		ASSERT(0);
246		break;
247	}
248}
249
250/* Is the given per-AG btree healthy enough for scanning? */
251void
252xchk_ag_btree_del_cursor_if_sick(
253	struct xfs_scrub	*sc,
254	struct xfs_btree_cur	**curp,
255	unsigned int		sm_type)
256{
257	unsigned int		mask = (*curp)->bc_ops->sick_mask;
258
259	/*
260	 * We always want the cursor if it's the same type as whatever we're
261	 * scrubbing, even if we already know the structure is corrupt.
262	 *
263	 * Otherwise, we're only interested in the btree for cross-referencing.
264	 * If we know the btree is bad then don't bother, just set XFAIL.
265	 */
266	if (sc->sm->sm_type == sm_type)
267		return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
269	/*
270	 * If we just repaired some AG metadata, sc->sick_mask will reflect all
271	 * the per-AG metadata types that were repaired.  Exclude these from
272	 * the filesystem health query because we have not yet updated the
273	 * health status and we want everything to be scanned.
274	 */
275	if ((sc->flags & XREP_ALREADY_FIXED) &&
276	    type_to_health_flag[sc->sm->sm_type].group == XHG_AG)
277		mask &= ~sc->sick_mask;
278
279	if (xfs_ag_has_sickness((*curp)->bc_ag.pag, mask)) {
280		sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XFAIL;
281		xfs_btree_del_cursor(*curp, XFS_BTREE_NOERROR);
282		*curp = NULL;
283	}
284}
285
286/*
287 * Quick scan to double-check that there isn't any evidence of lingering
288 * primary health problems.  If we're still clear, then the health update will
289 * take care of clearing the indirect evidence.
290 */
291int
292xchk_health_record(
293	struct xfs_scrub	*sc)
294{
295	struct xfs_mount	*mp = sc->mp;
296	struct xfs_perag	*pag;
297	xfs_agnumber_t		agno;
298
299	unsigned int		sick;
300	unsigned int		checked;
301
302	xfs_fs_measure_sickness(mp, &sick, &checked);
303	if (sick & XFS_SICK_FS_PRIMARY)
304		xchk_set_corrupt(sc);
305
306	xfs_rt_measure_sickness(mp, &sick, &checked);
307	if (sick & XFS_SICK_RT_PRIMARY)
308		xchk_set_corrupt(sc);
309
310	for_each_perag(mp, agno, pag) {
311		xfs_ag_measure_sickness(pag, &sick, &checked);
312		if (sick & XFS_SICK_AG_PRIMARY)
313			xchk_set_corrupt(sc);
314	}
315
316	return 0;
317}
v6.8
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2019-2023 Oracle.  All Rights Reserved.
  4 * Author: Darrick J. Wong <djwong@kernel.org>
  5 */
  6#include "xfs.h"
  7#include "xfs_fs.h"
  8#include "xfs_shared.h"
  9#include "xfs_format.h"
 10#include "xfs_trans_resv.h"
 11#include "xfs_mount.h"
 12#include "xfs_btree.h"
 13#include "xfs_ag.h"
 14#include "xfs_health.h"
 15#include "scrub/scrub.h"
 16#include "scrub/health.h"
 
 17
 18/*
 19 * Scrub and In-Core Filesystem Health Assessments
 20 * ===============================================
 21 *
 22 * Online scrub and repair have the time and the ability to perform stronger
 23 * checks than we can do from the metadata verifiers, because they can
 24 * cross-reference records between data structures.  Therefore, scrub is in a
 25 * good position to update the online filesystem health assessments to reflect
 26 * the good/bad state of the data structure.
 27 *
 28 * We therefore extend scrub in the following ways to achieve this:
 29 *
 30 * 1. Create a "sick_mask" field in the scrub context.  When we're setting up a
 31 * scrub call, set this to the default XFS_SICK_* flag(s) for the selected
 32 * scrub type (call it A).  Scrub and repair functions can override the default
 33 * sick_mask value if they choose.
 34 *
 35 * 2. If the scrubber returns a runtime error code, we exit making no changes
 36 * to the incore sick state.
 37 *
 38 * 3. If the scrubber finds that A is clean, use sick_mask to clear the incore
 39 * sick flags before exiting.
 40 *
 41 * 4. If the scrubber finds that A is corrupt, use sick_mask to set the incore
 42 * sick flags.  If the user didn't want to repair then we exit, leaving the
 43 * metadata structure unfixed and the sick flag set.
 44 *
 45 * 5. Now we know that A is corrupt and the user wants to repair, so run the
 46 * repairer.  If the repairer returns an error code, we exit with that error
 47 * code, having made no further changes to the incore sick state.
 48 *
 49 * 6. If repair rebuilds A correctly and the subsequent re-scrub of A is clean,
 50 * use sick_mask to clear the incore sick flags.  This should have the effect
 51 * that A is no longer marked sick.
 52 *
 53 * 7. If repair rebuilds A incorrectly, the re-scrub will find it corrupt and
 54 * use sick_mask to set the incore sick flags.  This should have no externally
 55 * visible effect since we already set them in step (4).
 56 *
 57 * There are some complications to this story, however.  For certain types of
 58 * complementary metadata indices (e.g. inobt/finobt), it is easier to rebuild
 59 * both structures at the same time.  The following principles apply to this
 60 * type of repair strategy:
 61 *
 62 * 8. Any repair function that rebuilds multiple structures should update
 63 * sick_mask_visible to reflect whatever other structures are rebuilt, and
 64 * verify that all the rebuilt structures can pass a scrub check.  The outcomes
 65 * of 5-7 still apply, but with a sick_mask that covers everything being
 66 * rebuilt.
 67 */
 68
 69/* Map our scrub type to a sick mask and a set of health update functions. */
 70
 71enum xchk_health_group {
 72	XHG_FS = 1,
 73	XHG_RT,
 74	XHG_AG,
 75	XHG_INO,
 76};
 77
 78struct xchk_health_map {
 79	enum xchk_health_group	group;
 80	unsigned int		sick_mask;
 81};
 82
 83static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = {
 84	[XFS_SCRUB_TYPE_SB]		= { XHG_AG,  XFS_SICK_AG_SB },
 85	[XFS_SCRUB_TYPE_AGF]		= { XHG_AG,  XFS_SICK_AG_AGF },
 86	[XFS_SCRUB_TYPE_AGFL]		= { XHG_AG,  XFS_SICK_AG_AGFL },
 87	[XFS_SCRUB_TYPE_AGI]		= { XHG_AG,  XFS_SICK_AG_AGI },
 88	[XFS_SCRUB_TYPE_BNOBT]		= { XHG_AG,  XFS_SICK_AG_BNOBT },
 89	[XFS_SCRUB_TYPE_CNTBT]		= { XHG_AG,  XFS_SICK_AG_CNTBT },
 90	[XFS_SCRUB_TYPE_INOBT]		= { XHG_AG,  XFS_SICK_AG_INOBT },
 91	[XFS_SCRUB_TYPE_FINOBT]		= { XHG_AG,  XFS_SICK_AG_FINOBT },
 92	[XFS_SCRUB_TYPE_RMAPBT]		= { XHG_AG,  XFS_SICK_AG_RMAPBT },
 93	[XFS_SCRUB_TYPE_REFCNTBT]	= { XHG_AG,  XFS_SICK_AG_REFCNTBT },
 94	[XFS_SCRUB_TYPE_INODE]		= { XHG_INO, XFS_SICK_INO_CORE },
 95	[XFS_SCRUB_TYPE_BMBTD]		= { XHG_INO, XFS_SICK_INO_BMBTD },
 96	[XFS_SCRUB_TYPE_BMBTA]		= { XHG_INO, XFS_SICK_INO_BMBTA },
 97	[XFS_SCRUB_TYPE_BMBTC]		= { XHG_INO, XFS_SICK_INO_BMBTC },
 98	[XFS_SCRUB_TYPE_DIR]		= { XHG_INO, XFS_SICK_INO_DIR },
 99	[XFS_SCRUB_TYPE_XATTR]		= { XHG_INO, XFS_SICK_INO_XATTR },
100	[XFS_SCRUB_TYPE_SYMLINK]	= { XHG_INO, XFS_SICK_INO_SYMLINK },
101	[XFS_SCRUB_TYPE_PARENT]		= { XHG_INO, XFS_SICK_INO_PARENT },
102	[XFS_SCRUB_TYPE_RTBITMAP]	= { XHG_RT,  XFS_SICK_RT_BITMAP },
103	[XFS_SCRUB_TYPE_RTSUM]		= { XHG_RT,  XFS_SICK_RT_SUMMARY },
104	[XFS_SCRUB_TYPE_UQUOTA]		= { XHG_FS,  XFS_SICK_FS_UQUOTA },
105	[XFS_SCRUB_TYPE_GQUOTA]		= { XHG_FS,  XFS_SICK_FS_GQUOTA },
106	[XFS_SCRUB_TYPE_PQUOTA]		= { XHG_FS,  XFS_SICK_FS_PQUOTA },
107	[XFS_SCRUB_TYPE_FSCOUNTERS]	= { XHG_FS,  XFS_SICK_FS_COUNTERS },
 
 
108};
109
110/* Return the health status mask for this scrub type. */
111unsigned int
112xchk_health_mask_for_scrub_type(
113	__u32			scrub_type)
114{
115	return type_to_health_flag[scrub_type].sick_mask;
116}
117
118/*
119 * If the scrub state is clean, add @mask to the scrub sick mask to clear
120 * additional sick flags from the metadata object's sick state.
121 */
122void
123xchk_mark_healthy_if_clean(
124	struct xfs_scrub	*sc,
125	unsigned int		mask)
126{
127	if (!(sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
128				  XFS_SCRUB_OFLAG_XCORRUPT)))
129		sc->sick_mask |= mask;
130}
131
132/*
133 * If we're scrubbing a piece of file metadata for the first time, does it look
134 * like it has been zapped?  Skip the check if we just repaired the metadata
135 * and are revalidating it.
136 */
137bool
138xchk_file_looks_zapped(
139	struct xfs_scrub	*sc,
140	unsigned int		mask)
141{
142	ASSERT((mask & ~XFS_SICK_INO_ZAPPED) == 0);
143
144	if (sc->flags & XREP_ALREADY_FIXED)
145		return false;
146
147	return xfs_inode_has_sickness(sc->ip, mask);
148}
149
150/*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151 * Update filesystem health assessments based on what we found and did.
152 *
153 * If the scrubber finds errors, we mark sick whatever's mentioned in
154 * sick_mask, no matter whether this is a first scan or an
155 * evaluation of repair effectiveness.
156 *
157 * Otherwise, no direct corruption was found, so mark whatever's in
158 * sick_mask as healthy.
159 */
160void
161xchk_update_health(
162	struct xfs_scrub	*sc)
163{
164	struct xfs_perag	*pag;
165	bool			bad;
166
 
 
 
 
 
 
 
 
 
 
 
 
167	if (!sc->sick_mask)
168		return;
169
170	bad = (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
171				   XFS_SCRUB_OFLAG_XCORRUPT));
172	switch (type_to_health_flag[sc->sm->sm_type].group) {
173	case XHG_AG:
174		pag = xfs_perag_get(sc->mp, sc->sm->sm_agno);
175		if (bad)
176			xfs_ag_mark_sick(pag, sc->sick_mask);
177		else
178			xfs_ag_mark_healthy(pag, sc->sick_mask);
179		xfs_perag_put(pag);
180		break;
181	case XHG_INO:
182		if (!sc->ip)
183			return;
184		if (bad)
185			xfs_inode_mark_sick(sc->ip, sc->sick_mask);
186		else
 
 
 
 
 
 
 
 
 
 
187			xfs_inode_mark_healthy(sc->ip, sc->sick_mask);
188		break;
189	case XHG_FS:
190		if (bad)
191			xfs_fs_mark_sick(sc->mp, sc->sick_mask);
192		else
193			xfs_fs_mark_healthy(sc->mp, sc->sick_mask);
194		break;
195	case XHG_RT:
196		if (bad)
197			xfs_rt_mark_sick(sc->mp, sc->sick_mask);
198		else
199			xfs_rt_mark_healthy(sc->mp, sc->sick_mask);
200		break;
201	default:
202		ASSERT(0);
203		break;
204	}
205}
206
207/* Is the given per-AG btree healthy enough for scanning? */
208bool
209xchk_ag_btree_healthy_enough(
210	struct xfs_scrub	*sc,
211	struct xfs_perag	*pag,
212	xfs_btnum_t		btnum)
213{
214	unsigned int		mask = 0;
215
216	/*
217	 * We always want the cursor if it's the same type as whatever we're
218	 * scrubbing, even if we already know the structure is corrupt.
219	 *
220	 * Otherwise, we're only interested in the btree for cross-referencing.
221	 * If we know the btree is bad then don't bother, just set XFAIL.
222	 */
223	switch (btnum) {
224	case XFS_BTNUM_BNO:
225		if (sc->sm->sm_type == XFS_SCRUB_TYPE_BNOBT)
226			return true;
227		mask = XFS_SICK_AG_BNOBT;
228		break;
229	case XFS_BTNUM_CNT:
230		if (sc->sm->sm_type == XFS_SCRUB_TYPE_CNTBT)
231			return true;
232		mask = XFS_SICK_AG_CNTBT;
233		break;
234	case XFS_BTNUM_INO:
235		if (sc->sm->sm_type == XFS_SCRUB_TYPE_INOBT)
236			return true;
237		mask = XFS_SICK_AG_INOBT;
238		break;
239	case XFS_BTNUM_FINO:
240		if (sc->sm->sm_type == XFS_SCRUB_TYPE_FINOBT)
241			return true;
242		mask = XFS_SICK_AG_FINOBT;
243		break;
244	case XFS_BTNUM_RMAP:
245		if (sc->sm->sm_type == XFS_SCRUB_TYPE_RMAPBT)
246			return true;
247		mask = XFS_SICK_AG_RMAPBT;
248		break;
249	case XFS_BTNUM_REFC:
250		if (sc->sm->sm_type == XFS_SCRUB_TYPE_REFCNTBT)
251			return true;
252		mask = XFS_SICK_AG_REFCNTBT;
253		break;
254	default:
255		ASSERT(0);
256		return true;
257	}
258
259	/*
260	 * If we just repaired some AG metadata, sc->sick_mask will reflect all
261	 * the per-AG metadata types that were repaired.  Exclude these from
262	 * the filesystem health query because we have not yet updated the
263	 * health status and we want everything to be scanned.
264	 */
265	if ((sc->flags & XREP_ALREADY_FIXED) &&
266	    type_to_health_flag[sc->sm->sm_type].group == XHG_AG)
267		mask &= ~sc->sick_mask;
268
269	if (xfs_ag_has_sickness(pag, mask)) {
270		sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XFAIL;
271		return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272	}
273
274	return true;
275}