// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2018-2024 Oracle. All Rights Reserved.
* Author: Darrick J. Wong <[email protected]>
*/
#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);
/*
* Online repair is only supported on v5 file systems, which require
* lazy sb counters and thus no update of sb_fdblocks here. But as of
* now we don't support lazy counting sb_frextents yet, and thus need
* to also update it directly here. And for that we need to keep
* track of the delalloc reservations separately, as they are are
* subtracted from m_frextents, but not included in sb_frextents.
*/
percpu_counter_set(&mp->m_frextents,
fsc->frextents - fsc->frextents_delayed);
mp->m_sb.sb_frextents = fsc->frextents;
return 0;
}