xref: /linux/fs/xfs/scrub/rtrmap.c (revision 91683bb3f264c04e6f0710de23dbd6c9605c550a)
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_rmap.h"
19 #include "xfs_rmap_btree.h"
20 #include "xfs_rtrmap_btree.h"
21 #include "xfs_inode.h"
22 #include "xfs_rtalloc.h"
23 #include "xfs_rtgroup.h"
24 #include "xfs_metafile.h"
25 #include "xfs_refcount.h"
26 #include "scrub/xfs_scrub.h"
27 #include "scrub/scrub.h"
28 #include "scrub/common.h"
29 #include "scrub/btree.h"
30 #include "scrub/trace.h"
31 #include "scrub/repair.h"
32 
33 /* Set us up with the realtime metadata locked. */
34 int
35 xchk_setup_rtrmapbt(
36 	struct xfs_scrub	*sc)
37 {
38 	int			error;
39 
40 	if (xchk_need_intent_drain(sc))
41 		xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
42 
43 	if (xchk_could_repair(sc)) {
44 		error = xrep_setup_rtrmapbt(sc);
45 		if (error)
46 			return error;
47 	}
48 
49 	error = xchk_rtgroup_init(sc, sc->sm->sm_agno, &sc->sr);
50 	if (error)
51 		return error;
52 
53 	error = xchk_setup_rt(sc);
54 	if (error)
55 		return error;
56 
57 	error = xchk_install_live_inode(sc, rtg_rmap(sc->sr.rtg));
58 	if (error)
59 		return error;
60 
61 	return xchk_rtgroup_lock(sc, &sc->sr, XCHK_RTGLOCK_ALL);
62 }
63 
64 /* Realtime reverse mapping. */
65 
66 struct xchk_rtrmap {
67 	/*
68 	 * The furthest-reaching of the rmapbt records that we've already
69 	 * processed.  This enables us to detect overlapping records for space
70 	 * allocations that cannot be shared.
71 	 */
72 	struct xfs_rmap_irec	overlap_rec;
73 
74 	/*
75 	 * The previous rmapbt record, so that we can check for two records
76 	 * that could be one.
77 	 */
78 	struct xfs_rmap_irec	prev_rec;
79 };
80 
81 /* Flag failures for records that overlap but cannot. */
82 STATIC void
83 xchk_rtrmapbt_check_overlapping(
84 	struct xchk_btree		*bs,
85 	struct xchk_rtrmap		*cr,
86 	const struct xfs_rmap_irec	*irec)
87 {
88 	xfs_rtblock_t			pnext, inext;
89 
90 	if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
91 		return;
92 
93 	/* No previous record? */
94 	if (cr->overlap_rec.rm_blockcount == 0)
95 		goto set_prev;
96 
97 	/* Do overlap_rec and irec overlap? */
98 	pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
99 	if (pnext <= irec->rm_startblock)
100 		goto set_prev;
101 
102 	xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
103 
104 	/* Save whichever rmap record extends furthest. */
105 	inext = irec->rm_startblock + irec->rm_blockcount;
106 	if (pnext > inext)
107 		return;
108 
109 set_prev:
110 	memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec));
111 }
112 
113 /* Decide if two reverse-mapping records can be merged. */
114 static inline bool
115 xchk_rtrmap_mergeable(
116 	struct xchk_rtrmap		*cr,
117 	const struct xfs_rmap_irec	*r2)
118 {
119 	const struct xfs_rmap_irec	*r1 = &cr->prev_rec;
120 
121 	/* Ignore if prev_rec is not yet initialized. */
122 	if (cr->prev_rec.rm_blockcount == 0)
123 		return false;
124 
125 	if (r1->rm_owner != r2->rm_owner)
126 		return false;
127 	if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
128 		return false;
129 	if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
130 	    XFS_RMAP_LEN_MAX)
131 		return false;
132 	if (r1->rm_flags != r2->rm_flags)
133 		return false;
134 	return r1->rm_offset + r1->rm_blockcount == r2->rm_offset;
135 }
136 
137 /* Flag failures for records that could be merged. */
138 STATIC void
139 xchk_rtrmapbt_check_mergeable(
140 	struct xchk_btree		*bs,
141 	struct xchk_rtrmap		*cr,
142 	const struct xfs_rmap_irec	*irec)
143 {
144 	if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
145 		return;
146 
147 	if (xchk_rtrmap_mergeable(cr, irec))
148 		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
149 
150 	memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec));
151 }
152 
153 /* Cross-reference a rmap against the refcount btree. */
154 STATIC void
155 xchk_rtrmapbt_xref_rtrefc(
156 	struct xfs_scrub	*sc,
157 	struct xfs_rmap_irec	*irec)
158 {
159 	xfs_rgblock_t		fbno;
160 	xfs_extlen_t		flen;
161 	bool			is_inode;
162 	bool			is_bmbt;
163 	bool			is_attr;
164 	bool			is_unwritten;
165 	int			error;
166 
167 	if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm))
168 		return;
169 
170 	is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
171 	is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
172 	is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
173 	is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
174 
175 	/* If this is shared, must be a data fork extent. */
176 	error = xfs_refcount_find_shared(sc->sr.refc_cur, irec->rm_startblock,
177 			irec->rm_blockcount, &fbno, &flen, false);
178 	if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur))
179 		return;
180 	if (flen != 0 && (!is_inode || is_attr || is_bmbt || is_unwritten))
181 		xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
182 }
183 
184 /* Cross-reference with other metadata. */
185 STATIC void
186 xchk_rtrmapbt_xref(
187 	struct xfs_scrub	*sc,
188 	struct xfs_rmap_irec	*irec)
189 {
190 	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
191 		return;
192 
193 	xchk_xref_is_used_rt_space(sc,
194 			xfs_rgbno_to_rtb(sc->sr.rtg, irec->rm_startblock),
195 			irec->rm_blockcount);
196 	if (irec->rm_owner == XFS_RMAP_OWN_COW)
197 		xchk_xref_is_cow_staging(sc, irec->rm_startblock,
198 				irec->rm_blockcount);
199 	else
200 		xchk_rtrmapbt_xref_rtrefc(sc, irec);
201 }
202 
203 /* Scrub a realtime rmapbt record. */
204 STATIC int
205 xchk_rtrmapbt_rec(
206 	struct xchk_btree		*bs,
207 	const union xfs_btree_rec	*rec)
208 {
209 	struct xchk_rtrmap		*cr = bs->private;
210 	struct xfs_rmap_irec		irec;
211 
212 	if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
213 	    xfs_rtrmap_check_irec(to_rtg(bs->cur->bc_group), &irec) != NULL) {
214 		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
215 		return 0;
216 	}
217 
218 	if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
219 		return 0;
220 
221 	xchk_rtrmapbt_check_mergeable(bs, cr, &irec);
222 	xchk_rtrmapbt_check_overlapping(bs, cr, &irec);
223 	xchk_rtrmapbt_xref(bs->sc, &irec);
224 	return 0;
225 }
226 
227 /* Scrub the realtime rmap btree. */
228 int
229 xchk_rtrmapbt(
230 	struct xfs_scrub	*sc)
231 {
232 	struct xfs_inode	*ip = rtg_rmap(sc->sr.rtg);
233 	struct xfs_owner_info	oinfo;
234 	struct xchk_rtrmap	cr = { };
235 	int			error;
236 
237 	error = xchk_metadata_inode_forks(sc);
238 	if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
239 		return error;
240 
241 	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, XFS_DATA_FORK);
242 	return xchk_btree(sc, sc->sr.rmap_cur, xchk_rtrmapbt_rec, &oinfo, &cr);
243 }
244 
245 /* xref check that the extent has no realtime reverse mapping at all */
246 void
247 xchk_xref_has_no_rt_owner(
248 	struct xfs_scrub	*sc,
249 	xfs_rgblock_t		bno,
250 	xfs_extlen_t		len)
251 {
252 	enum xbtree_recpacking	outcome;
253 	int			error;
254 
255 	if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
256 		return;
257 
258 	error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome);
259 	if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
260 		return;
261 	if (outcome != XBTREE_RECPACKING_EMPTY)
262 		xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
263 }
264 
265 /* xref check that the extent is completely mapped */
266 void
267 xchk_xref_has_rt_owner(
268 	struct xfs_scrub	*sc,
269 	xfs_rgblock_t		bno,
270 	xfs_extlen_t		len)
271 {
272 	enum xbtree_recpacking	outcome;
273 	int			error;
274 
275 	if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
276 		return;
277 
278 	error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome);
279 	if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
280 		return;
281 	if (outcome != XBTREE_RECPACKING_FULL)
282 		xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
283 }
284 
285 /* xref check that the extent is only owned by a given owner */
286 void
287 xchk_xref_is_only_rt_owned_by(
288 	struct xfs_scrub		*sc,
289 	xfs_agblock_t			bno,
290 	xfs_extlen_t			len,
291 	const struct xfs_owner_info	*oinfo)
292 {
293 	struct xfs_rmap_matches		res;
294 	int				error;
295 
296 	if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
297 		return;
298 
299 	error = xfs_rmap_count_owners(sc->sr.rmap_cur, bno, len, oinfo, &res);
300 	if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
301 		return;
302 	if (res.matches != 1)
303 		xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
304 	if (res.bad_non_owner_matches)
305 		xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
306 	if (res.non_owner_matches)
307 		xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
308 }
309