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 42363 : xchk_setup_rtrmapbt(
35 : struct xfs_scrub *sc)
36 : {
37 42363 : struct xfs_mount *mp = sc->mp;
38 42363 : struct xfs_rtgroup *rtg;
39 42363 : int error = 0;
40 :
41 42363 : if (xchk_need_intent_drain(sc))
42 4000 : xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
43 :
44 42363 : rtg = xfs_rtgroup_get(mp, sc->sm->sm_agno);
45 42363 : if (!rtg)
46 : return -ENOENT;
47 :
48 84726 : if (xchk_could_repair(sc)) {
49 3356 : error = xrep_setup_rtrmapbt(sc);
50 3356 : if (error)
51 : return error;
52 : }
53 :
54 42363 : error = xchk_setup_rt(sc);
55 42363 : if (error)
56 0 : goto out_rtg;
57 :
58 42363 : error = xchk_install_live_inode(sc, rtg->rtg_rmapip);
59 42363 : if (error)
60 0 : goto out_rtg;
61 :
62 42363 : error = xchk_ino_dqattach(sc);
63 42363 : if (error)
64 0 : goto out_rtg;
65 :
66 42363 : error = xchk_rtgroup_init(sc, rtg->rtg_rgno, &sc->sr, XCHK_RTGLOCK_ALL);
67 42363 : out_rtg:
68 42363 : xfs_rtgroup_put(rtg);
69 42363 : 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 174307720 : xchk_rtrmapbt_is_shareable(
91 : struct xfs_scrub *sc,
92 : const struct xfs_rmap_irec *irec)
93 : {
94 174307720 : if (!xfs_has_rtreflink(sc->mp))
95 : return false;
96 174307720 : 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 608232186 : xchk_rtrmapbt_check_overlapping(
104 : struct xchk_btree *bs,
105 : struct xchk_rtrmap *cr,
106 : const struct xfs_rmap_irec *irec)
107 : {
108 608232186 : xfs_rtblock_t pnext, inext;
109 :
110 608232186 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
111 : return;
112 :
113 : /* No previous record? */
114 608232186 : if (cr->overlap_rec.rm_blockcount == 0)
115 38579 : goto set_prev;
116 :
117 : /* Do overlap_rec and irec overlap? */
118 608193607 : pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
119 608193607 : if (pnext <= irec->rm_startblock)
120 521039432 : goto set_prev;
121 :
122 : /* Overlap is only allowed if both records are data fork mappings. */
123 87154175 : if (!xchk_rtrmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
124 87154175 : !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 87154327 : inext = irec->rm_startblock + irec->rm_blockcount;
129 87154327 : if (pnext > inext)
130 : return;
131 :
132 53965790 : set_prev:
133 1150087602 : 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 608222412 : xchk_rtrmap_mergeable(
139 : struct xchk_rtrmap *cr,
140 : const struct xfs_rmap_irec *r2)
141 : {
142 608222412 : const struct xfs_rmap_irec *r1 = &cr->prev_rec;
143 :
144 : /* Ignore if prev_rec is not yet initialized. */
145 608222412 : if (cr->prev_rec.rm_blockcount == 0)
146 : return false;
147 :
148 608183833 : if (r1->rm_owner != r2->rm_owner)
149 : return false;
150 24897263 : if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
151 : return false;
152 20248554 : if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
153 : XFS_RMAP_LEN_MAX)
154 : return false;
155 20248554 : if (r1->rm_flags != r2->rm_flags)
156 : return false;
157 5963184 : 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 608205040 : xchk_rtrmapbt_check_mergeable(
163 : struct xchk_btree *bs,
164 : struct xchk_rtrmap *cr,
165 : const struct xfs_rmap_irec *irec)
166 : {
167 608205040 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
168 : return;
169 :
170 608205040 : if (xchk_rtrmap_mergeable(cr, irec))
171 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
172 :
173 1216410080 : 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 605517435 : xchk_rtrmapbt_xref_rtrefc(
179 : struct xfs_scrub *sc,
180 : struct xfs_rmap_irec *irec)
181 : {
182 605517435 : xfs_rgblock_t fbno;
183 605517435 : xfs_extlen_t flen;
184 605517435 : bool is_inode;
185 605517435 : bool is_bmbt;
186 605517435 : bool is_attr;
187 605517435 : bool is_unwritten;
188 605517435 : int error;
189 :
190 605517435 : if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm))
191 0 : return;
192 :
193 605517435 : is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
194 605517435 : is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
195 605517435 : is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
196 605517435 : is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
197 :
198 : /* If this is shared, must be a data fork extent. */
199 605517435 : error = xfs_refcount_find_shared(sc->sr.refc_cur, irec->rm_startblock,
200 : irec->rm_blockcount, &fbno, &flen, false);
201 605413245 : if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur))
202 : return;
203 605449305 : 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 608189667 : xchk_rtrmapbt_xref(
210 : struct xfs_scrub *sc,
211 : struct xfs_rmap_irec *irec)
212 : {
213 608189667 : xfs_rtblock_t rtbno;
214 :
215 608189667 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
216 : return;
217 :
218 608213624 : rtbno = xfs_rgbno_to_rtb(sc->mp, sc->sr.rtg->rtg_rgno,
219 : irec->rm_startblock);
220 :
221 608223606 : xchk_xref_is_used_rt_space(sc, rtbno, irec->rm_blockcount);
222 608236357 : if (irec->rm_owner == XFS_RMAP_OWN_COW)
223 2718836 : xchk_xref_is_cow_staging(sc, irec->rm_startblock,
224 : irec->rm_blockcount);
225 : else
226 605517521 : xchk_rtrmapbt_xref_rtrefc(sc, irec);
227 : }
228 :
229 : /* Scrub a realtime rmapbt record. */
230 : STATIC int
231 608208924 : xchk_rtrmapbt_rec(
232 : struct xchk_btree *bs,
233 : const union xfs_btree_rec *rec)
234 : {
235 608208924 : struct xchk_rtrmap *cr = bs->private;
236 608208924 : struct xfs_rmap_irec irec;
237 :
238 1216422480 : if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
239 608183733 : xfs_rmap_check_irec(bs->cur, &irec) != NULL) {
240 39423 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
241 39423 : return 0;
242 : }
243 :
244 608214050 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
245 : return 0;
246 :
247 608214474 : xchk_rtrmapbt_check_mergeable(bs, cr, &irec);
248 608195486 : xchk_rtrmapbt_check_overlapping(bs, cr, &irec);
249 608198791 : xchk_rtrmapbt_xref(bs->sc, &irec);
250 608198791 : return 0;
251 : }
252 :
253 : /* Scrub the realtime rmap btree. */
254 : int
255 38579 : xchk_rtrmapbt(
256 : struct xfs_scrub *sc)
257 : {
258 38579 : struct xfs_owner_info oinfo;
259 38579 : struct xchk_rtrmap cr = { };
260 38579 : int error;
261 :
262 38579 : error = xchk_metadata_inode_forks(sc);
263 38579 : if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
264 : return error;
265 :
266 38579 : xfs_rmap_ino_bmbt_owner(&oinfo, sc->sr.rtg->rtg_rmapip->i_ino,
267 : XFS_DATA_FORK);
268 38579 : 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 3838017 : xchk_xref_has_no_rt_owner(
274 : struct xfs_scrub *sc,
275 : xfs_rgblock_t bno,
276 : xfs_extlen_t len)
277 : {
278 3838017 : enum xbtree_recpacking outcome;
279 3838017 : int error;
280 :
281 3838017 : if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
282 0 : return;
283 :
284 3838017 : error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome);
285 3837974 : if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
286 : return;
287 3837972 : 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 3916050 : xchk_xref_has_rt_owner(
294 : struct xfs_scrub *sc,
295 : xfs_rgblock_t bno,
296 : xfs_extlen_t len)
297 : {
298 3916050 : enum xbtree_recpacking outcome;
299 3916050 : int error;
300 :
301 3916050 : if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
302 0 : return;
303 :
304 3916050 : error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome);
305 3916155 : if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
306 : return;
307 3916174 : 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 5653966 : 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 5653966 : struct xfs_rmap_matches res;
320 5653966 : int error;
321 :
322 5653966 : if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm))
323 0 : return;
324 :
325 5653966 : error = xfs_rmap_count_owners(sc->sr.rmap_cur, bno, len, oinfo, &res);
326 5654102 : if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur))
327 : return;
328 5654096 : if (res.matches != 1)
329 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
330 5654096 : if (res.bad_non_owner_matches)
331 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
332 5654096 : if (res.non_owner_matches)
333 0 : xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0);
334 : }
|