1249259Sdim// SPDX-License-Identifier: GPL-2.0-or-later 2249259Sdim/* 3249259Sdim * Copyright (c) 2018-2024 Oracle. All Rights Reserved. 4249259Sdim * Author: Darrick J. Wong <djwong@kernel.org> 5249259Sdim */ 6249259Sdim#include "xfs.h" 7249259Sdim#include "xfs_fs.h" 8249259Sdim#include "xfs_shared.h" 9249259Sdim#include "xfs_format.h" 10249259Sdim#include "xfs_trans_resv.h" 11249259Sdim#include "xfs_mount.h" 12249259Sdim#include "xfs_defer.h" 13249259Sdim#include "xfs_btree.h" 14249259Sdim#include "xfs_bit.h" 15249259Sdim#include "xfs_log_format.h" 16249259Sdim#include "xfs_trans.h" 17249259Sdim#include "xfs_sb.h" 18249259Sdim#include "xfs_inode.h" 19249259Sdim#include "xfs_alloc.h" 20249259Sdim#include "xfs_ialloc.h" 21249259Sdim#include "xfs_rmap.h" 22249259Sdim#include "xfs_health.h" 23249259Sdim#include "scrub/xfs_scrub.h" 24249259Sdim#include "scrub/scrub.h" 25249259Sdim#include "scrub/common.h" 26249259Sdim#include "scrub/trace.h" 27249259Sdim#include "scrub/repair.h" 28249259Sdim#include "scrub/fscounters.h" 29249259Sdim 30249259Sdim/* 31249259Sdim * FS Summary Counters 32249259Sdim * =================== 33249259Sdim * 34249259Sdim * We correct errors in the filesystem summary counters by setting them to the 35249259Sdim * values computed during the obligatory scrub phase. However, we must be 36249259Sdim * careful not to allow any other thread to change the counters while we're 37249259Sdim * computing and setting new values. To achieve this, we freeze the 38249259Sdim * filesystem for the whole operation if the REPAIR flag is set. The checking 39249259Sdim * function is stricter when we've frozen the fs. 40249259Sdim */ 41249259Sdim 42249259Sdim/* 43249259Sdim * Reset the superblock counters. Caller is responsible for freezing the 44249259Sdim * filesystem during the calculation and reset phases. 45249259Sdim */ 46249259Sdimint 47249259Sdimxrep_fscounters( 48249259Sdim struct xfs_scrub *sc) 49249259Sdim{ 50249259Sdim struct xfs_mount *mp = sc->mp; 51249259Sdim struct xchk_fscounters *fsc = sc->buf; 52249259Sdim 53249259Sdim /* 54249259Sdim * Reinitialize the in-core counters from what we computed. We froze 55249259Sdim * the filesystem, so there shouldn't be anyone else trying to modify 56249259Sdim * these counters. 57249259Sdim */ 58249259Sdim if (!fsc->frozen) { 59249259Sdim ASSERT(fsc->frozen); 60249259Sdim return -EFSCORRUPTED; 61249259Sdim } 62249259Sdim 63249259Sdim trace_xrep_reset_counters(mp, fsc); 64249259Sdim 65249259Sdim percpu_counter_set(&mp->m_icount, fsc->icount); 66249259Sdim percpu_counter_set(&mp->m_ifree, fsc->ifree); 67249259Sdim percpu_counter_set(&mp->m_fdblocks, fsc->fdblocks); 68249259Sdim 69249259Sdim /* 70249259Sdim * Online repair is only supported on v5 file systems, which require 71249259Sdim * lazy sb counters and thus no update of sb_fdblocks here. But as of 72249259Sdim * now we don't support lazy counting sb_frextents yet, and thus need 73249259Sdim * to also update it directly here. And for that we need to keep 74249259Sdim * track of the delalloc reservations separately, as they are are 75249259Sdim * subtracted from m_frextents, but not included in sb_frextents. 76249259Sdim */ 77249259Sdim percpu_counter_set(&mp->m_frextents, 78249259Sdim fsc->frextents - fsc->frextents_delayed); 79249259Sdim mp->m_sb.sb_frextents = fsc->frextents; 80249259Sdim 81249259Sdim return 0; 82249259Sdim} 83249259Sdim