.. | .. |
---|
9 | 9 | #include "xfs_format.h" |
---|
10 | 10 | #include "xfs_trans_resv.h" |
---|
11 | 11 | #include "xfs_mount.h" |
---|
12 | | -#include "xfs_defer.h" |
---|
13 | 12 | #include "xfs_btree.h" |
---|
14 | | -#include "xfs_bit.h" |
---|
15 | 13 | #include "xfs_log_format.h" |
---|
16 | 14 | #include "xfs_trans.h" |
---|
17 | 15 | #include "xfs_sb.h" |
---|
18 | 16 | #include "xfs_inode.h" |
---|
19 | | -#include "xfs_icache.h" |
---|
20 | 17 | #include "xfs_alloc.h" |
---|
21 | 18 | #include "xfs_alloc_btree.h" |
---|
22 | 19 | #include "xfs_ialloc.h" |
---|
23 | 20 | #include "xfs_ialloc_btree.h" |
---|
24 | 21 | #include "xfs_rmap.h" |
---|
25 | 22 | #include "xfs_rmap_btree.h" |
---|
26 | | -#include "xfs_refcount.h" |
---|
27 | 23 | #include "xfs_refcount_btree.h" |
---|
28 | 24 | #include "xfs_extent_busy.h" |
---|
29 | 25 | #include "xfs_ag_resv.h" |
---|
30 | | -#include "xfs_trans_space.h" |
---|
31 | 26 | #include "xfs_quota.h" |
---|
32 | | -#include "scrub/xfs_scrub.h" |
---|
33 | 27 | #include "scrub/scrub.h" |
---|
34 | 28 | #include "scrub/common.h" |
---|
35 | 29 | #include "scrub/trace.h" |
---|
.. | .. |
---|
44 | 38 | int |
---|
45 | 39 | xrep_attempt( |
---|
46 | 40 | struct xfs_inode *ip, |
---|
47 | | - struct xfs_scrub *sc, |
---|
48 | | - bool *fixed) |
---|
| 41 | + struct xfs_scrub *sc) |
---|
49 | 42 | { |
---|
50 | 43 | int error = 0; |
---|
51 | 44 | |
---|
.. | .. |
---|
64 | 57 | * scrub so that we can tell userspace if we fixed the problem. |
---|
65 | 58 | */ |
---|
66 | 59 | sc->sm->sm_flags &= ~XFS_SCRUB_FLAGS_OUT; |
---|
67 | | - *fixed = true; |
---|
| 60 | + sc->flags |= XREP_ALREADY_FIXED; |
---|
68 | 61 | return -EAGAIN; |
---|
69 | 62 | case -EDEADLOCK: |
---|
70 | 63 | case -EAGAIN: |
---|
71 | 64 | /* Tell the caller to try again having grabbed all the locks. */ |
---|
72 | | - if (!sc->try_harder) { |
---|
73 | | - sc->try_harder = true; |
---|
| 65 | + if (!(sc->flags & XCHK_TRY_HARDER)) { |
---|
| 66 | + sc->flags |= XCHK_TRY_HARDER; |
---|
74 | 67 | return -EAGAIN; |
---|
75 | 68 | } |
---|
76 | 69 | /* |
---|
.. | .. |
---|
135 | 128 | if (sc->sa.agfl_bp) |
---|
136 | 129 | xfs_trans_bhold(sc->tp, sc->sa.agfl_bp); |
---|
137 | 130 | |
---|
138 | | - /* Roll the transaction. */ |
---|
| 131 | + /* |
---|
| 132 | + * Roll the transaction. We still own the buffer and the buffer lock |
---|
| 133 | + * regardless of whether or not the roll succeeds. If the roll fails, |
---|
| 134 | + * the buffers will be released during teardown on our way out of the |
---|
| 135 | + * kernel. If it succeeds, we join them to the new transaction and |
---|
| 136 | + * move on. |
---|
| 137 | + */ |
---|
139 | 138 | error = xfs_trans_roll(&sc->tp); |
---|
140 | 139 | if (error) |
---|
141 | | - goto out_release; |
---|
| 140 | + return error; |
---|
142 | 141 | |
---|
143 | 142 | /* Join AG headers to the new transaction. */ |
---|
144 | 143 | if (sc->sa.agi_bp) |
---|
.. | .. |
---|
149 | 148 | xfs_trans_bjoin(sc->tp, sc->sa.agfl_bp); |
---|
150 | 149 | |
---|
151 | 150 | return 0; |
---|
152 | | - |
---|
153 | | -out_release: |
---|
154 | | - /* |
---|
155 | | - * Rolling failed, so release the hold on the buffers. The |
---|
156 | | - * buffers will be released during teardown on our way out |
---|
157 | | - * of the kernel. |
---|
158 | | - */ |
---|
159 | | - if (sc->sa.agi_bp) |
---|
160 | | - xfs_trans_bhold_release(sc->tp, sc->sa.agi_bp); |
---|
161 | | - if (sc->sa.agf_bp) |
---|
162 | | - xfs_trans_bhold_release(sc->tp, sc->sa.agf_bp); |
---|
163 | | - if (sc->sa.agfl_bp) |
---|
164 | | - xfs_trans_bhold_release(sc->tp, sc->sa.agfl_bp); |
---|
165 | | - |
---|
166 | | - return error; |
---|
167 | 151 | } |
---|
168 | 152 | |
---|
169 | 153 | /* |
---|
.. | .. |
---|
224 | 208 | /* Now grab the block counters from the AGF. */ |
---|
225 | 209 | error = xfs_alloc_read_agf(mp, NULL, sm->sm_agno, 0, &bp); |
---|
226 | 210 | if (!error) { |
---|
227 | | - aglen = be32_to_cpu(XFS_BUF_TO_AGF(bp)->agf_length); |
---|
228 | | - freelen = be32_to_cpu(XFS_BUF_TO_AGF(bp)->agf_freeblks); |
---|
| 211 | + struct xfs_agf *agf = bp->b_addr; |
---|
| 212 | + |
---|
| 213 | + aglen = be32_to_cpu(agf->agf_length); |
---|
| 214 | + freelen = be32_to_cpu(agf->agf_freeblks); |
---|
229 | 215 | usedlen = aglen - freelen; |
---|
230 | 216 | xfs_buf_relse(bp); |
---|
231 | 217 | } |
---|
.. | .. |
---|
297 | 283 | /* Allocate a block in an AG. */ |
---|
298 | 284 | int |
---|
299 | 285 | xrep_alloc_ag_block( |
---|
300 | | - struct xfs_scrub *sc, |
---|
301 | | - struct xfs_owner_info *oinfo, |
---|
302 | | - xfs_fsblock_t *fsbno, |
---|
303 | | - enum xfs_ag_resv_type resv) |
---|
| 286 | + struct xfs_scrub *sc, |
---|
| 287 | + const struct xfs_owner_info *oinfo, |
---|
| 288 | + xfs_fsblock_t *fsbno, |
---|
| 289 | + enum xfs_ag_resv_type resv) |
---|
304 | 290 | { |
---|
305 | | - struct xfs_alloc_arg args = {0}; |
---|
306 | | - xfs_agblock_t bno; |
---|
307 | | - int error; |
---|
| 291 | + struct xfs_alloc_arg args = {0}; |
---|
| 292 | + xfs_agblock_t bno; |
---|
| 293 | + int error; |
---|
308 | 294 | |
---|
309 | 295 | switch (resv) { |
---|
310 | 296 | case XFS_AG_RESV_AGFL: |
---|
.. | .. |
---|
357 | 343 | struct xfs_trans *tp = sc->tp; |
---|
358 | 344 | struct xfs_mount *mp = sc->mp; |
---|
359 | 345 | struct xfs_buf *bp; |
---|
| 346 | + int error; |
---|
360 | 347 | |
---|
361 | 348 | trace_xrep_init_btblock(mp, XFS_FSB_TO_AGNO(mp, fsb), |
---|
362 | 349 | XFS_FSB_TO_AGBNO(mp, fsb), btnum); |
---|
363 | 350 | |
---|
364 | 351 | ASSERT(XFS_FSB_TO_AGNO(mp, fsb) == sc->sa.agno); |
---|
365 | | - bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, fsb), |
---|
366 | | - XFS_FSB_TO_BB(mp, 1), 0); |
---|
| 352 | + error = xfs_trans_get_buf(tp, mp->m_ddev_targp, |
---|
| 353 | + XFS_FSB_TO_DADDR(mp, fsb), XFS_FSB_TO_BB(mp, 1), 0, |
---|
| 354 | + &bp); |
---|
| 355 | + if (error) |
---|
| 356 | + return error; |
---|
367 | 357 | xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); |
---|
368 | | - xfs_btree_init_block(mp, bp, btnum, 0, 0, sc->sa.agno, 0); |
---|
| 358 | + xfs_btree_init_block(mp, bp, btnum, 0, 0, sc->sa.agno); |
---|
369 | 359 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_BTREE_BUF); |
---|
370 | | - xfs_trans_log_buf(tp, bp, 0, bp->b_length); |
---|
| 360 | + xfs_trans_log_buf(tp, bp, 0, BBTOB(bp->b_length) - 1); |
---|
371 | 361 | bp->b_ops = ops; |
---|
372 | 362 | *bpp = bp; |
---|
373 | 363 | |
---|
.. | .. |
---|
446 | 436 | int |
---|
447 | 437 | xrep_invalidate_blocks( |
---|
448 | 438 | struct xfs_scrub *sc, |
---|
449 | | - struct xfs_bitmap *bitmap) |
---|
| 439 | + struct xbitmap *bitmap) |
---|
450 | 440 | { |
---|
451 | | - struct xfs_bitmap_range *bmr; |
---|
452 | | - struct xfs_bitmap_range *n; |
---|
| 441 | + struct xbitmap_range *bmr; |
---|
| 442 | + struct xbitmap_range *n; |
---|
453 | 443 | struct xfs_buf *bp; |
---|
454 | 444 | xfs_fsblock_t fsbno; |
---|
455 | 445 | |
---|
.. | .. |
---|
461 | 451 | * because we never own those; and if we can't TRYLOCK the buffer we |
---|
462 | 452 | * assume it's owned by someone else. |
---|
463 | 453 | */ |
---|
464 | | - for_each_xfs_bitmap_block(fsbno, bmr, n, bitmap) { |
---|
| 454 | + for_each_xbitmap_block(fsbno, bmr, n, bitmap) { |
---|
465 | 455 | /* Skip AG headers and post-EOFS blocks */ |
---|
466 | 456 | if (!xfs_verify_fsbno(sc->mp, fsbno)) |
---|
467 | 457 | continue; |
---|
.. | .. |
---|
503 | 493 | struct xfs_scrub *sc, |
---|
504 | 494 | xfs_agblock_t agbno) |
---|
505 | 495 | { |
---|
506 | | - struct xfs_owner_info oinfo; |
---|
507 | 496 | int error; |
---|
508 | 497 | |
---|
509 | 498 | /* Make sure there's space on the freelist. */ |
---|
.. | .. |
---|
516 | 505 | * create an rmap for the block prior to merging it or else other |
---|
517 | 506 | * parts will break. |
---|
518 | 507 | */ |
---|
519 | | - xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG); |
---|
520 | 508 | error = xfs_rmap_alloc(sc->tp, sc->sa.agf_bp, sc->sa.agno, agbno, 1, |
---|
521 | | - &oinfo); |
---|
| 509 | + &XFS_RMAP_OINFO_AG); |
---|
522 | 510 | if (error) |
---|
523 | 511 | return error; |
---|
524 | 512 | |
---|
.. | .. |
---|
536 | 524 | /* Dispose of a single block. */ |
---|
537 | 525 | STATIC int |
---|
538 | 526 | xrep_reap_block( |
---|
539 | | - struct xfs_scrub *sc, |
---|
540 | | - xfs_fsblock_t fsbno, |
---|
541 | | - struct xfs_owner_info *oinfo, |
---|
542 | | - enum xfs_ag_resv_type resv) |
---|
| 527 | + struct xfs_scrub *sc, |
---|
| 528 | + xfs_fsblock_t fsbno, |
---|
| 529 | + const struct xfs_owner_info *oinfo, |
---|
| 530 | + enum xfs_ag_resv_type resv) |
---|
543 | 531 | { |
---|
544 | | - struct xfs_btree_cur *cur; |
---|
545 | | - struct xfs_buf *agf_bp = NULL; |
---|
546 | | - xfs_agnumber_t agno; |
---|
547 | | - xfs_agblock_t agbno; |
---|
548 | | - bool has_other_rmap; |
---|
549 | | - int error; |
---|
| 532 | + struct xfs_btree_cur *cur; |
---|
| 533 | + struct xfs_buf *agf_bp = NULL; |
---|
| 534 | + xfs_agnumber_t agno; |
---|
| 535 | + xfs_agblock_t agbno; |
---|
| 536 | + bool has_other_rmap; |
---|
| 537 | + int error; |
---|
550 | 538 | |
---|
551 | 539 | agno = XFS_FSB_TO_AGNO(sc->mp, fsbno); |
---|
552 | 540 | agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno); |
---|
.. | .. |
---|
560 | 548 | error = xfs_alloc_read_agf(sc->mp, sc->tp, agno, 0, &agf_bp); |
---|
561 | 549 | if (error) |
---|
562 | 550 | return error; |
---|
563 | | - if (!agf_bp) |
---|
564 | | - return -ENOMEM; |
---|
565 | 551 | } else { |
---|
566 | 552 | agf_bp = sc->sa.agf_bp; |
---|
567 | 553 | } |
---|
.. | .. |
---|
610 | 596 | /* Dispose of every block of every extent in the bitmap. */ |
---|
611 | 597 | int |
---|
612 | 598 | xrep_reap_extents( |
---|
613 | | - struct xfs_scrub *sc, |
---|
614 | | - struct xfs_bitmap *bitmap, |
---|
615 | | - struct xfs_owner_info *oinfo, |
---|
616 | | - enum xfs_ag_resv_type type) |
---|
| 599 | + struct xfs_scrub *sc, |
---|
| 600 | + struct xbitmap *bitmap, |
---|
| 601 | + const struct xfs_owner_info *oinfo, |
---|
| 602 | + enum xfs_ag_resv_type type) |
---|
617 | 603 | { |
---|
618 | | - struct xfs_bitmap_range *bmr; |
---|
619 | | - struct xfs_bitmap_range *n; |
---|
620 | | - xfs_fsblock_t fsbno; |
---|
621 | | - int error = 0; |
---|
| 604 | + struct xbitmap_range *bmr; |
---|
| 605 | + struct xbitmap_range *n; |
---|
| 606 | + xfs_fsblock_t fsbno; |
---|
| 607 | + int error = 0; |
---|
622 | 608 | |
---|
623 | 609 | ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb)); |
---|
624 | 610 | |
---|
625 | | - for_each_xfs_bitmap_block(fsbno, bmr, n, bitmap) { |
---|
| 611 | + for_each_xbitmap_block(fsbno, bmr, n, bitmap) { |
---|
626 | 612 | ASSERT(sc->ip != NULL || |
---|
627 | 613 | XFS_FSB_TO_AGNO(sc->mp, fsbno) == sc->sa.agno); |
---|
628 | 614 | trace_xrep_dispose_btree_extent(sc->mp, |
---|
.. | .. |
---|
631 | 617 | |
---|
632 | 618 | error = xrep_reap_block(sc, fsbno, oinfo, type); |
---|
633 | 619 | if (error) |
---|
634 | | - goto out; |
---|
| 620 | + break; |
---|
635 | 621 | } |
---|
636 | 622 | |
---|
637 | | -out: |
---|
638 | | - xfs_bitmap_destroy(bitmap); |
---|
639 | 623 | return error; |
---|
640 | 624 | } |
---|
641 | 625 | |
---|
.. | .. |
---|
682 | 666 | { |
---|
683 | 667 | xfs_agblock_t *agbno = priv; |
---|
684 | 668 | |
---|
685 | | - return (*agbno == bno) ? XFS_BTREE_QUERY_RANGE_ABORT : 0; |
---|
| 669 | + return (*agbno == bno) ? -ECANCELED : 0; |
---|
686 | 670 | } |
---|
687 | 671 | |
---|
688 | 672 | /* Does this block match the btree information passed in? */ |
---|
.. | .. |
---|
692 | 676 | struct xrep_find_ag_btree *fab, |
---|
693 | 677 | uint64_t owner, |
---|
694 | 678 | xfs_agblock_t agbno, |
---|
695 | | - bool *found_it) |
---|
| 679 | + bool *done_with_block) |
---|
696 | 680 | { |
---|
697 | 681 | struct xfs_mount *mp = ri->sc->mp; |
---|
698 | 682 | struct xfs_buf *bp; |
---|
699 | 683 | struct xfs_btree_block *btblock; |
---|
700 | 684 | xfs_daddr_t daddr; |
---|
701 | | - int error; |
---|
| 685 | + int block_level; |
---|
| 686 | + int error = 0; |
---|
702 | 687 | |
---|
703 | 688 | daddr = XFS_AGB_TO_DADDR(mp, ri->sc->sa.agno, agbno); |
---|
704 | 689 | |
---|
.. | .. |
---|
711 | 696 | if (owner == XFS_RMAP_OWN_AG) { |
---|
712 | 697 | error = xfs_agfl_walk(mp, ri->agf, ri->agfl_bp, |
---|
713 | 698 | xrep_findroot_agfl_walk, &agbno); |
---|
714 | | - if (error == XFS_BTREE_QUERY_RANGE_ABORT) |
---|
| 699 | + if (error == -ECANCELED) |
---|
715 | 700 | return 0; |
---|
716 | 701 | if (error) |
---|
717 | 702 | return error; |
---|
718 | 703 | } |
---|
719 | 704 | |
---|
| 705 | + /* |
---|
| 706 | + * Read the buffer into memory so that we can see if it's a match for |
---|
| 707 | + * our btree type. We have no clue if it is beforehand, and we want to |
---|
| 708 | + * avoid xfs_trans_read_buf's behavior of dumping the DONE state (which |
---|
| 709 | + * will cause needless disk reads in subsequent calls to this function) |
---|
| 710 | + * and logging metadata verifier failures. |
---|
| 711 | + * |
---|
| 712 | + * Therefore, pass in NULL buffer ops. If the buffer was already in |
---|
| 713 | + * memory from some other caller it will already have b_ops assigned. |
---|
| 714 | + * If it was in memory from a previous unsuccessful findroot_block |
---|
| 715 | + * call, the buffer won't have b_ops but it should be clean and ready |
---|
| 716 | + * for us to try to verify if the read call succeeds. The same applies |
---|
| 717 | + * if the buffer wasn't in memory at all. |
---|
| 718 | + * |
---|
| 719 | + * Note: If we never match a btree type with this buffer, it will be |
---|
| 720 | + * left in memory with NULL b_ops. This shouldn't be a problem unless |
---|
| 721 | + * the buffer gets written. |
---|
| 722 | + */ |
---|
720 | 723 | error = xfs_trans_read_buf(mp, ri->sc->tp, mp->m_ddev_targp, daddr, |
---|
721 | 724 | mp->m_bsize, 0, &bp, NULL); |
---|
722 | 725 | if (error) |
---|
723 | 726 | return error; |
---|
724 | 727 | |
---|
725 | | - /* |
---|
726 | | - * Does this look like a block matching our fs and higher than any |
---|
727 | | - * other block we've found so far? If so, reattach buffer verifiers |
---|
728 | | - * so the AIL won't complain if the buffer is also dirty. |
---|
729 | | - */ |
---|
| 728 | + /* Ensure the block magic matches the btree type we're looking for. */ |
---|
730 | 729 | btblock = XFS_BUF_TO_BLOCK(bp); |
---|
731 | | - if (be32_to_cpu(btblock->bb_magic) != fab->magic) |
---|
732 | | - goto out; |
---|
733 | | - if (xfs_sb_version_hascrc(&mp->m_sb) && |
---|
734 | | - !uuid_equal(&btblock->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) |
---|
735 | | - goto out; |
---|
736 | | - bp->b_ops = fab->buf_ops; |
---|
737 | | - |
---|
738 | | - /* Ignore this block if it's lower in the tree than we've seen. */ |
---|
739 | | - if (fab->root != NULLAGBLOCK && |
---|
740 | | - xfs_btree_get_level(btblock) < fab->height) |
---|
| 730 | + ASSERT(fab->buf_ops->magic[1] != 0); |
---|
| 731 | + if (btblock->bb_magic != fab->buf_ops->magic[1]) |
---|
741 | 732 | goto out; |
---|
742 | 733 | |
---|
743 | | - /* Make sure we pass the verifiers. */ |
---|
744 | | - bp->b_ops->verify_read(bp); |
---|
745 | | - if (bp->b_error) |
---|
| 734 | + /* |
---|
| 735 | + * If the buffer already has ops applied and they're not the ones for |
---|
| 736 | + * this btree type, we know this block doesn't match the btree and we |
---|
| 737 | + * can bail out. |
---|
| 738 | + * |
---|
| 739 | + * If the buffer ops match ours, someone else has already validated |
---|
| 740 | + * the block for us, so we can move on to checking if this is a root |
---|
| 741 | + * block candidate. |
---|
| 742 | + * |
---|
| 743 | + * If the buffer does not have ops, nobody has successfully validated |
---|
| 744 | + * the contents and the buffer cannot be dirty. If the magic, uuid, |
---|
| 745 | + * and structure match this btree type then we'll move on to checking |
---|
| 746 | + * if it's a root block candidate. If there is no match, bail out. |
---|
| 747 | + */ |
---|
| 748 | + if (bp->b_ops) { |
---|
| 749 | + if (bp->b_ops != fab->buf_ops) |
---|
| 750 | + goto out; |
---|
| 751 | + } else { |
---|
| 752 | + ASSERT(!xfs_trans_buf_is_dirty(bp)); |
---|
| 753 | + if (!uuid_equal(&btblock->bb_u.s.bb_uuid, |
---|
| 754 | + &mp->m_sb.sb_meta_uuid)) |
---|
| 755 | + goto out; |
---|
| 756 | + /* |
---|
| 757 | + * Read verifiers can reference b_ops, so we set the pointer |
---|
| 758 | + * here. If the verifier fails we'll reset the buffer state |
---|
| 759 | + * to what it was before we touched the buffer. |
---|
| 760 | + */ |
---|
| 761 | + bp->b_ops = fab->buf_ops; |
---|
| 762 | + fab->buf_ops->verify_read(bp); |
---|
| 763 | + if (bp->b_error) { |
---|
| 764 | + bp->b_ops = NULL; |
---|
| 765 | + bp->b_error = 0; |
---|
| 766 | + goto out; |
---|
| 767 | + } |
---|
| 768 | + |
---|
| 769 | + /* |
---|
| 770 | + * Some read verifiers will (re)set b_ops, so we must be |
---|
| 771 | + * careful not to change b_ops after running the verifier. |
---|
| 772 | + */ |
---|
| 773 | + } |
---|
| 774 | + |
---|
| 775 | + /* |
---|
| 776 | + * This block passes the magic/uuid and verifier tests for this btree |
---|
| 777 | + * type. We don't need the caller to try the other tree types. |
---|
| 778 | + */ |
---|
| 779 | + *done_with_block = true; |
---|
| 780 | + |
---|
| 781 | + /* |
---|
| 782 | + * Compare this btree block's level to the height of the current |
---|
| 783 | + * candidate root block. |
---|
| 784 | + * |
---|
| 785 | + * If the level matches the root we found previously, throw away both |
---|
| 786 | + * blocks because there can't be two candidate roots. |
---|
| 787 | + * |
---|
| 788 | + * If level is lower in the tree than the root we found previously, |
---|
| 789 | + * ignore this block. |
---|
| 790 | + */ |
---|
| 791 | + block_level = xfs_btree_get_level(btblock); |
---|
| 792 | + if (block_level + 1 == fab->height) { |
---|
| 793 | + fab->root = NULLAGBLOCK; |
---|
746 | 794 | goto out; |
---|
747 | | - fab->root = agbno; |
---|
748 | | - fab->height = xfs_btree_get_level(btblock) + 1; |
---|
749 | | - *found_it = true; |
---|
| 795 | + } else if (block_level < fab->height) { |
---|
| 796 | + goto out; |
---|
| 797 | + } |
---|
| 798 | + |
---|
| 799 | + /* |
---|
| 800 | + * This is the highest block in the tree that we've found so far. |
---|
| 801 | + * Update the btree height to reflect what we've learned from this |
---|
| 802 | + * block. |
---|
| 803 | + */ |
---|
| 804 | + fab->height = block_level + 1; |
---|
| 805 | + |
---|
| 806 | + /* |
---|
| 807 | + * If this block doesn't have sibling pointers, then it's the new root |
---|
| 808 | + * block candidate. Otherwise, the root will be found farther up the |
---|
| 809 | + * tree. |
---|
| 810 | + */ |
---|
| 811 | + if (btblock->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK) && |
---|
| 812 | + btblock->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK)) |
---|
| 813 | + fab->root = agbno; |
---|
| 814 | + else |
---|
| 815 | + fab->root = NULLAGBLOCK; |
---|
750 | 816 | |
---|
751 | 817 | trace_xrep_findroot_block(mp, ri->sc->sa.agno, agbno, |
---|
752 | 818 | be32_to_cpu(btblock->bb_magic), fab->height - 1); |
---|
.. | .. |
---|
768 | 834 | struct xrep_findroot *ri = priv; |
---|
769 | 835 | struct xrep_find_ag_btree *fab; |
---|
770 | 836 | xfs_agblock_t b; |
---|
771 | | - bool found_it; |
---|
| 837 | + bool done; |
---|
772 | 838 | int error = 0; |
---|
773 | 839 | |
---|
774 | 840 | /* Ignore anything that isn't AG metadata. */ |
---|
.. | .. |
---|
777 | 843 | |
---|
778 | 844 | /* Otherwise scan each block + btree type. */ |
---|
779 | 845 | for (b = 0; b < rec->rm_blockcount; b++) { |
---|
780 | | - found_it = false; |
---|
| 846 | + done = false; |
---|
781 | 847 | for (fab = ri->btree_info; fab->buf_ops; fab++) { |
---|
782 | 848 | if (rec->rm_owner != fab->rmap_owner) |
---|
783 | 849 | continue; |
---|
784 | 850 | error = xrep_findroot_block(ri, fab, |
---|
785 | 851 | rec->rm_owner, rec->rm_startblock + b, |
---|
786 | | - &found_it); |
---|
| 852 | + &done); |
---|
787 | 853 | if (error) |
---|
788 | 854 | return error; |
---|
789 | | - if (found_it) |
---|
| 855 | + if (done) |
---|
790 | 856 | break; |
---|
791 | 857 | } |
---|
792 | 858 | } |
---|
.. | .. |
---|
813 | 879 | |
---|
814 | 880 | ri.sc = sc; |
---|
815 | 881 | ri.btree_info = btree_info; |
---|
816 | | - ri.agf = XFS_BUF_TO_AGF(agf_bp); |
---|
| 882 | + ri.agf = agf_bp->b_addr; |
---|
817 | 883 | ri.agfl_bp = agfl_bp; |
---|
818 | 884 | for (fab = btree_info; fab->buf_ops; fab++) { |
---|
819 | 885 | ASSERT(agfl_bp || fab->rmap_owner != XFS_RMAP_OWN_AG); |
---|
.. | .. |
---|
833 | 899 | void |
---|
834 | 900 | xrep_force_quotacheck( |
---|
835 | 901 | struct xfs_scrub *sc, |
---|
836 | | - uint dqtype) |
---|
| 902 | + xfs_dqtype_t type) |
---|
837 | 903 | { |
---|
838 | 904 | uint flag; |
---|
839 | 905 | |
---|
840 | | - flag = xfs_quota_chkd_flag(dqtype); |
---|
| 906 | + flag = xfs_quota_chkd_flag(type); |
---|
841 | 907 | if (!(flag & sc->mp->m_qflags)) |
---|
842 | 908 | return; |
---|
843 | 909 | |
---|
.. | .. |
---|
873 | 939 | "inode %llu repair encountered quota error %d, quotacheck forced.", |
---|
874 | 940 | (unsigned long long)sc->ip->i_ino, error); |
---|
875 | 941 | if (XFS_IS_UQUOTA_ON(sc->mp) && !sc->ip->i_udquot) |
---|
876 | | - xrep_force_quotacheck(sc, XFS_DQ_USER); |
---|
| 942 | + xrep_force_quotacheck(sc, XFS_DQTYPE_USER); |
---|
877 | 943 | if (XFS_IS_GQUOTA_ON(sc->mp) && !sc->ip->i_gdquot) |
---|
878 | | - xrep_force_quotacheck(sc, XFS_DQ_GROUP); |
---|
| 944 | + xrep_force_quotacheck(sc, XFS_DQTYPE_GROUP); |
---|
879 | 945 | if (XFS_IS_PQUOTA_ON(sc->mp) && !sc->ip->i_pdquot) |
---|
880 | | - xrep_force_quotacheck(sc, XFS_DQ_PROJ); |
---|
| 946 | + xrep_force_quotacheck(sc, XFS_DQTYPE_PROJ); |
---|
881 | 947 | /* fall through */ |
---|
882 | 948 | case -ESRCH: |
---|
883 | 949 | error = 0; |
---|