xref: /linux/fs/xfs/scrub/fscounters_repair.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2018-2024 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_defer.h"
13 #include "xfs_btree.h"
14 #include "xfs_bit.h"
15 #include "xfs_log_format.h"
16 #include "xfs_trans.h"
17 #include "xfs_sb.h"
18 #include "xfs_inode.h"
19 #include "xfs_alloc.h"
20 #include "xfs_ialloc.h"
21 #include "xfs_rmap.h"
22 #include "xfs_health.h"
23 #include "scrub/xfs_scrub.h"
24 #include "scrub/scrub.h"
25 #include "scrub/common.h"
26 #include "scrub/trace.h"
27 #include "scrub/repair.h"
28 #include "scrub/fscounters.h"
29 
30 /*
31  * FS Summary Counters
32  * ===================
33  *
34  * We correct errors in the filesystem summary counters by setting them to the
35  * values computed during the obligatory scrub phase.  However, we must be
36  * careful not to allow any other thread to change the counters while we're
37  * computing and setting new values.  To achieve this, we freeze the
38  * filesystem for the whole operation if the REPAIR flag is set.  The checking
39  * function is stricter when we've frozen the fs.
40  */
41 
42 /*
43  * Reset the superblock counters.  Caller is responsible for freezing the
44  * filesystem during the calculation and reset phases.
45  */
46 int
47 xrep_fscounters(
48 	struct xfs_scrub	*sc)
49 {
50 	struct xfs_mount	*mp = sc->mp;
51 	struct xchk_fscounters	*fsc = sc->buf;
52 
53 	/*
54 	 * Reinitialize the in-core counters from what we computed.  We froze
55 	 * the filesystem, so there shouldn't be anyone else trying to modify
56 	 * these counters.
57 	 */
58 	if (!fsc->frozen) {
59 		ASSERT(fsc->frozen);
60 		return -EFSCORRUPTED;
61 	}
62 
63 	trace_xrep_reset_counters(mp, fsc);
64 
65 	percpu_counter_set(&mp->m_icount, fsc->icount);
66 	percpu_counter_set(&mp->m_ifree, fsc->ifree);
67 	percpu_counter_set(&mp->m_fdblocks, fsc->fdblocks);
68 
69 	/*
70 	 * Online repair is only supported on v5 file systems, which require
71 	 * lazy sb counters and thus no update of sb_fdblocks here.  But
72 	 * sb_frextents only uses a lazy counter with rtgroups, and thus needs
73 	 * to be updated directly here otherwise.  And for that we need to keep
74 	 * track of the delalloc reservations separately, as they are are
75 	 * subtracted from m_frextents, but not included in sb_frextents.
76 	 */
77 	percpu_counter_set(&mp->m_frextents,
78 		fsc->frextents - fsc->frextents_delayed);
79 	if (!xfs_has_rtgroups(mp))
80 		mp->m_sb.sb_frextents = fsc->frextents;
81 
82 	return 0;
83 }
84