Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2018-2023 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_refcount.h"
25 : #include "scrub/xfs_scrub.h"
26 : #include "scrub/scrub.h"
27 : #include "scrub/common.h"
28 : #include "scrub/btree.h"
29 : #include "scrub/trace.h"
30 : #include "scrub/repair.h"
31 :
32 : /* Set us up with the realtime metadata locked. */
33 : int
34 106453 : xchk_setup_rtrmapbt(
35 : struct xfs_scrub *sc)
36 : {
37 106453 : struct xfs_mount *mp = sc->mp;
38 106453 : struct xfs_rtgroup *rtg;
39 106453 : int error = 0;
40 :
41 106453 : if (xchk_need_intent_drain(sc))
42 4504 : xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
43 :
44 106453 : rtg = xfs_rtgroup_get(mp, sc->sm->sm_agno);
45 106510 : if (!rtg)
46 : return -ENOENT;
47 :
48 213020 : if (xchk_could_repair(sc)) {
49 11467 : error = xrep_setup_rtrmapbt(sc);
50 11467 : if (error)
51 : return error;
52 : }
53 :
54 106510 : error = xchk_setup_rt(sc);
55 106448 : if (error)
56 40 : goto out_rtg;
57 :
58 106408 : error = xchk_install_live_inode(sc, rtg->rtg_rmapip);
59 106455 : if (error)
60 0 : goto out_rtg;
61 :
62 106455 : error = xchk_ino_dqattach(sc);
63 106386 : if (error)
64 0 : goto out_rtg;
65 :
66 106386 : error = xchk_rtgroup_init(sc, rtg->rtg_rgno, &sc->sr, XCHK_RTGLOCK_ALL);
67 106499 : out_rtg:
68 106499 : xfs_rtgroup_put(rtg);
69 106499 : return error;
70 : }
71 :
72 : /* Realtime reverse mapping. */
73 :
74 : struct xchk_rtrmap {
75 : /*
76 : * The furthest-reaching of the rmapbt records that we've already
77 : * processed. This enables us to detect overlapping records for space
78 : * allocations that cannot be shared.
79 : */
80 : struct xfs_rmap_irec overlap_rec;
81 :
82 : /*
83 : * The previous rmapbt record, so that we can check for two records
84 : * that could be one.
85 : */
86 : struct xfs_rmap_irec prev_rec;
87 : };
88 :
89 : static inline bool
90 364386008 : xchk_rtrmapbt_is_shareable(
91 : struct xfs_scrub *sc,
92 : const struct xfs_rmap_irec *irec)
93 : {
94 364386008 : if (!xfs_has_rtreflink(sc->mp))
95 : return false;
96 364386008 : if (irec->rm_flags & XFS_RMAP_UNWRITTEN)
97 0 : return false;
98 : return true;
99 : }
100 :
101 : /* Flag failures for records that overlap but cannot. */
102 : STATIC void
103 759607637 : xchk_rtrmapbt_check_overlapping(
104 : struct xchk_btree *bs,
105 : struct xchk_rtrmap *cr,
106 : const struct xfs_rmap_irec *irec)
107 : {
108 759607637 : xfs_rtblock_t pnext, inext;
109 :
110 759607637 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
111 : return;
112 :
113 : /* No previous record? */
114 759607637 : if (cr->overlap_rec.rm_blockcount == 0)
115 102396 : goto set_prev;
116 :
117 : /* Do overlap_rec and irec overlap? */
118 759505241 : pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
119 759505241 : if (pnext <= irec->rm_startblock)
120 577221455 : goto set_prev;
121 :
122 : /* Overlap is only allowed if both records are data fork mappings. */
123 182283786 : if (!xchk_rtrmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
124 182283786 : !xchk_rtrmapbt_is_shareable(bs->sc, irec))
125 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
126 :
127 : /* Save whichever rmap record extends furthest. */
128 182128938 : inext = irec->rm_startblock + irec->rm_blockcount;
129 182128938 : if (pnext > inext)
130 : return;
131 :
132 151914564 : set_prev:
133 1458476830 : memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec));
134 : }
135 :
136 : /* Decide if two reverse-mapping records can be merged. */
137 : static inline bool
138 759623794 : xchk_rtrmap_mergeable(
139 : struct xchk_rtrmap *cr,
140 : const struct xfs_rmap_irec *r2)
141 : {
142 759623794 : const struct xfs_rmap_irec *r1 = &cr->prev_rec;
143 :
144 : /* Ignore if prev_rec is not yet initialized. */
145 759623794 : if (cr->prev_rec.rm_blockcount == 0)
146 : return false;
147 :
148 759521398 : if (r1->rm_owner != r2->rm_owner)
149 : return false;
150 87378439 : if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
151 : return false;
152 46384035 : if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
153 : XFS_RMAP_LEN_MAX)
154 : return false;
155 46384035 : if (r1->rm_flags != r2->rm_flags)
156 : return false;
157 14280392 : return r1->rm_offset + r1->rm_blockcount == r2->rm_offset;
158 : }
159 :
160 : /* Flag failures for records that could be merged. */
161 : STATIC void
162 759556919 : xchk_rtrmapbt_check_mergeable(
163 : struct xchk_btree *bs,
164 : struct xchk_rtrmap *cr,
165 : const struct xfs_rmap_irec *irec)
166 : {
167 759556919 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
168 : return;
169 :
170 759556919 : if (xchk_rtrmap_mergeable(cr, irec))
171 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
172 :
173 1519113838 : memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec));
174 : }
175 :
176 : /* Cross-reference a rmap against the refcount btree. */
177 : STATIC void
178 757220251 : xchk_rtrmapbt_xref_rtrefc(
179 : struct xfs_scrub *sc,
180 : struct xfs_rmap_irec *irec)
181 : {
182 757220251 : xfs_rgblock_t fbno;
183 757220251 : xfs_extlen_t flen;
184 757220251 : bool is_inode;
185 757220251 : bool is_bmbt;
186 757220251 : bool is_attr;
187 757220251 : bool is_unwritten;
188 757220251 : int error;
189 :
190 757220251 : if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm))
191 29499 : return;
192 :
193 757190752 : is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
194 757190752 : is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
195 757190752 : is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
196 757190752 : is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
197 :
198 : /* If this is shared, must be a data fork extent. */
199 757190752 : error = xfs_refcount_find_shared(sc->sr.refc_cur, irec->rm_startblock,
200 : irec->rm_blockcount, &fbno, &flen, false);
201 756981916 : if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur))
202 : return;
203 756946607 : if (flen != 0 && (!is_inode || is_attr || is_bmbt || is_unwritten))
204 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0);
205 : }
206 :
207 : /* Cross-reference with other metadata. */
208 : STATIC void
209 759385065 : xchk_rtrmapbt_xref(
210 : struct xfs_scrub *sc,
211 : struct xfs_rmap_irec *irec)
212 : {
213 759385065 : xfs_rtblock_t rtbno;
214 :
215 759385065 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
216 : return;
217 :
218 759349175 : rtbno = xfs_rgbno_to_rtb(sc->mp, sc->sr.rtg->rtg_rgno,
219 : irec->rm_startblock);
220 :
221 759651500 : xchk_xref_is_used_rt_space(sc, rtbno, irec->rm_blockcount);
222 760221502 : if (irec->rm_owner == XFS_RMAP_OWN_COW)
223 2915067 : xchk_xref_is_cow_staging(sc, irec->rm_startblock,
224 : irec->rm_blockcount);
225 : else
226 757306435 : xchk_rtrmapbt_xref_rtrefc(sc, irec);
227 : }
228 :
229 : /* Scrub a realtime rmapbt record. */
230 : STATIC int
231 759911603 : xchk_rtrmapbt_rec(
232 : struct xchk_btree *bs,
233 : const union xfs_btree_rec *rec)
234 : {
235 759911603 : struct xchk_rtrmap *cr = bs->private;
236 759911603 : struct xfs_rmap_irec irec;
237 :
238 1519359199 : if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
239 759733392 : xfs_rmap_check_irec(bs->cur, &irec) != NULL) {
240 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
241 0 : return 0;
242 : }
243 :
244 759459048 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
245 : return 0;
246 :
247 759493328 : xchk_rtrmapbt_check_mergeable(bs, cr, &irec);
248 759478438 : xchk_rtrmapbt_check_overlapping(bs, cr, &irec);
249 759355736 : xchk_rtrmapbt_xref(bs->sc, &irec);
250 759355736 : return 0;
251 : }
252 :
253 : /* Scrub the realtime rmap btree. */
254 : int
255 102352 : xchk_rtrmapbt(
256 : struct xfs_scrub *sc)
257 : {
258 102352 : struct xfs_owner_info oinfo;
259 102352 : struct xchk_rtrmap cr = { };
260 102352 : int error;
261 :
262 102352 : error = xchk_metadata_inode_forks(sc);
263 102396 : if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
264 : return error;
265 :
266 102396 : xfs_rmap_ino_bmbt_owner(&oinfo, sc->sr.rtg->rtg_rmapip->i_ino,
267 : XFS_DATA_FORK);
268 102396 : return xchk_btree(sc, sc->sr.rmap_cur, xchk_rtrmapbt_rec, &oinfo, &cr);
269 : }
270 :
271 : /* xref check that the extent has no realtime reverse mapping at all */
272 : void
273 24778535 : xchk_xref_has_no_rt_owner(
274 : struct xfs_scrub *sc,
275 : xfs_rgblock_t bno,
276 : xfs_extlen_t len)
277 : {
278 24778535 : enum xbtree_recpacking outcome;
279 24778535 : int error;
280 :
281 24778535 : if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
282 0 : return;
283 :
284 24778535 : error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome);
285 24781813 : if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
286 : return;
287 24781720 : if (outcome != XBTREE_RECPACKING_EMPTY)
288 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
289 : }
290 :
291 : /* xref check that the extent is completely mapped */
292 : void
293 24873409 : xchk_xref_has_rt_owner(
294 : struct xfs_scrub *sc,
295 : xfs_rgblock_t bno,
296 : xfs_extlen_t len)
297 : {
298 24873409 : enum xbtree_recpacking outcome;
299 24873409 : int error;
300 :
301 24873409 : if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
302 0 : return;
303 :
304 24873409 : error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome);
305 24873638 : if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
306 : return;
307 24873513 : if (outcome != XBTREE_RECPACKING_FULL)
308 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
309 : }
310 :
311 : /* xref check that the extent is only owned by a given owner */
312 : void
313 31046016 : xchk_xref_is_only_rt_owned_by(
314 : struct xfs_scrub *sc,
315 : xfs_agblock_t bno,
316 : xfs_extlen_t len,
317 : const struct xfs_owner_info *oinfo)
318 : {
319 31046016 : struct xfs_rmap_matches res;
320 31046016 : int error;
321 :
322 31046016 : if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
323 0 : return;
324 :
325 31046016 : error = xfs_rmap_count_owners(sc->sr.rmap_cur, bno, len, oinfo, &res);
326 31061287 : if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
327 : return;
328 31059913 : if (res.matches != 1)
329 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
330 31059913 : if (res.bad_non_owner_matches)
331 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
332 31059913 : if (res.non_owner_matches)
333 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
334 : }
|