xref: /linux/fs/xfs/scrub/rtrefcount.c (revision bb29b957eaaa15be33243550d9ee576c2d601669)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <djwong@kernel.org>
5  */
6 #include "xfs_platform.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
12 #include "xfs_mount.h"
13 #include "xfs_trans.h"
14 #include "xfs_btree.h"
15 #include "xfs_rmap.h"
16 #include "xfs_refcount.h"
17 #include "xfs_inode.h"
18 #include "xfs_rtbitmap.h"
19 #include "xfs_rtgroup.h"
20 #include "xfs_metafile.h"
21 #include "xfs_rtrefcount_btree.h"
22 #include "xfs_rtalloc.h"
23 #include "xfs_ag.h"
24 #include "scrub/scrub.h"
25 #include "scrub/common.h"
26 #include "scrub/btree.h"
27 #include "scrub/repair.h"
28 #include "scrub/refcount.h"
29 
30 /* Set us up with the realtime refcount metadata locked. */
31 int
32 xchk_setup_rtrefcountbt(
33 	struct xfs_scrub	*sc)
34 {
35 	int			error;
36 
37 	if (xchk_need_intent_drain(sc))
38 		xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
39 
40 	if (xchk_could_repair(sc)) {
41 		error = xrep_setup_rtrefcountbt(sc);
42 		if (error)
43 			return error;
44 	}
45 
46 	error = xchk_rtgroup_init(sc, sc->sm->sm_agno);
47 	if (error)
48 		return error;
49 
50 	error = xchk_setup_rt(sc);
51 	if (error)
52 		return error;
53 
54 	error = xchk_install_live_inode(sc, rtg_refcount(sc->sr.rtg));
55 	if (error)
56 		return error;
57 
58 	return xchk_rtgroup_lock(sc, XCHK_RTGLOCK_ALL);
59 }
60 
61 /* Realtime Reference count btree scrubber. */
62 
63 /* Use the rmap entries covering this extent to verify the refcount. */
64 STATIC void
65 xchk_rtrefcountbt_xref_rmap(
66 	struct xfs_scrub		*sc,
67 	const struct xfs_refcount_irec	*irec)
68 {
69 	struct xchk_refcnt_check	refchk = {
70 		.sc			= sc,
71 		.bno			= irec->rc_startblock,
72 		.len			= irec->rc_blockcount,
73 		.refcount		= irec->rc_refcount,
74 		.seen			= 0,
75 	};
76 	struct xfs_rmap_irec		low;
77 	struct xfs_rmap_irec		high;
78 	struct xchk_refcnt_frag		*frag;
79 	struct xchk_refcnt_frag		*n;
80 	int				error;
81 
82 	if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
83 		return;
84 
85 	/* Cross-reference with the rmapbt to confirm the refcount. */
86 	memset(&low, 0, sizeof(low));
87 	low.rm_startblock = irec->rc_startblock;
88 	memset(&high, 0xFF, sizeof(high));
89 	high.rm_startblock = irec->rc_startblock + irec->rc_blockcount - 1;
90 
91 	INIT_LIST_HEAD(&refchk.fragments);
92 	error = xfs_rmap_query_range(sc->sr.rmap_cur, &low, &high,
93 			xchk_refcountbt_rmap_check, &refchk);
94 	if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
95 		goto out_free;
96 
97 	xchk_refcountbt_process_rmap_fragments(&refchk);
98 	if (irec->rc_refcount != refchk.seen)
99 		xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
100 
101 out_free:
102 	list_for_each_entry_safe(frag, n, &refchk.fragments, list) {
103 		list_del(&frag->list);
104 		kfree(frag);
105 	}
106 }
107 
108 /* Cross-reference with the other btrees. */
109 STATIC void
110 xchk_rtrefcountbt_xref(
111 	struct xfs_scrub		*sc,
112 	const struct xfs_refcount_irec	*irec)
113 {
114 	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
115 		return;
116 
117 	xchk_xref_is_used_rt_space(sc,
118 			xfs_rgbno_to_rtb(sc->sr.rtg, irec->rc_startblock),
119 			irec->rc_blockcount);
120 	xchk_rtrefcountbt_xref_rmap(sc, irec);
121 }
122 
123 struct xchk_rtrefcbt_records {
124 	/* Previous refcount record. */
125 	struct xfs_refcount_irec	prev_rec;
126 
127 	/* The next rtgroup block where we aren't expecting shared extents. */
128 	xfs_rgblock_t			next_unshared_rgbno;
129 
130 	/* Number of CoW blocks we expect. */
131 	xfs_extlen_t			cow_blocks;
132 
133 	/* Was the last record a shared or CoW staging extent? */
134 	enum xfs_refc_domain		prev_domain;
135 };
136 
137 static inline bool
138 xchk_rtrefcount_mergeable(
139 	struct xchk_rtrefcbt_records	*rrc,
140 	const struct xfs_refcount_irec	*r2)
141 {
142 	const struct xfs_refcount_irec	*r1 = &rrc->prev_rec;
143 
144 	/* Ignore if prev_rec is not yet initialized. */
145 	if (r1->rc_blockcount == 0)
146 		return false;
147 
148 	if (r1->rc_domain != r2->rc_domain)
149 		return false;
150 	if (r1->rc_startblock + r1->rc_blockcount != r2->rc_startblock)
151 		return false;
152 	if (r1->rc_refcount != r2->rc_refcount)
153 		return false;
154 	if ((unsigned long long)r1->rc_blockcount + r2->rc_blockcount >
155 			XFS_REFC_LEN_MAX)
156 		return false;
157 
158 	return true;
159 }
160 
161 /* Flag failures for records that could be merged. */
162 STATIC void
163 xchk_rtrefcountbt_check_mergeable(
164 	struct xchk_btree		*bs,
165 	struct xchk_rtrefcbt_records	*rrc,
166 	const struct xfs_refcount_irec	*irec)
167 {
168 	if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
169 		return;
170 
171 	if (xchk_rtrefcount_mergeable(rrc, irec))
172 		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
173 
174 	memcpy(&rrc->prev_rec, irec, sizeof(struct xfs_refcount_irec));
175 }
176 
177 /*
178  * Make sure that a gap in the reference count records does not correspond to
179  * overlapping records (i.e. shared extents) in the reverse mappings.
180  */
181 static inline void
182 xchk_rtrefcountbt_xref_gaps(
183 	struct xfs_scrub	*sc,
184 	struct xchk_rtrefcbt_records *rrc,
185 	xfs_rgblock_t		bno)
186 {
187 	struct xfs_rmap_irec	low;
188 	struct xfs_rmap_irec	high;
189 	xfs_rgblock_t		next_bno = NULLRGBLOCK;
190 	int			error;
191 
192 	if (bno <= rrc->next_unshared_rgbno || !sc->sr.rmap_cur ||
193             xchk_skip_xref(sc->sm))
194 		return;
195 
196 	memset(&low, 0, sizeof(low));
197 	low.rm_startblock = rrc->next_unshared_rgbno;
198 	memset(&high, 0xFF, sizeof(high));
199 	high.rm_startblock = bno - 1;
200 
201 	error = xfs_rmap_query_range(sc->sr.rmap_cur, &low, &high,
202 			xchk_refcountbt_rmap_check_gap, &next_bno);
203 	if (error == -ECANCELED)
204 		xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
205 	else
206 		xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur);
207 }
208 
209 /* Scrub a rtrefcountbt record. */
210 STATIC int
211 xchk_rtrefcountbt_rec(
212 	struct xchk_btree		*bs,
213 	const union xfs_btree_rec	*rec)
214 {
215 	struct xfs_mount		*mp = bs->cur->bc_mp;
216 	struct xchk_rtrefcbt_records	*rrc = bs->private;
217 	struct xfs_refcount_irec	irec;
218 	u32				mod;
219 
220 	xfs_refcount_btrec_to_irec(rec, &irec);
221 	if (xfs_rtrefcount_check_irec(to_rtg(bs->cur->bc_group), &irec) !=
222 			NULL) {
223 		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
224 		return 0;
225 	}
226 
227 	/* We can only share full rt extents. */
228 	mod = xfs_rgbno_to_rtxoff(mp, irec.rc_startblock);
229 	if (mod)
230 		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
231 	mod = xfs_extlen_to_rtxmod(mp, irec.rc_blockcount);
232 	if (mod)
233 		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
234 
235 	if (irec.rc_domain == XFS_REFC_DOMAIN_COW)
236 		rrc->cow_blocks += irec.rc_blockcount;
237 
238 	/* Shared records always come before CoW records. */
239 	if (irec.rc_domain == XFS_REFC_DOMAIN_SHARED &&
240 	    rrc->prev_domain == XFS_REFC_DOMAIN_COW)
241 		xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
242 	rrc->prev_domain = irec.rc_domain;
243 
244 	xchk_rtrefcountbt_check_mergeable(bs, rrc, &irec);
245 	xchk_rtrefcountbt_xref(bs->sc, &irec);
246 
247 	/*
248 	 * If this is a record for a shared extent, check that all blocks
249 	 * between the previous record and this one have at most one reverse
250 	 * mapping.
251 	 */
252 	if (irec.rc_domain == XFS_REFC_DOMAIN_SHARED) {
253 		xchk_rtrefcountbt_xref_gaps(bs->sc, rrc, irec.rc_startblock);
254 		rrc->next_unshared_rgbno = irec.rc_startblock +
255 					   irec.rc_blockcount;
256 	}
257 
258 	return 0;
259 }
260 
261 /* Count the number of blocks used by the rtrefcount btree file in this AG. */
262 static int
263 xchk_rtrefcount_count_agblocks(
264 	struct xfs_scrub	*sc,
265 	xfs_agnumber_t		agno,
266 	const struct xfs_owner_info *btree_oinfo,
267 	xfs_filblks_t		*blocks)
268 {
269 	xfs_filblks_t		agblocks = 0;
270 	int			error;
271 
272 	error = xchk_ag_init_existing(sc, agno);
273 	if (error)
274 		goto out_free;
275 
276 	/*
277 	 * If we don't have an rmap cursor, we can't complete the cross
278 	 * referencing, so return EFSCORRUPTED to end the loop and trigger the
279 	 * XFAIL flag.
280 	 */
281 	if (!sc->sa.rmap_cur) {
282 		error = -EFSCORRUPTED;
283 		goto out_free;
284 	}
285 
286 	error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, btree_oinfo,
287 			&agblocks);
288 	if (error)
289 		goto out_free;
290 
291 	*blocks += agblocks;
292 out_free:
293 	xchk_ag_free(sc);
294 	return error;
295 }
296 
297 /* Make sure we have as many refc blocks as the rmap says. */
298 STATIC void
299 xchk_rtrefcount_xref_rmap(
300 	struct xfs_scrub	*sc,
301 	const struct xfs_owner_info *btree_oinfo,
302 	xfs_extlen_t		cow_blocks)
303 {
304 	xfs_filblks_t		refcbt_blocks = 0;
305 	xfs_filblks_t		blocks = 1; /* one for the iroot */
306 	xfs_agnumber_t		agno;
307 	int			error = 0;
308 
309 	if (!xfs_has_rmapbt(sc->mp) || xchk_skip_xref(sc->sm))
310 		return;
311 
312 	/* Check that we saw as many refcbt blocks as the rmap knows about. */
313 	error = xfs_btree_count_blocks(sc->sr.refc_cur, &refcbt_blocks);
314 	if (!xchk_btree_process_error(sc, sc->sr.refc_cur, 0, &error))
315 		return;
316 
317 	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
318 		error = xchk_rtrefcount_count_agblocks(sc, agno, btree_oinfo,
319 				&blocks);
320 		if (error)
321 			break;
322 	}
323 	if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
324 		return;
325 	if (blocks != refcbt_blocks)
326 		xchk_fblock_xref_set_corrupt(sc, XFS_DATA_FORK, 0);
327 
328 	if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
329 		return;
330 
331 	/* Check that we saw as many cow blocks as the rmap knows about. */
332 	error = xchk_count_rmap_ownedby_ag(sc, sc->sr.rmap_cur,
333 			&XFS_RMAP_OINFO_COW, &blocks);
334 	if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
335 		return;
336 	if (blocks != cow_blocks)
337 		xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
338 }
339 
340 /* Scrub the refcount btree for some rtgroup. */
341 int
342 xchk_rtrefcountbt(
343 	struct xfs_scrub	*sc)
344 {
345 	struct xfs_owner_info	btree_oinfo;
346 	struct xchk_rtrefcbt_records rrc = {
347 		.cow_blocks		= 0,
348 		.next_unshared_rgbno	= 0,
349 		.prev_domain		= XFS_REFC_DOMAIN_SHARED,
350 	};
351 	int			error;
352 
353 	error = xchk_metadata_inode_forks(sc);
354 	if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
355 		return error;
356 
357 	xfs_rmap_inode_bmbt_owner(&btree_oinfo, rtg_refcount(sc->sr.rtg),
358 			XFS_DATA_FORK);
359 	error = xchk_btree(sc, sc->sr.refc_cur, xchk_rtrefcountbt_rec,
360 			&btree_oinfo, &rrc);
361 	if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
362 		return error;
363 
364 	/*
365 	 * Check that all blocks between the last refcount > 1 record and the
366 	 * end of the rtgroup have at most one reverse mapping.
367 	 */
368 	xchk_rtrefcountbt_xref_gaps(sc, &rrc,
369 			xfs_rtx_to_rgbno(sc->sr.rtg, sc->mp->m_sb.sb_rgextents));
370 	xchk_rtrefcount_xref_rmap(sc, &btree_oinfo, rrc.cow_blocks);
371 
372 	return 0;
373 }
374 
375 /* xref check that a cow staging extent is marked in the rtrefcountbt. */
376 void
377 xchk_xref_is_rt_cow_staging(
378 	struct xfs_scrub		*sc,
379 	xfs_rgblock_t			bno,
380 	xfs_extlen_t			len)
381 {
382 	struct xfs_refcount_irec	rc;
383 	int				has_refcount;
384 	int				error;
385 
386 	if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm))
387 		return;
388 
389 	/* Find the CoW staging extent. */
390 	error = xfs_refcount_lookup_le(sc->sr.refc_cur, XFS_REFC_DOMAIN_COW,
391 			bno, &has_refcount);
392 	if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur))
393 		return;
394 	if (!has_refcount) {
395 		xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
396 		return;
397 	}
398 
399 	error = xfs_refcount_get_rec(sc->sr.refc_cur, &rc, &has_refcount);
400 	if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur))
401 		return;
402 	if (!has_refcount) {
403 		xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
404 		return;
405 	}
406 
407 	/* CoW lookup returned a shared extent record? */
408 	if (rc.rc_domain != XFS_REFC_DOMAIN_COW)
409 		xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
410 
411 	/* Can't start after bno */
412 	if (rc.rc_startblock > bno)
413 		xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
414 
415 	/* Must be at least as long as what was passed in */
416 	if (rc.rc_startblock + rc.rc_blockcount < bno + len)
417 		xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
418 }
419 
420 /*
421  * xref check that the extent is not shared.  Only file data blocks
422  * can have multiple owners.
423  */
424 void
425 xchk_xref_is_not_rt_shared(
426 	struct xfs_scrub	*sc,
427 	xfs_rgblock_t		bno,
428 	xfs_extlen_t		len)
429 {
430 	enum xbtree_recpacking	outcome;
431 	int			error;
432 
433 	if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm))
434 		return;
435 
436 	error = xfs_refcount_has_records(sc->sr.refc_cur,
437 			XFS_REFC_DOMAIN_SHARED, bno, len, &outcome);
438 	if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur))
439 		return;
440 	if (outcome != XBTREE_RECPACKING_EMPTY)
441 		xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
442 }
443 
444 /* xref check that the extent is not being used for CoW staging. */
445 void
446 xchk_xref_is_not_rt_cow_staging(
447 	struct xfs_scrub	*sc,
448 	xfs_rgblock_t		bno,
449 	xfs_extlen_t		len)
450 {
451 	enum xbtree_recpacking	outcome;
452 	int			error;
453 
454 	if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm))
455 		return;
456 
457 	error = xfs_refcount_has_records(sc->sr.refc_cur, XFS_REFC_DOMAIN_COW,
458 			bno, len, &outcome);
459 	if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur))
460 		return;
461 	if (outcome != XBTREE_RECPACKING_EMPTY)
462 		xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
463 }
464