1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2022-2023 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_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_defer.h"
13 #include "xfs_btree.h"
14 #include "xfs_log_format.h"
15 #include "xfs_trans.h"
16 #include "xfs_inode.h"
17 #include "xfs_inode_fork.h"
18 #include "xfs_alloc.h"
19 #include "xfs_bmap.h"
20 #include "xfs_rmap.h"
21 #include "xfs_refcount.h"
22 #include "xfs_quota.h"
23 #include "xfs_ialloc.h"
24 #include "xfs_ag.h"
25 #include "xfs_error.h"
26 #include "xfs_errortag.h"
27 #include "xfs_icache.h"
28 #include "xfs_refcount_btree.h"
29 #include "xfs_rtalloc.h"
30 #include "xfs_rtbitmap.h"
31 #include "xfs_rtgroup.h"
32 #include "xfs_bmap_util.h"
33 #include "scrub/xfs_scrub.h"
34 #include "scrub/scrub.h"
35 #include "scrub/common.h"
36 #include "scrub/trace.h"
37 #include "scrub/repair.h"
38 #include "scrub/bitmap.h"
39 #include "scrub/off_bitmap.h"
40 #include "scrub/fsb_bitmap.h"
41 #include "scrub/rtb_bitmap.h"
42 #include "scrub/reap.h"
43
44 /*
45 * CoW Fork Mapping Repair
46 * =======================
47 *
48 * Although CoW staging extents are owned by incore CoW inode forks, on disk
49 * they are owned by the refcount btree. The ondisk metadata does not record
50 * any ownership information, which limits what we can do to repair the
51 * mappings in the CoW fork. At most, we can replace ifork mappings that lack
52 * an entry in the refcount btree or are described by a reverse mapping record
53 * whose owner is not OWN_COW.
54 *
55 * Replacing extents is also tricky -- we can't touch written CoW fork extents
56 * since they are undergoing writeback, and delalloc extents do not require
57 * repair since they only exist incore. Hence the most we can do is find the
58 * bad parts of unwritten mappings, allocate a replacement set of blocks, and
59 * replace the incore mapping. We use the regular reaping process to unmap
60 * or free the discarded blocks, as appropriate.
61 */
62 struct xrep_cow {
63 struct xfs_scrub *sc;
64
65 /* Bitmap of file offset ranges that need replacing. */
66 struct xoff_bitmap bad_fileoffs;
67
68 /* Bitmap of fsblocks that were removed from the CoW fork. */
69 union {
70 struct xfsb_bitmap old_cowfork_fsblocks;
71 struct xrtb_bitmap old_cowfork_rtblocks;
72 };
73
74 /* CoW fork mappings used to scan for bad CoW staging extents. */
75 struct xfs_bmbt_irec irec;
76
77 /* refcount btree block number of irec.br_startblock */
78 unsigned int irec_startbno;
79
80 /* refcount btree block number of the next refcount record we expect */
81 unsigned int next_bno;
82 };
83
84 /*
85 * Mark the part of the file range that corresponds to the given physical
86 * space. Caller must ensure that the physical range is within xc->irec.
87 */
88 STATIC int
xrep_cow_mark_file_range(struct xrep_cow * xc,xfs_fsblock_t startblock,xfs_filblks_t blockcount)89 xrep_cow_mark_file_range(
90 struct xrep_cow *xc,
91 xfs_fsblock_t startblock,
92 xfs_filblks_t blockcount)
93 {
94 xfs_fileoff_t startoff;
95
96 startoff = xc->irec.br_startoff +
97 (startblock - xc->irec.br_startblock);
98
99 trace_xrep_cow_mark_file_range(xc->sc->ip, startblock, startoff,
100 blockcount);
101
102 return xoff_bitmap_set(&xc->bad_fileoffs, startoff, blockcount);
103 }
104
105 /*
106 * Trim @src to fit within the CoW fork mapping being examined, and put the
107 * result in @dst.
108 */
109 static inline void
xrep_cow_trim_refcount(struct xrep_cow * xc,struct xfs_refcount_irec * dst,const struct xfs_refcount_irec * src)110 xrep_cow_trim_refcount(
111 struct xrep_cow *xc,
112 struct xfs_refcount_irec *dst,
113 const struct xfs_refcount_irec *src)
114 {
115 unsigned int adj;
116
117 memcpy(dst, src, sizeof(*dst));
118
119 if (dst->rc_startblock < xc->irec_startbno) {
120 adj = xc->irec_startbno - dst->rc_startblock;
121 dst->rc_blockcount -= adj;
122 dst->rc_startblock += adj;
123 }
124
125 if (dst->rc_startblock + dst->rc_blockcount >
126 xc->irec_startbno + xc->irec.br_blockcount) {
127 adj = (dst->rc_startblock + dst->rc_blockcount) -
128 (xc->irec_startbno + xc->irec.br_blockcount);
129 dst->rc_blockcount -= adj;
130 }
131 }
132
133 /* Mark any shared CoW staging extents. */
134 STATIC int
xrep_cow_mark_shared_staging(struct xfs_btree_cur * cur,const struct xfs_refcount_irec * rec,void * priv)135 xrep_cow_mark_shared_staging(
136 struct xfs_btree_cur *cur,
137 const struct xfs_refcount_irec *rec,
138 void *priv)
139 {
140 struct xrep_cow *xc = priv;
141 struct xfs_refcount_irec rrec;
142
143 if (!xfs_refcount_check_domain(rec) ||
144 rec->rc_domain != XFS_REFC_DOMAIN_SHARED)
145 return -EFSCORRUPTED;
146
147 xrep_cow_trim_refcount(xc, &rrec, rec);
148
149 return xrep_cow_mark_file_range(xc,
150 xfs_gbno_to_fsb(cur->bc_group, rrec.rc_startblock),
151 rrec.rc_blockcount);
152 }
153
154 /*
155 * Mark any portion of the CoW fork file offset range where there is not a CoW
156 * staging extent record in the refcountbt, and keep a record of where we did
157 * find correct refcountbt records. Staging records are always cleaned out at
158 * mount time, so any two inodes trying to map the same staging area would have
159 * already taken the fs down due to refcount btree verifier errors. Hence this
160 * inode should be the sole creator of the staging extent records ondisk.
161 */
162 STATIC int
xrep_cow_mark_missing_staging(struct xfs_btree_cur * cur,const struct xfs_refcount_irec * rec,void * priv)163 xrep_cow_mark_missing_staging(
164 struct xfs_btree_cur *cur,
165 const struct xfs_refcount_irec *rec,
166 void *priv)
167 {
168 struct xrep_cow *xc = priv;
169 struct xfs_refcount_irec rrec;
170 int error;
171
172 if (!xfs_refcount_check_domain(rec) ||
173 rec->rc_domain != XFS_REFC_DOMAIN_COW)
174 return -EFSCORRUPTED;
175
176 xrep_cow_trim_refcount(xc, &rrec, rec);
177
178 if (xc->next_bno >= rrec.rc_startblock)
179 goto next;
180
181 error = xrep_cow_mark_file_range(xc,
182 xfs_gbno_to_fsb(cur->bc_group, xc->next_bno),
183 rrec.rc_startblock - xc->next_bno);
184 if (error)
185 return error;
186
187 next:
188 xc->next_bno = rrec.rc_startblock + rrec.rc_blockcount;
189 return 0;
190 }
191
192 /*
193 * Mark any area that does not correspond to a CoW staging rmap. These are
194 * cross-linked areas that must be avoided.
195 */
196 STATIC int
xrep_cow_mark_missing_staging_rmap(struct xfs_btree_cur * cur,const struct xfs_rmap_irec * rec,void * priv)197 xrep_cow_mark_missing_staging_rmap(
198 struct xfs_btree_cur *cur,
199 const struct xfs_rmap_irec *rec,
200 void *priv)
201 {
202 struct xrep_cow *xc = priv;
203 xfs_agblock_t rec_bno;
204 xfs_extlen_t rec_len;
205 unsigned int adj;
206
207 if (rec->rm_owner == XFS_RMAP_OWN_COW)
208 return 0;
209
210 rec_bno = rec->rm_startblock;
211 rec_len = rec->rm_blockcount;
212 if (rec_bno < xc->irec_startbno) {
213 adj = xc->irec_startbno - rec_bno;
214 rec_len -= adj;
215 rec_bno += adj;
216 }
217
218 if (rec_bno + rec_len > xc->irec_startbno + xc->irec.br_blockcount) {
219 adj = (rec_bno + rec_len) -
220 (xc->irec_startbno + xc->irec.br_blockcount);
221 rec_len -= adj;
222 }
223
224 return xrep_cow_mark_file_range(xc,
225 xfs_gbno_to_fsb(cur->bc_group, rec_bno), rec_len);
226 }
227
228 /*
229 * Trim the start and end of the current mapping by up to 1/4 of the length
230 * and mark that as "bad" to test the cow fork repair mechanism.
231 */
232 static inline int
xrep_cow_debug_replacement(struct xrep_cow * xc)233 xrep_cow_debug_replacement(
234 struct xrep_cow *xc)
235 {
236 xfs_fsblock_t fsbno = xc->irec.br_startblock;
237 xfs_extlen_t len = xc->irec.br_blockcount;
238 uint32_t trim;
239
240 /* get_random_u32_below requires a nonzero argument */
241 trim = len > 4 ? get_random_u32_below(len / 4) : 0;
242 len -= trim;
243
244 trim = len > 4 ? get_random_u32_below(len / 4) : 0;
245 fsbno += trim;
246 len -= trim;
247
248 return xrep_cow_mark_file_range(xc, fsbno, len);
249 }
250
251 /*
252 * Find any part of the CoW fork mapping that isn't a single-owner CoW staging
253 * extent and mark the corresponding part of the file range in the bitmap.
254 */
255 STATIC int
xrep_cow_find_bad(struct xrep_cow * xc)256 xrep_cow_find_bad(
257 struct xrep_cow *xc)
258 {
259 struct xfs_refcount_irec rc_low = { 0 };
260 struct xfs_refcount_irec rc_high = { 0 };
261 struct xfs_rmap_irec rm_low = { 0 };
262 struct xfs_rmap_irec rm_high = { 0 };
263 struct xfs_perag *pag;
264 struct xfs_scrub *sc = xc->sc;
265 xfs_agnumber_t agno;
266 int error;
267
268 agno = XFS_FSB_TO_AGNO(sc->mp, xc->irec.br_startblock);
269 xc->irec_startbno = XFS_FSB_TO_AGBNO(sc->mp, xc->irec.br_startblock);
270
271 pag = xfs_perag_get(sc->mp, agno);
272 if (!pag)
273 return -EFSCORRUPTED;
274
275 error = xrep_ag_init(sc, pag, &sc->sa);
276 if (error)
277 goto out_pag;
278
279 /* Mark any CoW fork extents that are shared. */
280 rc_low.rc_startblock = xc->irec_startbno;
281 rc_high.rc_startblock = xc->irec_startbno + xc->irec.br_blockcount - 1;
282 rc_low.rc_domain = rc_high.rc_domain = XFS_REFC_DOMAIN_SHARED;
283 error = xfs_refcount_query_range(sc->sa.refc_cur, &rc_low, &rc_high,
284 xrep_cow_mark_shared_staging, xc);
285 if (error)
286 goto out_sa;
287
288 /* Make sure there are CoW staging extents for the whole mapping. */
289 rc_low.rc_startblock = xc->irec_startbno;
290 rc_high.rc_startblock = xc->irec_startbno + xc->irec.br_blockcount - 1;
291 rc_low.rc_domain = rc_high.rc_domain = XFS_REFC_DOMAIN_COW;
292 xc->next_bno = xc->irec_startbno;
293 error = xfs_refcount_query_range(sc->sa.refc_cur, &rc_low, &rc_high,
294 xrep_cow_mark_missing_staging, xc);
295 if (error)
296 goto out_sa;
297
298 if (xc->next_bno < xc->irec_startbno + xc->irec.br_blockcount) {
299 error = xrep_cow_mark_file_range(xc,
300 xfs_agbno_to_fsb(pag, xc->next_bno),
301 xc->irec_startbno + xc->irec.br_blockcount -
302 xc->next_bno);
303 if (error)
304 goto out_sa;
305 }
306
307 /* Mark any area has an rmap that isn't a COW staging extent. */
308 rm_low.rm_startblock = xc->irec_startbno;
309 memset(&rm_high, 0xFF, sizeof(rm_high));
310 rm_high.rm_startblock = xc->irec_startbno + xc->irec.br_blockcount - 1;
311 error = xfs_rmap_query_range(sc->sa.rmap_cur, &rm_low, &rm_high,
312 xrep_cow_mark_missing_staging_rmap, xc);
313 if (error)
314 goto out_sa;
315
316 /*
317 * If userspace is forcing us to rebuild the CoW fork or someone turned
318 * on the debugging knob, replace everything in the CoW fork.
319 */
320 if (XFS_TEST_ERROR(sc->mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR))
321 error = xrep_cow_debug_replacement(xc);
322 else if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD)
323 error = xrep_cow_mark_file_range(xc, xc->irec.br_startblock,
324 xc->irec.br_blockcount);
325
326 out_sa:
327 xchk_ag_free(sc, &sc->sa);
328 out_pag:
329 xfs_perag_put(pag);
330 return error;
331 }
332
333 /*
334 * Find any part of the CoW fork mapping that isn't a single-owner CoW staging
335 * extent and mark the corresponding part of the file range in the bitmap.
336 */
337 STATIC int
xrep_cow_find_bad_rt(struct xrep_cow * xc)338 xrep_cow_find_bad_rt(
339 struct xrep_cow *xc)
340 {
341 struct xfs_refcount_irec rc_low = { 0 };
342 struct xfs_refcount_irec rc_high = { 0 };
343 struct xfs_rmap_irec rm_low = { 0 };
344 struct xfs_rmap_irec rm_high = { 0 };
345 struct xfs_scrub *sc = xc->sc;
346 struct xfs_rtgroup *rtg;
347 int error = 0;
348
349 xc->irec_startbno = xfs_rtb_to_rgbno(sc->mp, xc->irec.br_startblock);
350
351 rtg = xfs_rtgroup_get(sc->mp,
352 xfs_rtb_to_rgno(sc->mp, xc->irec.br_startblock));
353 if (!rtg)
354 return -EFSCORRUPTED;
355
356 error = xrep_rtgroup_init(sc, rtg, &sc->sr,
357 XFS_RTGLOCK_RMAP | XFS_RTGLOCK_REFCOUNT);
358 if (error)
359 goto out_rtg;
360
361 /* Mark any CoW fork extents that are shared. */
362 rc_low.rc_startblock = xc->irec_startbno;
363 rc_high.rc_startblock = xc->irec_startbno + xc->irec.br_blockcount - 1;
364 rc_low.rc_domain = rc_high.rc_domain = XFS_REFC_DOMAIN_SHARED;
365 error = xfs_refcount_query_range(sc->sr.refc_cur, &rc_low, &rc_high,
366 xrep_cow_mark_shared_staging, xc);
367 if (error)
368 goto out_sr;
369
370 /* Make sure there are CoW staging extents for the whole mapping. */
371 rc_low.rc_startblock = xc->irec_startbno;
372 rc_high.rc_startblock = xc->irec_startbno + xc->irec.br_blockcount - 1;
373 rc_low.rc_domain = rc_high.rc_domain = XFS_REFC_DOMAIN_COW;
374 xc->next_bno = xc->irec_startbno;
375 error = xfs_refcount_query_range(sc->sr.refc_cur, &rc_low, &rc_high,
376 xrep_cow_mark_missing_staging, xc);
377 if (error)
378 goto out_sr;
379
380 if (xc->next_bno < xc->irec_startbno + xc->irec.br_blockcount) {
381 error = xrep_cow_mark_file_range(xc,
382 xfs_rgbno_to_rtb(rtg, xc->next_bno),
383 xc->irec_startbno + xc->irec.br_blockcount -
384 xc->next_bno);
385 if (error)
386 goto out_sr;
387 }
388
389 /* Mark any area has an rmap that isn't a COW staging extent. */
390 rm_low.rm_startblock = xc->irec_startbno;
391 memset(&rm_high, 0xFF, sizeof(rm_high));
392 rm_high.rm_startblock = xc->irec_startbno + xc->irec.br_blockcount - 1;
393 error = xfs_rmap_query_range(sc->sr.rmap_cur, &rm_low, &rm_high,
394 xrep_cow_mark_missing_staging_rmap, xc);
395 if (error)
396 goto out_sr;
397
398 /*
399 * If userspace is forcing us to rebuild the CoW fork or someone
400 * turned on the debugging knob, replace everything in the
401 * CoW fork and then scan for staging extents in the refcountbt.
402 */
403 if (XFS_TEST_ERROR(sc->mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR))
404 error = xrep_cow_debug_replacement(xc);
405 else if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD)
406 error = xrep_cow_mark_file_range(xc, xc->irec.br_startblock,
407 xc->irec.br_blockcount);
408
409 out_sr:
410 xchk_rtgroup_btcur_free(&sc->sr);
411 xchk_rtgroup_free(sc, &sc->sr);
412 out_rtg:
413 xfs_rtgroup_put(rtg);
414 return error;
415 }
416
417 /*
418 * Allocate a replacement CoW staging extent of up to the given number of
419 * blocks, and fill out the mapping.
420 */
421 STATIC int
xrep_cow_alloc(struct xfs_scrub * sc,struct xfs_bmbt_irec * del)422 xrep_cow_alloc(
423 struct xfs_scrub *sc,
424 struct xfs_bmbt_irec *del)
425 {
426 struct xfs_alloc_arg args = {
427 .tp = sc->tp,
428 .mp = sc->mp,
429 .oinfo = XFS_RMAP_OINFO_SKIP_UPDATE,
430 .minlen = 1,
431 .maxlen = del->br_blockcount,
432 .prod = 1,
433 .resv = XFS_AG_RESV_NONE,
434 .datatype = XFS_ALLOC_USERDATA,
435 };
436 int error;
437
438 error = xfs_trans_reserve_more(sc->tp, del->br_blockcount, 0);
439 if (error)
440 return error;
441
442 error = xfs_alloc_vextent_start_ag(&args, XFS_INODE_TO_FSB(sc->ip));
443 if (error)
444 return error;
445 if (args.fsbno == NULLFSBLOCK)
446 return -ENOSPC;
447
448 xfs_refcount_alloc_cow_extent(sc->tp, false, args.fsbno, args.len);
449
450 del->br_startblock = args.fsbno;
451 del->br_blockcount = args.len;
452 return 0;
453 }
454
455 /*
456 * Allocate a replacement rt CoW staging extent of up to the given number of
457 * blocks, and fill out the mapping.
458 */
459 STATIC int
xrep_cow_alloc_rt(struct xfs_scrub * sc,struct xfs_bmbt_irec * del)460 xrep_cow_alloc_rt(
461 struct xfs_scrub *sc,
462 struct xfs_bmbt_irec *del)
463 {
464 xfs_fsblock_t fsbno;
465 xfs_rtxlen_t maxrtx =
466 min(U32_MAX, xfs_blen_to_rtbxlen(sc->mp, del->br_blockcount));
467 xfs_extlen_t len;
468 int error;
469
470 error = xfs_trans_reserve_more(sc->tp, 0, maxrtx);
471 if (error)
472 return error;
473
474 error = xfs_rtallocate_rtgs(sc->tp, NULLRTBLOCK, 1, maxrtx, 1, false,
475 false, &fsbno, &len);
476 if (error)
477 return error;
478
479 xfs_refcount_alloc_cow_extent(sc->tp, true, fsbno, len);
480
481 del->br_startblock = fsbno;
482 del->br_blockcount = len;
483 return 0;
484 }
485
486 /*
487 * Look up the current CoW fork mapping so that we only allocate enough to
488 * replace a single mapping. If we don't find a mapping that covers the start
489 * of the file range, or we find a delalloc or written extent, something is
490 * seriously wrong, since we didn't drop the ILOCK.
491 */
492 static inline int
xrep_cow_find_mapping(struct xrep_cow * xc,struct xfs_iext_cursor * icur,xfs_fileoff_t badoff,xfs_extlen_t badlen,struct xfs_bmbt_irec * got,struct xfs_bmbt_irec * rep)493 xrep_cow_find_mapping(
494 struct xrep_cow *xc,
495 struct xfs_iext_cursor *icur,
496 xfs_fileoff_t badoff,
497 xfs_extlen_t badlen,
498 struct xfs_bmbt_irec *got,
499 struct xfs_bmbt_irec *rep)
500 {
501 struct xfs_inode *ip = xc->sc->ip;
502 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK);
503
504 if (!xfs_iext_lookup_extent(ip, ifp, badoff, icur, got))
505 goto bad;
506 memcpy(rep, got, sizeof(*rep));
507
508 if (got->br_startoff > badoff)
509 goto bad;
510
511 if (isnullstartblock(got->br_startblock))
512 goto bad;
513
514 if (xfs_bmap_is_written_extent(got))
515 goto bad;
516
517 if (got->br_startoff < badoff) {
518 const int64_t delta = badoff - got->br_startoff;
519
520 rep->br_blockcount -= delta;
521 rep->br_startoff += delta;
522 rep->br_startblock += delta;
523 }
524
525 if (got->br_startoff + got->br_blockcount > badoff + badlen) {
526 const int64_t delta = (got->br_startoff + got->br_blockcount) -
527 (badoff + badlen);
528
529 rep->br_blockcount -= delta;
530 }
531
532 if (got->br_blockcount == 0)
533 goto bad;
534
535 return 0;
536 bad:
537 ASSERT(0);
538 return -EFSCORRUPTED;
539 }
540
541 /*
542 * Replace the unwritten CoW staging extent backing the given file range with a
543 * new space extent that isn't as problematic.
544 */
545 STATIC int
xrep_cow_replace_range(struct xrep_cow * xc,xfs_fileoff_t startoff,xfs_extlen_t * blockcount)546 xrep_cow_replace_range(
547 struct xrep_cow *xc,
548 xfs_fileoff_t startoff,
549 xfs_extlen_t *blockcount)
550 {
551 struct xfs_iext_cursor icur;
552 struct xfs_bmbt_irec got, rep;
553 struct xfs_scrub *sc = xc->sc;
554 xfs_fsblock_t old_fsbno;
555 int error;
556
557 /*
558 * Put the existing CoW fork mapping in @got, and put in @rep the
559 * contents of @got trimmed to @startoff/@blockcount. We only want
560 * to replace the bad region, and only one mapping at a time.
561 */
562 error = xrep_cow_find_mapping(xc, &icur, startoff, *blockcount, &got,
563 &rep);
564 if (error)
565 return error;
566 old_fsbno = rep.br_startblock;
567
568 /*
569 * Allocate a replacement extent. If we don't fill all the blocks,
570 * shorten the quantity that will be deleted in this step.
571 */
572 if (XFS_IS_REALTIME_INODE(sc->ip))
573 error = xrep_cow_alloc_rt(sc, &rep);
574 else
575 error = xrep_cow_alloc(sc, &rep);
576 if (error)
577 return error;
578
579 /*
580 * Replace the old mapping with the new one, and commit the metadata
581 * changes made so far.
582 */
583 xfs_bmap_replace_cow_mapping(sc->ip, &icur, &got, &rep);
584
585 xfs_inode_set_cowblocks_tag(sc->ip);
586 error = xfs_defer_finish(&sc->tp);
587 if (error)
588 return error;
589
590 /* Note the old CoW staging extents; we'll reap them all later. */
591 if (XFS_IS_REALTIME_INODE(sc->ip))
592 error = xrtb_bitmap_set(&xc->old_cowfork_rtblocks, old_fsbno,
593 rep.br_blockcount);
594 else
595 error = xfsb_bitmap_set(&xc->old_cowfork_fsblocks, old_fsbno,
596 rep.br_blockcount);
597 if (error)
598 return error;
599
600 *blockcount = rep.br_blockcount;
601 return 0;
602 }
603
604 /*
605 * Replace a bad part of an unwritten CoW staging extent with a fresh delalloc
606 * reservation.
607 */
608 STATIC int
xrep_cow_replace(uint64_t startoff,uint64_t blockcount,void * priv)609 xrep_cow_replace(
610 uint64_t startoff,
611 uint64_t blockcount,
612 void *priv)
613 {
614 struct xrep_cow *xc = priv;
615 int error = 0;
616
617 while (blockcount > 0) {
618 xfs_extlen_t len = min_t(xfs_filblks_t, blockcount,
619 XFS_MAX_BMBT_EXTLEN);
620
621 error = xrep_cow_replace_range(xc, startoff, &len);
622 if (error)
623 break;
624
625 blockcount -= len;
626 startoff += len;
627 }
628
629 return error;
630 }
631
632 /*
633 * Repair an inode's CoW fork. The CoW fork is an in-core structure, so
634 * there's no btree to rebuid. Instead, we replace any mappings that are
635 * cross-linked or lack ondisk CoW fork records in the refcount btree.
636 */
637 int
xrep_bmap_cow(struct xfs_scrub * sc)638 xrep_bmap_cow(
639 struct xfs_scrub *sc)
640 {
641 struct xrep_cow *xc;
642 struct xfs_iext_cursor icur;
643 struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, XFS_COW_FORK);
644 int error;
645
646 if (!xfs_has_rmapbt(sc->mp) || !xfs_has_reflink(sc->mp))
647 return -EOPNOTSUPP;
648
649 if (!ifp)
650 return 0;
651
652 /*
653 * Realtime files with large extent sizes are not supported because
654 * we could encounter an CoW mapping that has been partially written
655 * out *and* requires replacement, and there's no solution to that.
656 */
657 if (xfs_inode_has_bigrtalloc(sc->ip))
658 return -EOPNOTSUPP;
659
660 /* Metadata inodes aren't supposed to have data on the rt volume. */
661 if (xfs_is_metadir_inode(sc->ip) && XFS_IS_REALTIME_INODE(sc->ip))
662 return -EOPNOTSUPP;
663
664 /*
665 * If we're somehow not in extents format, then reinitialize it to
666 * an empty extent mapping fork and exit.
667 */
668 if (ifp->if_format != XFS_DINODE_FMT_EXTENTS) {
669 ifp->if_format = XFS_DINODE_FMT_EXTENTS;
670 ifp->if_nextents = 0;
671 return 0;
672 }
673
674 xc = kzalloc_obj(struct xrep_cow, XCHK_GFP_FLAGS);
675 if (!xc)
676 return -ENOMEM;
677
678 xfs_trans_ijoin(sc->tp, sc->ip, 0);
679
680 xc->sc = sc;
681 xoff_bitmap_init(&xc->bad_fileoffs);
682 if (XFS_IS_REALTIME_INODE(sc->ip))
683 xrtb_bitmap_init(&xc->old_cowfork_rtblocks);
684 else
685 xfsb_bitmap_init(&xc->old_cowfork_fsblocks);
686
687 for_each_xfs_iext(ifp, &icur, &xc->irec) {
688 if (xchk_should_terminate(sc, &error))
689 goto out_bitmap;
690
691 /*
692 * delalloc reservations only exist incore, so there is no
693 * ondisk metadata that we can examine. Hence we leave them
694 * alone.
695 */
696 if (isnullstartblock(xc->irec.br_startblock))
697 continue;
698
699 /*
700 * COW fork extents are only in the written state if writeback
701 * is actively writing to disk. We cannot restart the write
702 * at a different disk address since we've already issued the
703 * IO, so we leave these alone and hope for the best.
704 */
705 if (xfs_bmap_is_written_extent(&xc->irec))
706 continue;
707
708 if (XFS_IS_REALTIME_INODE(sc->ip))
709 error = xrep_cow_find_bad_rt(xc);
710 else
711 error = xrep_cow_find_bad(xc);
712 if (error)
713 goto out_bitmap;
714 }
715
716 /* Replace any bad unwritten mappings with fresh reservations. */
717 error = xoff_bitmap_walk(&xc->bad_fileoffs, xrep_cow_replace, xc);
718 if (error)
719 goto out_bitmap;
720
721 /*
722 * Reap as many of the old CoW blocks as we can. They are owned ondisk
723 * by the refcount btree, not the inode, so it is correct to treat them
724 * like inode metadata.
725 */
726 if (XFS_IS_REALTIME_INODE(sc->ip))
727 error = xrep_reap_rtblocks(sc, &xc->old_cowfork_rtblocks,
728 &XFS_RMAP_OINFO_COW);
729 else
730 error = xrep_reap_fsblocks(sc, &xc->old_cowfork_fsblocks,
731 &XFS_RMAP_OINFO_COW);
732 if (error)
733 goto out_bitmap;
734
735 out_bitmap:
736 if (XFS_IS_REALTIME_INODE(sc->ip))
737 xrtb_bitmap_destroy(&xc->old_cowfork_rtblocks);
738 else
739 xfsb_bitmap_destroy(&xc->old_cowfork_fsblocks);
740 xoff_bitmap_destroy(&xc->bad_fileoffs);
741 kfree(xc);
742 return error;
743 }
744