Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2020-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_btree.h"
13 : #include "xfs_log_format.h"
14 : #include "xfs_trans.h"
15 : #include "xfs_rtalloc.h"
16 : #include "xfs_inode.h"
17 : #include "xfs_bit.h"
18 : #include "xfs_bmap.h"
19 : #include "xfs_bmap_btree.h"
20 : #include "xfs_rmap.h"
21 : #include "xfs_rtrmap_btree.h"
22 : #include "xfs_swapext.h"
23 : #include "xfs_rtbitmap.h"
24 : #include "xfs_rtgroup.h"
25 : #include "xfs_refcount.h"
26 : #include "scrub/scrub.h"
27 : #include "scrub/common.h"
28 : #include "scrub/trace.h"
29 : #include "scrub/repair.h"
30 : #include "scrub/xfile.h"
31 : #include "scrub/tempfile.h"
32 : #include "scrub/tempswap.h"
33 : #include "scrub/reap.h"
34 :
35 : /*
36 : * We use an xfile to construct new bitmap blocks for the portion of the
37 : * rtbitmap file that we're replacing. Whereas the ondisk bitmap must be
38 : * accessed through the buffer cache, the xfile bitmap supports direct
39 : * word-level accesses. Therefore, we create a small abstraction for linear
40 : * access.
41 : */
42 : typedef unsigned long long xrep_wordoff_t;
43 : typedef unsigned int xrep_wordcnt_t;
44 :
45 : struct xrep_rgbmp {
46 : struct xfs_scrub *sc;
47 :
48 : /* file offset inside the rtbitmap where we start swapping */
49 : xfs_fileoff_t group_rbmoff;
50 :
51 : /* number of rtbitmap blocks for this group */
52 : xfs_filblks_t group_rbmlen;
53 :
54 : /* The next rtgroup block we expect to see during our rtrmapbt walk. */
55 : xfs_rgblock_t next_rgbno;
56 :
57 : /* rtword position of xfile as we write buffers to disk. */
58 : xrep_wordoff_t prep_wordoff;
59 : };
60 :
61 : /* Mask to round an rtx down to the nearest bitmap word. */
62 : #define XREP_RTBMP_WORDMASK ((1ULL << XFS_NBWORDLOG) - 1)
63 :
64 : /* Set up to repair the realtime bitmap for this group. */
65 : int
66 37459 : xrep_setup_rgbitmap(
67 : struct xfs_scrub *sc,
68 : unsigned int *resblks)
69 : {
70 37459 : struct xfs_mount *mp = sc->mp;
71 37459 : char *descr;
72 37459 : unsigned long long blocks = 0;
73 37459 : unsigned long long rtbmp_words;
74 37459 : size_t bufsize = mp->m_sb.sb_blocksize;
75 37459 : int error;
76 :
77 37459 : error = xrep_tempfile_create(sc, S_IFREG);
78 37459 : if (error)
79 : return error;
80 :
81 : /* Create an xfile to hold our reconstructed bitmap. */
82 37459 : rtbmp_words = xfs_rtbitmap_wordcount(mp, mp->m_sb.sb_rextents);
83 37459 : descr = xchk_xfile_rtgroup_descr(sc, "bitmap file");
84 37459 : error = xfile_create(descr, rtbmp_words << XFS_WORDLOG, &sc->xfile);
85 37459 : kfree(descr);
86 37459 : if (error)
87 : return error;
88 :
89 37459 : bufsize = max(bufsize, sizeof(struct xrep_tempswap));
90 :
91 : /*
92 : * Allocate a memory buffer for faster creation of new bitmap
93 : * blocks.
94 : */
95 37459 : sc->buf = kvmalloc(bufsize, XCHK_GFP_FLAGS);
96 37459 : if (!sc->buf)
97 : return -ENOMEM;
98 :
99 : /*
100 : * Reserve enough blocks to write out a completely new bitmap file,
101 : * plus twice as many blocks as we would need if we can only allocate
102 : * one block per data fork mapping. This should cover the
103 : * preallocation of the temporary file and swapping the extent
104 : * mappings.
105 : *
106 : * We cannot use xfs_swapext_estimate because we have not yet
107 : * constructed the replacement bitmap and therefore do not know how
108 : * many extents it will use. By the time we do, we will have a dirty
109 : * transaction (which we cannot drop because we cannot drop the
110 : * rtbitmap ILOCK) and cannot ask for more reservation.
111 : */
112 37459 : blocks = mp->m_sb.sb_rbmblocks;
113 37459 : blocks += xfs_bmbt_calc_size(mp, blocks) * 2;
114 37459 : if (blocks > UINT_MAX)
115 : return -EOPNOTSUPP;
116 :
117 37459 : *resblks += blocks;
118 :
119 : /*
120 : * Grab support for atomic extent swapping before we allocate any
121 : * transactions or grab ILOCKs.
122 : */
123 37459 : return xrep_tempswap_grab_log_assist(sc);
124 : }
125 :
126 : static inline xrep_wordoff_t
127 : rtx_to_wordoff(
128 : struct xfs_mount *mp,
129 : xfs_rtxnum_t rtx)
130 : {
131 939340 : return rtx >> XFS_NBWORDLOG;
132 : }
133 :
134 : static inline xrep_wordcnt_t
135 : rtxlen_to_wordcnt(
136 : xfs_rtxlen_t rtxlen)
137 : {
138 52545 : return rtxlen >> XFS_NBWORDLOG;
139 : }
140 :
141 : /* Helper functions to record rtwords in an xfile. */
142 :
143 : static inline int
144 839620 : xfbmp_load(
145 : struct xrep_rgbmp *rb,
146 : xrep_wordoff_t wordoff,
147 : xfs_rtword_t *word)
148 : {
149 839620 : union xfs_rtword_ondisk urk;
150 839620 : int error;
151 :
152 839620 : error = xfile_obj_load(rb->sc->xfile, &urk,
153 : sizeof(union xfs_rtword_ondisk),
154 839620 : wordoff << XFS_WORDLOG);
155 839620 : if (error)
156 : return error;
157 :
158 839620 : *word = xfs_rtbitmap_getword(rb->sc->mp, &urk);
159 839620 : return 0;
160 : }
161 :
162 : static inline int
163 839620 : xfbmp_store(
164 : struct xrep_rgbmp *rb,
165 : xrep_wordoff_t wordoff,
166 : const xfs_rtword_t word)
167 : {
168 839620 : union xfs_rtword_ondisk urk;
169 :
170 839620 : xfs_rtbitmap_setword(rb->sc->mp, &urk, word);
171 1679240 : return xfile_obj_store(rb->sc->xfile, &urk,
172 : sizeof(union xfs_rtword_ondisk),
173 839620 : wordoff << XFS_WORDLOG);
174 : }
175 :
176 : static inline int
177 1446618 : xfbmp_copyin(
178 : struct xrep_rgbmp *rb,
179 : xrep_wordoff_t wordoff,
180 : const union xfs_rtword_ondisk *word,
181 : xrep_wordcnt_t nr_words)
182 : {
183 2893236 : return xfile_obj_store(rb->sc->xfile, word, nr_words << XFS_WORDLOG,
184 1446618 : wordoff << XFS_WORDLOG);
185 : }
186 :
187 : static inline int
188 1806265 : xfbmp_copyout(
189 : struct xrep_rgbmp *rb,
190 : xrep_wordoff_t wordoff,
191 : union xfs_rtword_ondisk *word,
192 : xrep_wordcnt_t nr_words)
193 : {
194 3612530 : return xfile_obj_load(rb->sc->xfile, word, nr_words << XFS_WORDLOG,
195 1806265 : wordoff << XFS_WORDLOG);
196 : }
197 :
198 : /*
199 : * Preserve the portions of the rtbitmap block for the start of this rtgroup
200 : * that map to the previous rtgroup.
201 : */
202 : STATIC int
203 32841 : xrep_rgbitmap_load_before(
204 : struct xrep_rgbmp *rb)
205 : {
206 32841 : struct xfs_scrub *sc = rb->sc;
207 32841 : struct xfs_mount *mp = sc->mp;
208 32841 : struct xfs_rtgroup *rtg = sc->sr.rtg;
209 32841 : struct xfs_buf *bp;
210 32841 : xrep_wordoff_t wordoff;
211 32841 : xfs_rtblock_t group_rtbno;
212 32841 : xfs_rtxnum_t group_rtx, rbmoff_rtx;
213 32841 : xfs_rtword_t ondisk_word;
214 32841 : xfs_rtword_t xfile_word;
215 32841 : xfs_rtword_t mask;
216 32841 : xrep_wordcnt_t wordcnt;
217 32841 : int bit;
218 32841 : int error;
219 :
220 : /*
221 : * Compute the file offset within the rtbitmap block that corresponds
222 : * to the start of this group, and decide if we need to read blocks
223 : * from the group before this one.
224 : */
225 32841 : group_rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno, 0);
226 32841 : group_rtx = xfs_rtb_to_rtxt(mp, group_rtbno);
227 :
228 32841 : rb->group_rbmoff = xfs_rtx_to_rbmblock(mp, group_rtx);
229 32841 : rbmoff_rtx = xfs_rbmblock_to_rtx(mp, rb->group_rbmoff);
230 32841 : rb->prep_wordoff = rtx_to_wordoff(mp, rbmoff_rtx);
231 :
232 32841 : trace_xrep_rgbitmap_load(rtg, rb->group_rbmoff, rbmoff_rtx,
233 : group_rtx - 1);
234 :
235 32841 : if (rbmoff_rtx == group_rtx)
236 : return 0;
237 :
238 26272 : error = xfs_rtbuf_get(mp, sc->tp, rb->group_rbmoff, 0, &bp);
239 26272 : if (error) {
240 : /*
241 : * Reading the existing rbmblock failed, and we must deal with
242 : * the part of the rtbitmap block that corresponds to the
243 : * previous group. The most conservative option is to fill
244 : * that part of the bitmap with zeroes so that it won't get
245 : * allocated. The xfile contains zeroes already, so we can
246 : * return.
247 : */
248 : return 0;
249 : }
250 :
251 : /*
252 : * Copy full rtbitmap words into memory from the beginning of the
253 : * ondisk block until we get to the word that corresponds to the start
254 : * of this group.
255 : */
256 26272 : wordoff = rtx_to_wordoff(mp, rbmoff_rtx);
257 26272 : wordcnt = rtxlen_to_wordcnt(group_rtx - rbmoff_rtx);
258 26272 : if (wordcnt > 0) {
259 26272 : union xfs_rtword_ondisk *p;
260 :
261 26272 : p = xfs_rbmblock_wordptr(bp, 0);
262 26272 : error = xfbmp_copyin(rb, wordoff, p, wordcnt);
263 26272 : if (error)
264 0 : goto out_rele;
265 :
266 26272 : trace_xrep_rgbitmap_load_words(mp, rb->group_rbmoff, wordoff,
267 : wordcnt);
268 26272 : wordoff += wordcnt;
269 : }
270 :
271 : /*
272 : * Compute the bit position of the first rtextent of this group. If
273 : * the bit position is zero, we don't have to RMW a partial word and
274 : * move to the next step.
275 : */
276 26272 : bit = group_rtx & XREP_RTBMP_WORDMASK;
277 26272 : if (bit == 0)
278 26272 : goto out_rele;
279 :
280 : /*
281 : * Create a mask of the bits that we want to load from disk. These
282 : * bits track space in a different rtgroup, which is why we must
283 : * preserve them even as we replace parts of the bitmap.
284 : */
285 0 : mask = ~((((xfs_rtword_t)1 << (XFS_NBWORD - bit)) - 1) << bit);
286 :
287 0 : error = xfbmp_load(rb, wordoff, &xfile_word);
288 0 : if (error)
289 0 : goto out_rele;
290 0 : ondisk_word = xfs_rtbitmap_getword(mp,
291 : xfs_rbmblock_wordptr(bp, wordcnt));
292 :
293 0 : trace_xrep_rgbitmap_load_word(mp, wordoff, bit, ondisk_word,
294 : xfile_word, mask);
295 :
296 0 : xfile_word &= ~mask;
297 0 : xfile_word |= (ondisk_word & mask);
298 :
299 0 : error = xfbmp_store(rb, wordoff, xfile_word);
300 0 : if (error)
301 0 : goto out_rele;
302 :
303 0 : out_rele:
304 26272 : xfs_trans_brelse(sc->tp, bp);
305 26272 : return error;
306 : }
307 :
308 : /*
309 : * Preserve the portions of the rtbitmap block for the end of this rtgroup
310 : * that map to the next rtgroup.
311 : */
312 : STATIC int
313 32841 : xrep_rgbitmap_load_after(
314 : struct xrep_rgbmp *rb)
315 : {
316 32841 : struct xfs_scrub *sc = rb->sc;
317 32841 : struct xfs_mount *mp = rb->sc->mp;
318 32841 : struct xfs_rtgroup *rtg = rb->sc->sr.rtg;
319 32841 : struct xfs_buf *bp;
320 32841 : xrep_wordoff_t wordoff;
321 32841 : xfs_rtblock_t last_rtbno;
322 32841 : xfs_rtxnum_t last_group_rtx, last_rbmblock_rtx;
323 32841 : xfs_fileoff_t last_group_rbmoff;
324 32841 : xfs_rtword_t ondisk_word;
325 32841 : xfs_rtword_t xfile_word;
326 32841 : xfs_rtword_t mask;
327 32841 : xrep_wordcnt_t wordcnt;
328 32841 : unsigned int last_group_word;
329 32841 : int bit;
330 32841 : int error;
331 :
332 32841 : last_rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno,
333 32841 : rtg->rtg_blockcount - 1);
334 32841 : last_group_rtx = xfs_rtb_to_rtxt(mp, last_rtbno);
335 :
336 32841 : last_group_rbmoff = xfs_rtx_to_rbmblock(mp, last_group_rtx);
337 32841 : rb->group_rbmlen = last_group_rbmoff - rb->group_rbmoff + 1;
338 32841 : last_rbmblock_rtx = xfs_rbmblock_to_rtx(mp, last_group_rbmoff + 1) - 1;
339 :
340 32841 : trace_xrep_rgbitmap_load(rtg, last_group_rbmoff, last_group_rtx + 1,
341 : last_rbmblock_rtx);
342 :
343 32841 : if (last_rbmblock_rtx == last_group_rtx ||
344 32841 : rtg->rtg_rgno == mp->m_sb.sb_rgcount - 1)
345 : return 0;
346 :
347 26273 : error = xfs_rtbuf_get(mp, sc->tp, last_group_rbmoff, 0, &bp);
348 26273 : if (error) {
349 : /*
350 : * Reading the existing rbmblock failed, and we must deal with
351 : * the part of the rtbitmap block that corresponds to the
352 : * previous group. The most conservative option is to fill
353 : * that part of the bitmap with zeroes so that it won't get
354 : * allocated. The xfile contains zeroes already, so we can
355 : * return.
356 : */
357 : return 0;
358 : }
359 :
360 : /*
361 : * Compute the bit position of the first rtextent of the next group.
362 : * If the bit position is zero, we don't have to RMW a partial word
363 : * and move to the next step.
364 : */
365 26273 : wordoff = rtx_to_wordoff(mp, last_group_rtx);
366 26273 : bit = (last_group_rtx + 1) & XREP_RTBMP_WORDMASK;
367 26273 : if (bit == 0)
368 26273 : goto copy_words;
369 :
370 : /*
371 : * Create a mask of the bits that we want to load from disk. These
372 : * bits track space in a different rtgroup, which is why we must
373 : * preserve them even as we replace parts of the bitmap.
374 : */
375 0 : mask = (((xfs_rtword_t)1 << (XFS_NBWORD - bit)) - 1) << bit;
376 :
377 0 : error = xfbmp_load(rb, wordoff, &xfile_word);
378 0 : if (error)
379 0 : goto out_rele;
380 0 : last_group_word = xfs_rtx_to_rbmword(mp, last_group_rtx);
381 0 : ondisk_word = xfs_rtbitmap_getword(mp,
382 : xfs_rbmblock_wordptr(bp, last_group_word));
383 :
384 0 : trace_xrep_rgbitmap_load_word(mp, wordoff, bit, ondisk_word,
385 : xfile_word, mask);
386 :
387 0 : xfile_word &= ~mask;
388 0 : xfile_word |= (ondisk_word & mask);
389 :
390 0 : error = xfbmp_store(rb, wordoff, xfile_word);
391 0 : if (error)
392 0 : goto out_rele;
393 :
394 0 : copy_words:
395 : /* Copy as many full words as we can. */
396 26273 : wordoff++;
397 26273 : wordcnt = rtxlen_to_wordcnt(last_rbmblock_rtx - last_group_rtx);
398 26273 : if (wordcnt > 0) {
399 26273 : union xfs_rtword_ondisk *p;
400 :
401 26273 : p = xfs_rbmblock_wordptr(bp, mp->m_blockwsize - wordcnt);
402 26273 : error = xfbmp_copyin(rb, wordoff, p, wordcnt);
403 26273 : if (error)
404 0 : goto out_rele;
405 :
406 26273 : trace_xrep_rgbitmap_load_words(mp, last_group_rbmoff, wordoff,
407 : wordcnt);
408 : }
409 :
410 0 : out_rele:
411 26273 : xfs_trans_brelse(sc->tp, bp);
412 26273 : return error;
413 : }
414 :
415 : /* Perform a logical OR operation on an rtword in the incore bitmap. */
416 : static int
417 839620 : xrep_rgbitmap_or(
418 : struct xrep_rgbmp *rb,
419 : xrep_wordoff_t wordoff,
420 : xfs_rtword_t mask)
421 : {
422 839620 : xfs_rtword_t word;
423 839620 : int error;
424 :
425 839620 : error = xfbmp_load(rb, wordoff, &word);
426 839620 : if (error)
427 : return error;
428 :
429 839620 : trace_xrep_rgbitmap_or(rb->sc->mp, wordoff, mask, word);
430 :
431 839620 : return xfbmp_store(rb, wordoff, word | mask);
432 : }
433 :
434 : /*
435 : * Mark as free every rt extent between the next rt block we expected to see
436 : * in the rtrmap records and the given rt block.
437 : */
438 : STATIC int
439 734749 : xrep_rgbitmap_mark_free(
440 : struct xrep_rgbmp *rb,
441 : xfs_rgblock_t rgbno)
442 : {
443 734749 : struct xfs_mount *mp = rb->sc->mp;
444 734749 : struct xfs_rtgroup *rtg = rb->sc->sr.rtg;
445 734749 : xfs_rtblock_t rtbno;
446 734749 : xfs_rtxnum_t startrtx;
447 734749 : xfs_rtxnum_t nextrtx;
448 734749 : xrep_wordoff_t wordoff, nextwordoff;
449 734749 : unsigned int bit;
450 734749 : unsigned int bufwsize;
451 734749 : xfs_extlen_t mod;
452 734749 : xfs_rtword_t mask;
453 734749 : enum xbtree_recpacking outcome;
454 734749 : int error;
455 :
456 734749 : if (!xfs_verify_rgbext(rtg, rb->next_rgbno, rgbno - rb->next_rgbno))
457 : return -EFSCORRUPTED;
458 :
459 : /*
460 : * Convert rt blocks to rt extents The block range we find must be
461 : * aligned to an rtextent boundary on both ends.
462 : */
463 734749 : rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno, rb->next_rgbno);
464 734749 : startrtx = xfs_rtb_to_rtx(mp, rtbno, &mod);
465 734749 : if (mod)
466 : return -EFSCORRUPTED;
467 :
468 734749 : rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno, rgbno - 1);
469 734749 : nextrtx = xfs_rtb_to_rtx(mp, rtbno, &mod) + 1;
470 734749 : if (mod != mp->m_sb.sb_rextsize - 1)
471 : return -EFSCORRUPTED;
472 :
473 : /* Must not be shared or CoW staging. */
474 734749 : if (rb->sc->sr.refc_cur) {
475 734749 : error = xfs_refcount_has_records(rb->sc->sr.refc_cur,
476 : XFS_REFC_DOMAIN_SHARED, rb->next_rgbno,
477 : rgbno - rb->next_rgbno, &outcome);
478 734749 : if (error)
479 : return error;
480 734749 : if (outcome != XBTREE_RECPACKING_EMPTY)
481 : return -EFSCORRUPTED;
482 :
483 734749 : error = xfs_refcount_has_records(rb->sc->sr.refc_cur,
484 : XFS_REFC_DOMAIN_COW, rb->next_rgbno,
485 : rgbno - rb->next_rgbno, &outcome);
486 734749 : if (error)
487 : return error;
488 734749 : if (outcome != XBTREE_RECPACKING_EMPTY)
489 : return -EFSCORRUPTED;
490 : }
491 :
492 734749 : trace_xrep_rgbitmap_record_free(mp, startrtx, nextrtx - 1);
493 :
494 : /* Set bits as needed to round startrtx up to the nearest word. */
495 734749 : bit = startrtx & XREP_RTBMP_WORDMASK;
496 734749 : if (bit) {
497 709218 : xfs_rtblock_t len = nextrtx - startrtx;
498 709218 : unsigned int lastbit;
499 :
500 709218 : lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
501 709218 : mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
502 :
503 709218 : error = xrep_rgbitmap_or(rb, rtx_to_wordoff(mp, startrtx), mask);
504 709218 : if (error || lastbit - bit == len)
505 : return error;
506 138370 : startrtx += XFS_NBWORD - bit;
507 : }
508 :
509 : /* Set bits as needed to round nextrtx down to the nearest word. */
510 163901 : bit = nextrtx & XREP_RTBMP_WORDMASK;
511 163901 : if (bit) {
512 130402 : mask = ((xfs_rtword_t)1 << bit) - 1;
513 :
514 130402 : error = xrep_rgbitmap_or(rb, rtx_to_wordoff(mp, nextrtx), mask);
515 130402 : if (error || startrtx + bit == nextrtx)
516 : return error;
517 7107 : nextrtx -= bit;
518 : }
519 :
520 40606 : trace_xrep_rgbitmap_record_free_bulk(mp, startrtx, nextrtx - 1);
521 :
522 : /* Set all the words in between, up to a whole fs block at once. */
523 40606 : wordoff = rtx_to_wordoff(mp, startrtx);
524 40606 : nextwordoff = rtx_to_wordoff(mp, nextrtx);
525 40606 : bufwsize = mp->m_sb.sb_blocksize >> XFS_WORDLOG;
526 :
527 1434679 : while (wordoff < nextwordoff) {
528 1394073 : xrep_wordoff_t rem;
529 1394073 : xrep_wordcnt_t wordcnt;
530 :
531 1394073 : wordcnt = min_t(xrep_wordcnt_t, nextwordoff - wordoff,
532 : bufwsize);
533 :
534 : /*
535 : * Try to keep us aligned to sc->buf to reduce the number of
536 : * xfile writes.
537 : */
538 1394073 : rem = wordoff & (bufwsize - 1);
539 1394073 : if (rem)
540 40587 : wordcnt = min_t(xrep_wordcnt_t, wordcnt,
541 : bufwsize - rem);
542 :
543 1394073 : error = xfbmp_copyin(rb, wordoff, rb->sc->buf, wordcnt);
544 1394073 : if (error)
545 0 : return error;
546 :
547 1394073 : wordoff += wordcnt;
548 : }
549 :
550 : return 0;
551 : }
552 :
553 : /* Set free space in the rtbitmap based on rtrmapbt records. */
554 : STATIC int
555 1236918701 : xrep_rgbitmap_walk_rtrmap(
556 : struct xfs_btree_cur *cur,
557 : const struct xfs_rmap_irec *rec,
558 : void *priv)
559 : {
560 1236918701 : struct xrep_rgbmp *rb = priv;
561 1236918701 : int error = 0;
562 :
563 1236918701 : if (xchk_should_terminate(rb->sc, &error))
564 0 : return error;
565 :
566 1236918701 : if (rb->next_rgbno < rec->rm_startblock) {
567 718491 : error = xrep_rgbitmap_mark_free(rb, rec->rm_startblock);
568 718491 : if (error)
569 : return error;
570 : }
571 :
572 1236918701 : rb->next_rgbno = max(rb->next_rgbno,
573 : rec->rm_startblock + rec->rm_blockcount);
574 1236918701 : return 0;
575 : }
576 :
577 : /*
578 : * Walk the rtrmapbt to find all the gaps between records, and mark the gaps
579 : * in the realtime bitmap that we're computing.
580 : */
581 : STATIC int
582 32841 : xrep_rgbitmap_find_freespace(
583 : struct xrep_rgbmp *rb)
584 : {
585 32841 : struct xfs_scrub *sc = rb->sc;
586 32841 : struct xfs_mount *mp = sc->mp;
587 32841 : struct xfs_rtgroup *rtg = sc->sr.rtg;
588 32841 : int error;
589 :
590 : /* Prepare a buffer of ones so that we can accelerate bulk setting. */
591 32841 : memset(sc->buf, 0xFF, mp->m_sb.sb_blocksize);
592 :
593 32841 : xrep_rtgroup_btcur_init(sc, &sc->sr);
594 32841 : error = xfs_rmap_query_all(sc->sr.rmap_cur, xrep_rgbitmap_walk_rtrmap,
595 : rb);
596 32841 : if (error)
597 0 : goto out;
598 :
599 : /*
600 : * Mark as free every possible rt extent from the last one we saw to
601 : * the end of the rt group.
602 : */
603 32841 : if (rb->next_rgbno < rtg->rtg_blockcount) {
604 16258 : error = xrep_rgbitmap_mark_free(rb, rtg->rtg_blockcount);
605 16258 : if (error)
606 0 : goto out;
607 : }
608 :
609 32841 : out:
610 32841 : xchk_rtgroup_btcur_free(&sc->sr);
611 32841 : return error;
612 : }
613 :
614 : static int
615 1806265 : xrep_rgbitmap_prep_buf(
616 : struct xfs_scrub *sc,
617 : struct xfs_buf *bp,
618 : void *data)
619 : {
620 1806265 : struct xrep_rgbmp *rb = data;
621 1806265 : struct xfs_mount *mp = sc->mp;
622 1806265 : int error;
623 :
624 3612530 : error = xfbmp_copyout(rb, rb->prep_wordoff,
625 : xfs_rbmblock_wordptr(bp, 0), mp->m_blockwsize);
626 1806265 : if (error)
627 : return error;
628 :
629 1806265 : if (xfs_has_rtgroups(sc->mp)) {
630 1806265 : struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
631 :
632 1806265 : hdr->rt_magic = cpu_to_be32(XFS_RTBITMAP_MAGIC);
633 1806265 : hdr->rt_owner = cpu_to_be64(sc->ip->i_ino);
634 1806265 : hdr->rt_blkno = cpu_to_be64(xfs_buf_daddr(bp));
635 1806265 : hdr->rt_lsn = 0;
636 1806265 : uuid_copy(&hdr->rt_uuid, &sc->mp->m_sb.sb_meta_uuid);
637 1806265 : bp->b_ops = &xfs_rtbitmap_buf_ops;
638 : } else {
639 0 : bp->b_ops = &xfs_rtbuf_ops;
640 : }
641 :
642 1806265 : rb->prep_wordoff += mp->m_blockwsize;
643 1806265 : xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_RTBITMAP_BUF);
644 1806265 : return 0;
645 : }
646 :
647 : /* Repair the realtime bitmap for this rt group. */
648 : int
649 32841 : xrep_rgbitmap(
650 : struct xfs_scrub *sc)
651 : {
652 32841 : struct xrep_rgbmp rb = {
653 : .sc = sc,
654 : .next_rgbno = 0,
655 : };
656 32841 : struct xrep_tempswap *ti = NULL;
657 32841 : int error;
658 :
659 : /*
660 : * We require the realtime rmapbt (and atomic file updates) to rebuild
661 : * anything.
662 : */
663 32841 : if (!xfs_has_rtrmapbt(sc->mp))
664 : return -EOPNOTSUPP;
665 :
666 : /*
667 : * If the start or end of this rt group happens to be in the middle of
668 : * an rtbitmap block, try to read in the parts of the bitmap that are
669 : * from some other group.
670 : */
671 32841 : error = xrep_rgbitmap_load_before(&rb);
672 32841 : if (error)
673 : return error;
674 32841 : error = xrep_rgbitmap_load_after(&rb);
675 32841 : if (error)
676 : return error;
677 :
678 : /*
679 : * Generate the new rtbitmap data. We don't need the rtbmp information
680 : * once this call is finished.
681 : */
682 32841 : error = xrep_rgbitmap_find_freespace(&rb);
683 32841 : if (error)
684 : return error;
685 :
686 : /*
687 : * Try to take ILOCK_EXCL of the temporary file. We had better be the
688 : * only ones holding onto this inode, but we can't block while holding
689 : * the rtbitmap file's ILOCK_EXCL.
690 : */
691 32842 : while (!xrep_tempfile_ilock_nowait(sc)) {
692 1 : if (xchk_should_terminate(sc, &error))
693 0 : return error;
694 1 : delay(1);
695 : }
696 :
697 : /*
698 : * Make sure we have space allocated for the part of the bitmap
699 : * file that corresponds to this group.
700 : */
701 32841 : xfs_trans_ijoin(sc->tp, sc->ip, 0);
702 32841 : xfs_trans_ijoin(sc->tp, sc->tempip, 0);
703 32841 : error = xrep_tempfile_prealloc(sc, rb.group_rbmoff, rb.group_rbmlen);
704 32841 : if (error)
705 : return error;
706 :
707 : /* Last chance to abort before we start committing fixes. */
708 32841 : if (xchk_should_terminate(sc, &error))
709 0 : return error;
710 :
711 : /* Copy the bitmap file that we generated. */
712 32841 : error = xrep_tempfile_copyin(sc, rb.group_rbmoff, rb.group_rbmlen,
713 : xrep_rgbitmap_prep_buf, &rb);
714 32841 : if (error)
715 : return error;
716 65682 : error = xrep_tempfile_set_isize(sc,
717 32841 : XFS_FSB_TO_B(sc->mp, sc->mp->m_sb.sb_rbmblocks));
718 32841 : if (error)
719 : return error;
720 :
721 : /*
722 : * Now swap the extents. We're done with the temporary buffer, so
723 : * we can reuse it for the tempfile swapext information.
724 : */
725 32841 : ti = sc->buf;
726 32841 : error = xrep_tempswap_trans_reserve(sc, XFS_DATA_FORK, rb.group_rbmoff,
727 : rb.group_rbmlen, ti);
728 32841 : if (error)
729 : return error;
730 :
731 32841 : error = xrep_tempswap_contents(sc, ti);
732 32841 : if (error)
733 : return error;
734 32841 : ti = NULL;
735 :
736 : /* Free the old bitmap blocks if they are free. */
737 32841 : return xrep_reap_ifork(sc, sc->tempip, XFS_DATA_FORK);
738 : }
739 :
740 : /* Set up to repair the realtime bitmap file metadata. */
741 : int
742 6569 : xrep_setup_rtbitmap(
743 : struct xfs_scrub *sc,
744 : unsigned int *resblks)
745 : {
746 6569 : struct xfs_mount *mp = sc->mp;
747 6569 : unsigned long long blocks = 0;
748 :
749 : /*
750 : * Reserve enough blocks to write out a completely new bmbt for the
751 : * bitmap file.
752 : */
753 6569 : blocks = xfs_bmbt_calc_size(mp, mp->m_sb.sb_rbmblocks);
754 6569 : if (blocks > UINT_MAX)
755 : return -EOPNOTSUPP;
756 :
757 6569 : *resblks += blocks;
758 6569 : return 0;
759 : }
760 :
761 : /* Repair the realtime bitmap file metadata. */
762 : int
763 6569 : xrep_rtbitmap(
764 : struct xfs_scrub *sc)
765 : {
766 : /*
767 : * The only thing we know how to fix right now is problems with the
768 : * inode or its fork data.
769 : */
770 6569 : return xrep_metadata_inode_forks(sc);
771 : }
|