Commit 4ed080cd authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: repair summary counters



Use the same summary counter calculation infrastructure to generate new
values for the in-core summary counters.   The difference between the
scrubber and the repairer is that the repairer will freeze the fs during
setup, which means that the values should match exactly.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent a1f3e0cc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ xfs-y += $(addprefix scrub/, \
				   alloc_repair.o \
				   bmap_repair.o \
				   cow_repair.o \
				   fscounters_repair.o \
				   ialloc_repair.o \
				   inode_repair.o \
				   newbt.o \
+14 −13
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"
#include "scrub/fscounters.h"

/*
 * FS Summary Counters
@@ -48,17 +49,6 @@
 * our tolerance for mismatch between expected and actual counter values.
 */

struct xchk_fscounters {
	struct xfs_scrub	*sc;
	uint64_t		icount;
	uint64_t		ifree;
	uint64_t		fdblocks;
	uint64_t		frextents;
	unsigned long long	icount_min;
	unsigned long long	icount_max;
	bool			frozen;
};

/*
 * Since the expected value computation is lockless but only browses incore
 * values, the percpu counters should be fairly close to each other.  However,
@@ -235,8 +225,13 @@ xchk_setup_fscounters(
	 * Pause all writer activity in the filesystem while we're scrubbing to
	 * reduce the likelihood of background perturbations to the counters
	 * throwing off our calculations.
	 *
	 * If we're repairing, we need to prevent any other thread from
	 * changing the global fs summary counters while we're repairing them.
	 * This requires the fs to be frozen, which will disable background
	 * reclaim and purge all inactive inodes.
	 */
	if (sc->flags & XCHK_TRY_HARDER) {
	if ((sc->flags & XCHK_TRY_HARDER) || xchk_could_repair(sc)) {
		error = xchk_fscounters_freeze(sc);
		if (error)
			return error;
@@ -254,7 +249,9 @@ xchk_setup_fscounters(
 * set the INCOMPLETE flag even when a negative errno is returned.  This care
 * must be taken with certain errno values (i.e. EFSBADCRC, EFSCORRUPTED,
 * ECANCELED) that are absorbed into a scrub state flag update by
 * xchk_*_process_error.
 * xchk_*_process_error.  Scrub and repair share the same incore data
 * structures, so the INCOMPLETE flag is critical to prevent a repair based on
 * insufficient information.
 */

/* Count free space btree blocks manually for pre-lazysbcount filesystems. */
@@ -482,6 +479,10 @@ xchk_fscount_within_range(
	if (curr_value == expected)
		return true;

	/* We require exact matches when repair is running. */
	if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)
		return false;

	min_value = min(old_value, curr_value);
	max_value = max(old_value, curr_value);

+20 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <djwong@kernel.org>
 */
#ifndef __XFS_SCRUB_FSCOUNTERS_H__
#define __XFS_SCRUB_FSCOUNTERS_H__

struct xchk_fscounters {
	struct xfs_scrub	*sc;
	uint64_t		icount;
	uint64_t		ifree;
	uint64_t		fdblocks;
	uint64_t		frextents;
	unsigned long long	icount_min;
	unsigned long long	icount_max;
	bool			frozen;
};

#endif /* __XFS_SCRUB_FSCOUNTERS_H__ */
+72 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2018-2024 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <djwong@kernel.org>
 */
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_shared.h"
#include "xfs_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
#include "xfs_defer.h"
#include "xfs_btree.h"
#include "xfs_bit.h"
#include "xfs_log_format.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_inode.h"
#include "xfs_alloc.h"
#include "xfs_ialloc.h"
#include "xfs_rmap.h"
#include "xfs_health.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"
#include "scrub/repair.h"
#include "scrub/fscounters.h"

/*
 * FS Summary Counters
 * ===================
 *
 * We correct errors in the filesystem summary counters by setting them to the
 * values computed during the obligatory scrub phase.  However, we must be
 * careful not to allow any other thread to change the counters while we're
 * computing and setting new values.  To achieve this, we freeze the
 * filesystem for the whole operation if the REPAIR flag is set.  The checking
 * function is stricter when we've frozen the fs.
 */

/*
 * Reset the superblock counters.  Caller is responsible for freezing the
 * filesystem during the calculation and reset phases.
 */
int
xrep_fscounters(
	struct xfs_scrub	*sc)
{
	struct xfs_mount	*mp = sc->mp;
	struct xchk_fscounters	*fsc = sc->buf;

	/*
	 * Reinitialize the in-core counters from what we computed.  We froze
	 * the filesystem, so there shouldn't be anyone else trying to modify
	 * these counters.
	 */
	if (!fsc->frozen) {
		ASSERT(fsc->frozen);
		return -EFSCORRUPTED;
	}

	trace_xrep_reset_counters(mp, fsc);

	percpu_counter_set(&mp->m_icount, fsc->icount);
	percpu_counter_set(&mp->m_ifree, fsc->ifree);
	percpu_counter_set(&mp->m_fdblocks, fsc->fdblocks);
	percpu_counter_set(&mp->m_frextents, fsc->frextents);
	mp->m_sb.sb_frextents = fsc->frextents;

	return 0;
}
+2 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ int xrep_bmap_data(struct xfs_scrub *sc);
int xrep_bmap_attr(struct xfs_scrub *sc);
int xrep_bmap_cow(struct xfs_scrub *sc);
int xrep_nlinks(struct xfs_scrub *sc);
int xrep_fscounters(struct xfs_scrub *sc);

#ifdef CONFIG_XFS_RT
int xrep_rtbitmap(struct xfs_scrub *sc);
@@ -198,6 +199,7 @@ xrep_setup_nothing(
#define xrep_quota			xrep_notsupported
#define xrep_quotacheck			xrep_notsupported
#define xrep_nlinks			xrep_notsupported
#define xrep_fscounters			xrep_notsupported

#endif /* CONFIG_XFS_ONLINE_REPAIR */

Loading