| .. | .. |
|---|
| 13 | 13 | #include "xfs_sb.h" |
|---|
| 14 | 14 | #include "xfs_mount.h" |
|---|
| 15 | 15 | #include "xfs_defer.h" |
|---|
| 16 | | -#include "xfs_inode.h" |
|---|
| 17 | 16 | #include "xfs_btree.h" |
|---|
| 18 | 17 | #include "xfs_rmap.h" |
|---|
| 19 | 18 | #include "xfs_alloc_btree.h" |
|---|
| .. | .. |
|---|
| 21 | 20 | #include "xfs_extent_busy.h" |
|---|
| 22 | 21 | #include "xfs_errortag.h" |
|---|
| 23 | 22 | #include "xfs_error.h" |
|---|
| 24 | | -#include "xfs_cksum.h" |
|---|
| 25 | 23 | #include "xfs_trace.h" |
|---|
| 26 | 24 | #include "xfs_trans.h" |
|---|
| 27 | 25 | #include "xfs_buf_item.h" |
|---|
| .. | .. |
|---|
| 41 | 39 | STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *); |
|---|
| 42 | 40 | STATIC int xfs_alloc_ag_vextent_near(xfs_alloc_arg_t *); |
|---|
| 43 | 41 | STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); |
|---|
| 44 | | -STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *, |
|---|
| 45 | | - xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *); |
|---|
| 46 | 42 | |
|---|
| 47 | 43 | /* |
|---|
| 48 | 44 | * Size of the AGFL. For CRC-enabled filesystes we steal a couple of slots in |
|---|
| .. | .. |
|---|
| 150 | 146 | xfs_extlen_t len, /* length of extent */ |
|---|
| 151 | 147 | int *stat) /* success/failure */ |
|---|
| 152 | 148 | { |
|---|
| 149 | + int error; |
|---|
| 150 | + |
|---|
| 153 | 151 | cur->bc_rec.a.ar_startblock = bno; |
|---|
| 154 | 152 | cur->bc_rec.a.ar_blockcount = len; |
|---|
| 155 | | - return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); |
|---|
| 153 | + error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); |
|---|
| 154 | + cur->bc_ag.abt.active = (*stat == 1); |
|---|
| 155 | + return error; |
|---|
| 156 | 156 | } |
|---|
| 157 | 157 | |
|---|
| 158 | 158 | /* |
|---|
| .. | .. |
|---|
| 166 | 166 | xfs_extlen_t len, /* length of extent */ |
|---|
| 167 | 167 | int *stat) /* success/failure */ |
|---|
| 168 | 168 | { |
|---|
| 169 | + int error; |
|---|
| 170 | + |
|---|
| 169 | 171 | cur->bc_rec.a.ar_startblock = bno; |
|---|
| 170 | 172 | cur->bc_rec.a.ar_blockcount = len; |
|---|
| 171 | | - return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); |
|---|
| 173 | + error = xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); |
|---|
| 174 | + cur->bc_ag.abt.active = (*stat == 1); |
|---|
| 175 | + return error; |
|---|
| 172 | 176 | } |
|---|
| 173 | 177 | |
|---|
| 174 | 178 | /* |
|---|
| .. | .. |
|---|
| 182 | 186 | xfs_extlen_t len, /* length of extent */ |
|---|
| 183 | 187 | int *stat) /* success/failure */ |
|---|
| 184 | 188 | { |
|---|
| 189 | + int error; |
|---|
| 185 | 190 | cur->bc_rec.a.ar_startblock = bno; |
|---|
| 186 | 191 | cur->bc_rec.a.ar_blockcount = len; |
|---|
| 187 | | - return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); |
|---|
| 192 | + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); |
|---|
| 193 | + cur->bc_ag.abt.active = (*stat == 1); |
|---|
| 194 | + return error; |
|---|
| 195 | +} |
|---|
| 196 | + |
|---|
| 197 | +static inline bool |
|---|
| 198 | +xfs_alloc_cur_active( |
|---|
| 199 | + struct xfs_btree_cur *cur) |
|---|
| 200 | +{ |
|---|
| 201 | + return cur && cur->bc_ag.abt.active; |
|---|
| 188 | 202 | } |
|---|
| 189 | 203 | |
|---|
| 190 | 204 | /* |
|---|
| .. | .. |
|---|
| 216 | 230 | int *stat) /* output: success/failure */ |
|---|
| 217 | 231 | { |
|---|
| 218 | 232 | struct xfs_mount *mp = cur->bc_mp; |
|---|
| 219 | | - xfs_agnumber_t agno = cur->bc_private.a.agno; |
|---|
| 233 | + xfs_agnumber_t agno = cur->bc_ag.agno; |
|---|
| 220 | 234 | union xfs_btree_rec *rec; |
|---|
| 221 | 235 | int error; |
|---|
| 222 | 236 | |
|---|
| .. | .. |
|---|
| 317 | 331 | xfs_extlen_t newlen1=0; /* length with newbno1 */ |
|---|
| 318 | 332 | xfs_extlen_t newlen2=0; /* length with newbno2 */ |
|---|
| 319 | 333 | xfs_agblock_t wantend; /* end of target extent */ |
|---|
| 320 | | - bool userdata = xfs_alloc_is_userdata(datatype); |
|---|
| 334 | + bool userdata = datatype & XFS_ALLOC_USERDATA; |
|---|
| 321 | 335 | |
|---|
| 322 | 336 | ASSERT(freelen >= wantlen); |
|---|
| 323 | 337 | freeend = freebno + freelen; |
|---|
| .. | .. |
|---|
| 437 | 451 | #ifdef DEBUG |
|---|
| 438 | 452 | if ((error = xfs_alloc_get_rec(cnt_cur, &nfbno1, &nflen1, &i))) |
|---|
| 439 | 453 | return error; |
|---|
| 440 | | - XFS_WANT_CORRUPTED_RETURN(mp, |
|---|
| 441 | | - i == 1 && nfbno1 == fbno && nflen1 == flen); |
|---|
| 454 | + if (XFS_IS_CORRUPT(mp, |
|---|
| 455 | + i != 1 || |
|---|
| 456 | + nfbno1 != fbno || |
|---|
| 457 | + nflen1 != flen)) |
|---|
| 458 | + return -EFSCORRUPTED; |
|---|
| 442 | 459 | #endif |
|---|
| 443 | 460 | } else { |
|---|
| 444 | 461 | if ((error = xfs_alloc_lookup_eq(cnt_cur, fbno, flen, &i))) |
|---|
| 445 | 462 | return error; |
|---|
| 446 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); |
|---|
| 463 | + if (XFS_IS_CORRUPT(mp, i != 1)) |
|---|
| 464 | + return -EFSCORRUPTED; |
|---|
| 447 | 465 | } |
|---|
| 448 | 466 | /* |
|---|
| 449 | 467 | * Look up the record in the by-block tree if necessary. |
|---|
| .. | .. |
|---|
| 452 | 470 | #ifdef DEBUG |
|---|
| 453 | 471 | if ((error = xfs_alloc_get_rec(bno_cur, &nfbno1, &nflen1, &i))) |
|---|
| 454 | 472 | return error; |
|---|
| 455 | | - XFS_WANT_CORRUPTED_RETURN(mp, |
|---|
| 456 | | - i == 1 && nfbno1 == fbno && nflen1 == flen); |
|---|
| 473 | + if (XFS_IS_CORRUPT(mp, |
|---|
| 474 | + i != 1 || |
|---|
| 475 | + nfbno1 != fbno || |
|---|
| 476 | + nflen1 != flen)) |
|---|
| 477 | + return -EFSCORRUPTED; |
|---|
| 457 | 478 | #endif |
|---|
| 458 | 479 | } else { |
|---|
| 459 | 480 | if ((error = xfs_alloc_lookup_eq(bno_cur, fbno, flen, &i))) |
|---|
| 460 | 481 | return error; |
|---|
| 461 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); |
|---|
| 482 | + if (XFS_IS_CORRUPT(mp, i != 1)) |
|---|
| 483 | + return -EFSCORRUPTED; |
|---|
| 462 | 484 | } |
|---|
| 463 | 485 | |
|---|
| 464 | 486 | #ifdef DEBUG |
|---|
| .. | .. |
|---|
| 469 | 491 | bnoblock = XFS_BUF_TO_BLOCK(bno_cur->bc_bufs[0]); |
|---|
| 470 | 492 | cntblock = XFS_BUF_TO_BLOCK(cnt_cur->bc_bufs[0]); |
|---|
| 471 | 493 | |
|---|
| 472 | | - XFS_WANT_CORRUPTED_RETURN(mp, |
|---|
| 473 | | - bnoblock->bb_numrecs == cntblock->bb_numrecs); |
|---|
| 494 | + if (XFS_IS_CORRUPT(mp, |
|---|
| 495 | + bnoblock->bb_numrecs != |
|---|
| 496 | + cntblock->bb_numrecs)) |
|---|
| 497 | + return -EFSCORRUPTED; |
|---|
| 474 | 498 | } |
|---|
| 475 | 499 | #endif |
|---|
| 476 | 500 | |
|---|
| .. | .. |
|---|
| 500 | 524 | */ |
|---|
| 501 | 525 | if ((error = xfs_btree_delete(cnt_cur, &i))) |
|---|
| 502 | 526 | return error; |
|---|
| 503 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); |
|---|
| 527 | + if (XFS_IS_CORRUPT(mp, i != 1)) |
|---|
| 528 | + return -EFSCORRUPTED; |
|---|
| 504 | 529 | /* |
|---|
| 505 | 530 | * Add new by-size btree entry(s). |
|---|
| 506 | 531 | */ |
|---|
| 507 | 532 | if (nfbno1 != NULLAGBLOCK) { |
|---|
| 508 | 533 | if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno1, nflen1, &i))) |
|---|
| 509 | 534 | return error; |
|---|
| 510 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 0); |
|---|
| 535 | + if (XFS_IS_CORRUPT(mp, i != 0)) |
|---|
| 536 | + return -EFSCORRUPTED; |
|---|
| 511 | 537 | if ((error = xfs_btree_insert(cnt_cur, &i))) |
|---|
| 512 | 538 | return error; |
|---|
| 513 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); |
|---|
| 539 | + if (XFS_IS_CORRUPT(mp, i != 1)) |
|---|
| 540 | + return -EFSCORRUPTED; |
|---|
| 514 | 541 | } |
|---|
| 515 | 542 | if (nfbno2 != NULLAGBLOCK) { |
|---|
| 516 | 543 | if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i))) |
|---|
| 517 | 544 | return error; |
|---|
| 518 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 0); |
|---|
| 545 | + if (XFS_IS_CORRUPT(mp, i != 0)) |
|---|
| 546 | + return -EFSCORRUPTED; |
|---|
| 519 | 547 | if ((error = xfs_btree_insert(cnt_cur, &i))) |
|---|
| 520 | 548 | return error; |
|---|
| 521 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); |
|---|
| 549 | + if (XFS_IS_CORRUPT(mp, i != 1)) |
|---|
| 550 | + return -EFSCORRUPTED; |
|---|
| 522 | 551 | } |
|---|
| 523 | 552 | /* |
|---|
| 524 | 553 | * Fix up the by-block btree entry(s). |
|---|
| .. | .. |
|---|
| 529 | 558 | */ |
|---|
| 530 | 559 | if ((error = xfs_btree_delete(bno_cur, &i))) |
|---|
| 531 | 560 | return error; |
|---|
| 532 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); |
|---|
| 561 | + if (XFS_IS_CORRUPT(mp, i != 1)) |
|---|
| 562 | + return -EFSCORRUPTED; |
|---|
| 533 | 563 | } else { |
|---|
| 534 | 564 | /* |
|---|
| 535 | 565 | * Update the by-block entry to start later|be shorter. |
|---|
| .. | .. |
|---|
| 543 | 573 | */ |
|---|
| 544 | 574 | if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i))) |
|---|
| 545 | 575 | return error; |
|---|
| 546 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 0); |
|---|
| 576 | + if (XFS_IS_CORRUPT(mp, i != 0)) |
|---|
| 577 | + return -EFSCORRUPTED; |
|---|
| 547 | 578 | if ((error = xfs_btree_insert(bno_cur, &i))) |
|---|
| 548 | 579 | return error; |
|---|
| 549 | | - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); |
|---|
| 580 | + if (XFS_IS_CORRUPT(mp, i != 1)) |
|---|
| 581 | + return -EFSCORRUPTED; |
|---|
| 550 | 582 | } |
|---|
| 551 | 583 | return 0; |
|---|
| 552 | 584 | } |
|---|
| .. | .. |
|---|
| 555 | 587 | xfs_agfl_verify( |
|---|
| 556 | 588 | struct xfs_buf *bp) |
|---|
| 557 | 589 | { |
|---|
| 558 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
|---|
| 590 | + struct xfs_mount *mp = bp->b_mount; |
|---|
| 559 | 591 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); |
|---|
| 592 | + __be32 *agfl_bno = xfs_buf_to_agfl_bno(bp); |
|---|
| 560 | 593 | int i; |
|---|
| 561 | 594 | |
|---|
| 562 | 595 | /* |
|---|
| .. | .. |
|---|
| 568 | 601 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
|---|
| 569 | 602 | return NULL; |
|---|
| 570 | 603 | |
|---|
| 571 | | - if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid)) |
|---|
| 604 | + if (!xfs_verify_magic(bp, agfl->agfl_magicnum)) |
|---|
| 572 | 605 | return __this_address; |
|---|
| 573 | | - if (be32_to_cpu(agfl->agfl_magicnum) != XFS_AGFL_MAGIC) |
|---|
| 606 | + if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid)) |
|---|
| 574 | 607 | return __this_address; |
|---|
| 575 | 608 | /* |
|---|
| 576 | 609 | * during growfs operations, the perag is not fully initialised, |
|---|
| .. | .. |
|---|
| 582 | 615 | return __this_address; |
|---|
| 583 | 616 | |
|---|
| 584 | 617 | for (i = 0; i < xfs_agfl_size(mp); i++) { |
|---|
| 585 | | - if (be32_to_cpu(agfl->agfl_bno[i]) != NULLAGBLOCK && |
|---|
| 586 | | - be32_to_cpu(agfl->agfl_bno[i]) >= mp->m_sb.sb_agblocks) |
|---|
| 618 | + if (be32_to_cpu(agfl_bno[i]) != NULLAGBLOCK && |
|---|
| 619 | + be32_to_cpu(agfl_bno[i]) >= mp->m_sb.sb_agblocks) |
|---|
| 587 | 620 | return __this_address; |
|---|
| 588 | 621 | } |
|---|
| 589 | 622 | |
|---|
| .. | .. |
|---|
| 596 | 629 | xfs_agfl_read_verify( |
|---|
| 597 | 630 | struct xfs_buf *bp) |
|---|
| 598 | 631 | { |
|---|
| 599 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
|---|
| 632 | + struct xfs_mount *mp = bp->b_mount; |
|---|
| 600 | 633 | xfs_failaddr_t fa; |
|---|
| 601 | 634 | |
|---|
| 602 | 635 | /* |
|---|
| .. | .. |
|---|
| 621 | 654 | xfs_agfl_write_verify( |
|---|
| 622 | 655 | struct xfs_buf *bp) |
|---|
| 623 | 656 | { |
|---|
| 624 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
|---|
| 657 | + struct xfs_mount *mp = bp->b_mount; |
|---|
| 625 | 658 | struct xfs_buf_log_item *bip = bp->b_log_item; |
|---|
| 626 | 659 | xfs_failaddr_t fa; |
|---|
| 627 | 660 | |
|---|
| .. | .. |
|---|
| 643 | 676 | |
|---|
| 644 | 677 | const struct xfs_buf_ops xfs_agfl_buf_ops = { |
|---|
| 645 | 678 | .name = "xfs_agfl", |
|---|
| 679 | + .magic = { cpu_to_be32(XFS_AGFL_MAGIC), cpu_to_be32(XFS_AGFL_MAGIC) }, |
|---|
| 646 | 680 | .verify_read = xfs_agfl_read_verify, |
|---|
| 647 | 681 | .verify_write = xfs_agfl_write_verify, |
|---|
| 648 | 682 | .verify_struct = xfs_agfl_verify, |
|---|
| .. | .. |
|---|
| 676 | 710 | STATIC int |
|---|
| 677 | 711 | xfs_alloc_update_counters( |
|---|
| 678 | 712 | struct xfs_trans *tp, |
|---|
| 679 | | - struct xfs_perag *pag, |
|---|
| 680 | 713 | struct xfs_buf *agbp, |
|---|
| 681 | 714 | long len) |
|---|
| 682 | 715 | { |
|---|
| 683 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 716 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 684 | 717 | |
|---|
| 685 | | - pag->pagf_freeblks += len; |
|---|
| 718 | + agbp->b_pag->pagf_freeblks += len; |
|---|
| 686 | 719 | be32_add_cpu(&agf->agf_freeblks, len); |
|---|
| 687 | 720 | |
|---|
| 688 | 721 | xfs_trans_agblocks_delta(tp, len); |
|---|
| 689 | 722 | if (unlikely(be32_to_cpu(agf->agf_freeblks) > |
|---|
| 690 | | - be32_to_cpu(agf->agf_length))) |
|---|
| 723 | + be32_to_cpu(agf->agf_length))) { |
|---|
| 724 | + xfs_buf_mark_corrupt(agbp); |
|---|
| 691 | 725 | return -EFSCORRUPTED; |
|---|
| 726 | + } |
|---|
| 692 | 727 | |
|---|
| 693 | 728 | xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); |
|---|
| 694 | 729 | return 0; |
|---|
| 695 | 730 | } |
|---|
| 696 | 731 | |
|---|
| 697 | 732 | /* |
|---|
| 698 | | - * Allocation group level functions. |
|---|
| 733 | + * Block allocation algorithm and data structures. |
|---|
| 699 | 734 | */ |
|---|
| 735 | +struct xfs_alloc_cur { |
|---|
| 736 | + struct xfs_btree_cur *cnt; /* btree cursors */ |
|---|
| 737 | + struct xfs_btree_cur *bnolt; |
|---|
| 738 | + struct xfs_btree_cur *bnogt; |
|---|
| 739 | + xfs_extlen_t cur_len;/* current search length */ |
|---|
| 740 | + xfs_agblock_t rec_bno;/* extent startblock */ |
|---|
| 741 | + xfs_extlen_t rec_len;/* extent length */ |
|---|
| 742 | + xfs_agblock_t bno; /* alloc bno */ |
|---|
| 743 | + xfs_extlen_t len; /* alloc len */ |
|---|
| 744 | + xfs_extlen_t diff; /* diff from search bno */ |
|---|
| 745 | + unsigned int busy_gen;/* busy state */ |
|---|
| 746 | + bool busy; |
|---|
| 747 | +}; |
|---|
| 748 | + |
|---|
| 749 | +/* |
|---|
| 750 | + * Set up cursors, etc. in the extent allocation cursor. This function can be |
|---|
| 751 | + * called multiple times to reset an initialized structure without having to |
|---|
| 752 | + * reallocate cursors. |
|---|
| 753 | + */ |
|---|
| 754 | +static int |
|---|
| 755 | +xfs_alloc_cur_setup( |
|---|
| 756 | + struct xfs_alloc_arg *args, |
|---|
| 757 | + struct xfs_alloc_cur *acur) |
|---|
| 758 | +{ |
|---|
| 759 | + int error; |
|---|
| 760 | + int i; |
|---|
| 761 | + |
|---|
| 762 | + ASSERT(args->alignment == 1 || args->type != XFS_ALLOCTYPE_THIS_BNO); |
|---|
| 763 | + |
|---|
| 764 | + acur->cur_len = args->maxlen; |
|---|
| 765 | + acur->rec_bno = 0; |
|---|
| 766 | + acur->rec_len = 0; |
|---|
| 767 | + acur->bno = 0; |
|---|
| 768 | + acur->len = 0; |
|---|
| 769 | + acur->diff = -1; |
|---|
| 770 | + acur->busy = false; |
|---|
| 771 | + acur->busy_gen = 0; |
|---|
| 772 | + |
|---|
| 773 | + /* |
|---|
| 774 | + * Perform an initial cntbt lookup to check for availability of maxlen |
|---|
| 775 | + * extents. If this fails, we'll return -ENOSPC to signal the caller to |
|---|
| 776 | + * attempt a small allocation. |
|---|
| 777 | + */ |
|---|
| 778 | + if (!acur->cnt) |
|---|
| 779 | + acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp, |
|---|
| 780 | + args->agbp, args->agno, XFS_BTNUM_CNT); |
|---|
| 781 | + error = xfs_alloc_lookup_ge(acur->cnt, 0, args->maxlen, &i); |
|---|
| 782 | + if (error) |
|---|
| 783 | + return error; |
|---|
| 784 | + |
|---|
| 785 | + /* |
|---|
| 786 | + * Allocate the bnobt left and right search cursors. |
|---|
| 787 | + */ |
|---|
| 788 | + if (!acur->bnolt) |
|---|
| 789 | + acur->bnolt = xfs_allocbt_init_cursor(args->mp, args->tp, |
|---|
| 790 | + args->agbp, args->agno, XFS_BTNUM_BNO); |
|---|
| 791 | + if (!acur->bnogt) |
|---|
| 792 | + acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp, |
|---|
| 793 | + args->agbp, args->agno, XFS_BTNUM_BNO); |
|---|
| 794 | + return i == 1 ? 0 : -ENOSPC; |
|---|
| 795 | +} |
|---|
| 796 | + |
|---|
| 797 | +static void |
|---|
| 798 | +xfs_alloc_cur_close( |
|---|
| 799 | + struct xfs_alloc_cur *acur, |
|---|
| 800 | + bool error) |
|---|
| 801 | +{ |
|---|
| 802 | + int cur_error = XFS_BTREE_NOERROR; |
|---|
| 803 | + |
|---|
| 804 | + if (error) |
|---|
| 805 | + cur_error = XFS_BTREE_ERROR; |
|---|
| 806 | + |
|---|
| 807 | + if (acur->cnt) |
|---|
| 808 | + xfs_btree_del_cursor(acur->cnt, cur_error); |
|---|
| 809 | + if (acur->bnolt) |
|---|
| 810 | + xfs_btree_del_cursor(acur->bnolt, cur_error); |
|---|
| 811 | + if (acur->bnogt) |
|---|
| 812 | + xfs_btree_del_cursor(acur->bnogt, cur_error); |
|---|
| 813 | + acur->cnt = acur->bnolt = acur->bnogt = NULL; |
|---|
| 814 | +} |
|---|
| 815 | + |
|---|
| 816 | +/* |
|---|
| 817 | + * Check an extent for allocation and track the best available candidate in the |
|---|
| 818 | + * allocation structure. The cursor is deactivated if it has entered an out of |
|---|
| 819 | + * range state based on allocation arguments. Optionally return the extent |
|---|
| 820 | + * extent geometry and allocation status if requested by the caller. |
|---|
| 821 | + */ |
|---|
| 822 | +static int |
|---|
| 823 | +xfs_alloc_cur_check( |
|---|
| 824 | + struct xfs_alloc_arg *args, |
|---|
| 825 | + struct xfs_alloc_cur *acur, |
|---|
| 826 | + struct xfs_btree_cur *cur, |
|---|
| 827 | + int *new) |
|---|
| 828 | +{ |
|---|
| 829 | + int error, i; |
|---|
| 830 | + xfs_agblock_t bno, bnoa, bnew; |
|---|
| 831 | + xfs_extlen_t len, lena, diff = -1; |
|---|
| 832 | + bool busy; |
|---|
| 833 | + unsigned busy_gen = 0; |
|---|
| 834 | + bool deactivate = false; |
|---|
| 835 | + bool isbnobt = cur->bc_btnum == XFS_BTNUM_BNO; |
|---|
| 836 | + |
|---|
| 837 | + *new = 0; |
|---|
| 838 | + |
|---|
| 839 | + error = xfs_alloc_get_rec(cur, &bno, &len, &i); |
|---|
| 840 | + if (error) |
|---|
| 841 | + return error; |
|---|
| 842 | + if (XFS_IS_CORRUPT(args->mp, i != 1)) |
|---|
| 843 | + return -EFSCORRUPTED; |
|---|
| 844 | + |
|---|
| 845 | + /* |
|---|
| 846 | + * Check minlen and deactivate a cntbt cursor if out of acceptable size |
|---|
| 847 | + * range (i.e., walking backwards looking for a minlen extent). |
|---|
| 848 | + */ |
|---|
| 849 | + if (len < args->minlen) { |
|---|
| 850 | + deactivate = !isbnobt; |
|---|
| 851 | + goto out; |
|---|
| 852 | + } |
|---|
| 853 | + |
|---|
| 854 | + busy = xfs_alloc_compute_aligned(args, bno, len, &bnoa, &lena, |
|---|
| 855 | + &busy_gen); |
|---|
| 856 | + acur->busy |= busy; |
|---|
| 857 | + if (busy) |
|---|
| 858 | + acur->busy_gen = busy_gen; |
|---|
| 859 | + /* deactivate a bnobt cursor outside of locality range */ |
|---|
| 860 | + if (bnoa < args->min_agbno || bnoa > args->max_agbno) { |
|---|
| 861 | + deactivate = isbnobt; |
|---|
| 862 | + goto out; |
|---|
| 863 | + } |
|---|
| 864 | + if (lena < args->minlen) |
|---|
| 865 | + goto out; |
|---|
| 866 | + |
|---|
| 867 | + args->len = XFS_EXTLEN_MIN(lena, args->maxlen); |
|---|
| 868 | + xfs_alloc_fix_len(args); |
|---|
| 869 | + ASSERT(args->len >= args->minlen); |
|---|
| 870 | + if (args->len < acur->len) |
|---|
| 871 | + goto out; |
|---|
| 872 | + |
|---|
| 873 | + /* |
|---|
| 874 | + * We have an aligned record that satisfies minlen and beats or matches |
|---|
| 875 | + * the candidate extent size. Compare locality for near allocation mode. |
|---|
| 876 | + */ |
|---|
| 877 | + ASSERT(args->type == XFS_ALLOCTYPE_NEAR_BNO); |
|---|
| 878 | + diff = xfs_alloc_compute_diff(args->agbno, args->len, |
|---|
| 879 | + args->alignment, args->datatype, |
|---|
| 880 | + bnoa, lena, &bnew); |
|---|
| 881 | + if (bnew == NULLAGBLOCK) |
|---|
| 882 | + goto out; |
|---|
| 883 | + |
|---|
| 884 | + /* |
|---|
| 885 | + * Deactivate a bnobt cursor with worse locality than the current best. |
|---|
| 886 | + */ |
|---|
| 887 | + if (diff > acur->diff) { |
|---|
| 888 | + deactivate = isbnobt; |
|---|
| 889 | + goto out; |
|---|
| 890 | + } |
|---|
| 891 | + |
|---|
| 892 | + ASSERT(args->len > acur->len || |
|---|
| 893 | + (args->len == acur->len && diff <= acur->diff)); |
|---|
| 894 | + acur->rec_bno = bno; |
|---|
| 895 | + acur->rec_len = len; |
|---|
| 896 | + acur->bno = bnew; |
|---|
| 897 | + acur->len = args->len; |
|---|
| 898 | + acur->diff = diff; |
|---|
| 899 | + *new = 1; |
|---|
| 900 | + |
|---|
| 901 | + /* |
|---|
| 902 | + * We're done if we found a perfect allocation. This only deactivates |
|---|
| 903 | + * the current cursor, but this is just an optimization to terminate a |
|---|
| 904 | + * cntbt search that otherwise runs to the edge of the tree. |
|---|
| 905 | + */ |
|---|
| 906 | + if (acur->diff == 0 && acur->len == args->maxlen) |
|---|
| 907 | + deactivate = true; |
|---|
| 908 | +out: |
|---|
| 909 | + if (deactivate) |
|---|
| 910 | + cur->bc_ag.abt.active = false; |
|---|
| 911 | + trace_xfs_alloc_cur_check(args->mp, cur->bc_btnum, bno, len, diff, |
|---|
| 912 | + *new); |
|---|
| 913 | + return 0; |
|---|
| 914 | +} |
|---|
| 915 | + |
|---|
| 916 | +/* |
|---|
| 917 | + * Complete an allocation of a candidate extent. Remove the extent from both |
|---|
| 918 | + * trees and update the args structure. |
|---|
| 919 | + */ |
|---|
| 920 | +STATIC int |
|---|
| 921 | +xfs_alloc_cur_finish( |
|---|
| 922 | + struct xfs_alloc_arg *args, |
|---|
| 923 | + struct xfs_alloc_cur *acur) |
|---|
| 924 | +{ |
|---|
| 925 | + struct xfs_agf __maybe_unused *agf = args->agbp->b_addr; |
|---|
| 926 | + int error; |
|---|
| 927 | + |
|---|
| 928 | + ASSERT(acur->cnt && acur->bnolt); |
|---|
| 929 | + ASSERT(acur->bno >= acur->rec_bno); |
|---|
| 930 | + ASSERT(acur->bno + acur->len <= acur->rec_bno + acur->rec_len); |
|---|
| 931 | + ASSERT(acur->rec_bno + acur->rec_len <= be32_to_cpu(agf->agf_length)); |
|---|
| 932 | + |
|---|
| 933 | + error = xfs_alloc_fixup_trees(acur->cnt, acur->bnolt, acur->rec_bno, |
|---|
| 934 | + acur->rec_len, acur->bno, acur->len, 0); |
|---|
| 935 | + if (error) |
|---|
| 936 | + return error; |
|---|
| 937 | + |
|---|
| 938 | + args->agbno = acur->bno; |
|---|
| 939 | + args->len = acur->len; |
|---|
| 940 | + args->wasfromfl = 0; |
|---|
| 941 | + |
|---|
| 942 | + trace_xfs_alloc_cur(args); |
|---|
| 943 | + return 0; |
|---|
| 944 | +} |
|---|
| 945 | + |
|---|
| 946 | +/* |
|---|
| 947 | + * Locality allocation lookup algorithm. This expects a cntbt cursor and uses |
|---|
| 948 | + * bno optimized lookup to search for extents with ideal size and locality. |
|---|
| 949 | + */ |
|---|
| 950 | +STATIC int |
|---|
| 951 | +xfs_alloc_cntbt_iter( |
|---|
| 952 | + struct xfs_alloc_arg *args, |
|---|
| 953 | + struct xfs_alloc_cur *acur) |
|---|
| 954 | +{ |
|---|
| 955 | + struct xfs_btree_cur *cur = acur->cnt; |
|---|
| 956 | + xfs_agblock_t bno; |
|---|
| 957 | + xfs_extlen_t len, cur_len; |
|---|
| 958 | + int error; |
|---|
| 959 | + int i; |
|---|
| 960 | + |
|---|
| 961 | + if (!xfs_alloc_cur_active(cur)) |
|---|
| 962 | + return 0; |
|---|
| 963 | + |
|---|
| 964 | + /* locality optimized lookup */ |
|---|
| 965 | + cur_len = acur->cur_len; |
|---|
| 966 | + error = xfs_alloc_lookup_ge(cur, args->agbno, cur_len, &i); |
|---|
| 967 | + if (error) |
|---|
| 968 | + return error; |
|---|
| 969 | + if (i == 0) |
|---|
| 970 | + return 0; |
|---|
| 971 | + error = xfs_alloc_get_rec(cur, &bno, &len, &i); |
|---|
| 972 | + if (error) |
|---|
| 973 | + return error; |
|---|
| 974 | + |
|---|
| 975 | + /* check the current record and update search length from it */ |
|---|
| 976 | + error = xfs_alloc_cur_check(args, acur, cur, &i); |
|---|
| 977 | + if (error) |
|---|
| 978 | + return error; |
|---|
| 979 | + ASSERT(len >= acur->cur_len); |
|---|
| 980 | + acur->cur_len = len; |
|---|
| 981 | + |
|---|
| 982 | + /* |
|---|
| 983 | + * We looked up the first record >= [agbno, len] above. The agbno is a |
|---|
| 984 | + * secondary key and so the current record may lie just before or after |
|---|
| 985 | + * agbno. If it is past agbno, check the previous record too so long as |
|---|
| 986 | + * the length matches as it may be closer. Don't check a smaller record |
|---|
| 987 | + * because that could deactivate our cursor. |
|---|
| 988 | + */ |
|---|
| 989 | + if (bno > args->agbno) { |
|---|
| 990 | + error = xfs_btree_decrement(cur, 0, &i); |
|---|
| 991 | + if (!error && i) { |
|---|
| 992 | + error = xfs_alloc_get_rec(cur, &bno, &len, &i); |
|---|
| 993 | + if (!error && i && len == acur->cur_len) |
|---|
| 994 | + error = xfs_alloc_cur_check(args, acur, cur, |
|---|
| 995 | + &i); |
|---|
| 996 | + } |
|---|
| 997 | + if (error) |
|---|
| 998 | + return error; |
|---|
| 999 | + } |
|---|
| 1000 | + |
|---|
| 1001 | + /* |
|---|
| 1002 | + * Increment the search key until we find at least one allocation |
|---|
| 1003 | + * candidate or if the extent we found was larger. Otherwise, double the |
|---|
| 1004 | + * search key to optimize the search. Efficiency is more important here |
|---|
| 1005 | + * than absolute best locality. |
|---|
| 1006 | + */ |
|---|
| 1007 | + cur_len <<= 1; |
|---|
| 1008 | + if (!acur->len || acur->cur_len >= cur_len) |
|---|
| 1009 | + acur->cur_len++; |
|---|
| 1010 | + else |
|---|
| 1011 | + acur->cur_len = cur_len; |
|---|
| 1012 | + |
|---|
| 1013 | + return error; |
|---|
| 1014 | +} |
|---|
| 1015 | + |
|---|
| 1016 | +/* |
|---|
| 1017 | + * Deal with the case where only small freespaces remain. Either return the |
|---|
| 1018 | + * contents of the last freespace record, or allocate space from the freelist if |
|---|
| 1019 | + * there is nothing in the tree. |
|---|
| 1020 | + */ |
|---|
| 1021 | +STATIC int /* error */ |
|---|
| 1022 | +xfs_alloc_ag_vextent_small( |
|---|
| 1023 | + struct xfs_alloc_arg *args, /* allocation argument structure */ |
|---|
| 1024 | + struct xfs_btree_cur *ccur, /* optional by-size cursor */ |
|---|
| 1025 | + xfs_agblock_t *fbnop, /* result block number */ |
|---|
| 1026 | + xfs_extlen_t *flenp, /* result length */ |
|---|
| 1027 | + int *stat) /* status: 0-freelist, 1-normal/none */ |
|---|
| 1028 | +{ |
|---|
| 1029 | + struct xfs_agf *agf = args->agbp->b_addr; |
|---|
| 1030 | + int error = 0; |
|---|
| 1031 | + xfs_agblock_t fbno = NULLAGBLOCK; |
|---|
| 1032 | + xfs_extlen_t flen = 0; |
|---|
| 1033 | + int i = 0; |
|---|
| 1034 | + |
|---|
| 1035 | + /* |
|---|
| 1036 | + * If a cntbt cursor is provided, try to allocate the largest record in |
|---|
| 1037 | + * the tree. Try the AGFL if the cntbt is empty, otherwise fail the |
|---|
| 1038 | + * allocation. Make sure to respect minleft even when pulling from the |
|---|
| 1039 | + * freelist. |
|---|
| 1040 | + */ |
|---|
| 1041 | + if (ccur) |
|---|
| 1042 | + error = xfs_btree_decrement(ccur, 0, &i); |
|---|
| 1043 | + if (error) |
|---|
| 1044 | + goto error; |
|---|
| 1045 | + if (i) { |
|---|
| 1046 | + error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i); |
|---|
| 1047 | + if (error) |
|---|
| 1048 | + goto error; |
|---|
| 1049 | + if (XFS_IS_CORRUPT(args->mp, i != 1)) { |
|---|
| 1050 | + error = -EFSCORRUPTED; |
|---|
| 1051 | + goto error; |
|---|
| 1052 | + } |
|---|
| 1053 | + goto out; |
|---|
| 1054 | + } |
|---|
| 1055 | + |
|---|
| 1056 | + if (args->minlen != 1 || args->alignment != 1 || |
|---|
| 1057 | + args->resv == XFS_AG_RESV_AGFL || |
|---|
| 1058 | + be32_to_cpu(agf->agf_flcount) <= args->minleft) |
|---|
| 1059 | + goto out; |
|---|
| 1060 | + |
|---|
| 1061 | + error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); |
|---|
| 1062 | + if (error) |
|---|
| 1063 | + goto error; |
|---|
| 1064 | + if (fbno == NULLAGBLOCK) |
|---|
| 1065 | + goto out; |
|---|
| 1066 | + |
|---|
| 1067 | + xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, |
|---|
| 1068 | + (args->datatype & XFS_ALLOC_NOBUSY)); |
|---|
| 1069 | + |
|---|
| 1070 | + if (args->datatype & XFS_ALLOC_USERDATA) { |
|---|
| 1071 | + struct xfs_buf *bp; |
|---|
| 1072 | + |
|---|
| 1073 | + error = xfs_trans_get_buf(args->tp, args->mp->m_ddev_targp, |
|---|
| 1074 | + XFS_AGB_TO_DADDR(args->mp, args->agno, fbno), |
|---|
| 1075 | + args->mp->m_bsize, 0, &bp); |
|---|
| 1076 | + if (error) |
|---|
| 1077 | + goto error; |
|---|
| 1078 | + xfs_trans_binval(args->tp, bp); |
|---|
| 1079 | + } |
|---|
| 1080 | + *fbnop = args->agbno = fbno; |
|---|
| 1081 | + *flenp = args->len = 1; |
|---|
| 1082 | + if (XFS_IS_CORRUPT(args->mp, fbno >= be32_to_cpu(agf->agf_length))) { |
|---|
| 1083 | + error = -EFSCORRUPTED; |
|---|
| 1084 | + goto error; |
|---|
| 1085 | + } |
|---|
| 1086 | + args->wasfromfl = 1; |
|---|
| 1087 | + trace_xfs_alloc_small_freelist(args); |
|---|
| 1088 | + |
|---|
| 1089 | + /* |
|---|
| 1090 | + * If we're feeding an AGFL block to something that doesn't live in the |
|---|
| 1091 | + * free space, we need to clear out the OWN_AG rmap. |
|---|
| 1092 | + */ |
|---|
| 1093 | + error = xfs_rmap_free(args->tp, args->agbp, args->agno, fbno, 1, |
|---|
| 1094 | + &XFS_RMAP_OINFO_AG); |
|---|
| 1095 | + if (error) |
|---|
| 1096 | + goto error; |
|---|
| 1097 | + |
|---|
| 1098 | + *stat = 0; |
|---|
| 1099 | + return 0; |
|---|
| 1100 | + |
|---|
| 1101 | +out: |
|---|
| 1102 | + /* |
|---|
| 1103 | + * Can't do the allocation, give up. |
|---|
| 1104 | + */ |
|---|
| 1105 | + if (flen < args->minlen) { |
|---|
| 1106 | + args->agbno = NULLAGBLOCK; |
|---|
| 1107 | + trace_xfs_alloc_small_notenough(args); |
|---|
| 1108 | + flen = 0; |
|---|
| 1109 | + } |
|---|
| 1110 | + *fbnop = fbno; |
|---|
| 1111 | + *flenp = flen; |
|---|
| 1112 | + *stat = 1; |
|---|
| 1113 | + trace_xfs_alloc_small_done(args); |
|---|
| 1114 | + return 0; |
|---|
| 1115 | + |
|---|
| 1116 | +error: |
|---|
| 1117 | + trace_xfs_alloc_small_error(args); |
|---|
| 1118 | + return error; |
|---|
| 1119 | +} |
|---|
| 700 | 1120 | |
|---|
| 701 | 1121 | /* |
|---|
| 702 | 1122 | * Allocate a variable extent in the allocation group agno. |
|---|
| .. | .. |
|---|
| 754 | 1174 | } |
|---|
| 755 | 1175 | |
|---|
| 756 | 1176 | if (!args->wasfromfl) { |
|---|
| 757 | | - error = xfs_alloc_update_counters(args->tp, args->pag, |
|---|
| 758 | | - args->agbp, |
|---|
| 1177 | + error = xfs_alloc_update_counters(args->tp, args->agbp, |
|---|
| 759 | 1178 | -((long)(args->len))); |
|---|
| 760 | 1179 | if (error) |
|---|
| 761 | 1180 | return error; |
|---|
| .. | .. |
|---|
| 781 | 1200 | xfs_alloc_ag_vextent_exact( |
|---|
| 782 | 1201 | xfs_alloc_arg_t *args) /* allocation argument structure */ |
|---|
| 783 | 1202 | { |
|---|
| 1203 | + struct xfs_agf __maybe_unused *agf = args->agbp->b_addr; |
|---|
| 784 | 1204 | xfs_btree_cur_t *bno_cur;/* by block-number btree cursor */ |
|---|
| 785 | 1205 | xfs_btree_cur_t *cnt_cur;/* by count btree cursor */ |
|---|
| 786 | 1206 | int error; |
|---|
| .. | .. |
|---|
| 817 | 1237 | error = xfs_alloc_get_rec(bno_cur, &fbno, &flen, &i); |
|---|
| 818 | 1238 | if (error) |
|---|
| 819 | 1239 | goto error0; |
|---|
| 820 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1240 | + if (XFS_IS_CORRUPT(args->mp, i != 1)) { |
|---|
| 1241 | + error = -EFSCORRUPTED; |
|---|
| 1242 | + goto error0; |
|---|
| 1243 | + } |
|---|
| 821 | 1244 | ASSERT(fbno <= args->agbno); |
|---|
| 822 | 1245 | |
|---|
| 823 | 1246 | /* |
|---|
| .. | .. |
|---|
| 856 | 1279 | */ |
|---|
| 857 | 1280 | cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, |
|---|
| 858 | 1281 | args->agno, XFS_BTNUM_CNT); |
|---|
| 859 | | - ASSERT(args->agbno + args->len <= |
|---|
| 860 | | - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); |
|---|
| 1282 | + ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length)); |
|---|
| 861 | 1283 | error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno, |
|---|
| 862 | 1284 | args->len, XFSA_FIXUP_BNO_OK); |
|---|
| 863 | 1285 | if (error) { |
|---|
| .. | .. |
|---|
| 886 | 1308 | } |
|---|
| 887 | 1309 | |
|---|
| 888 | 1310 | /* |
|---|
| 889 | | - * Search the btree in a given direction via the search cursor and compare |
|---|
| 890 | | - * the records found against the good extent we've already found. |
|---|
| 1311 | + * Search a given number of btree records in a given direction. Check each |
|---|
| 1312 | + * record against the good extent we've already found. |
|---|
| 891 | 1313 | */ |
|---|
| 892 | 1314 | STATIC int |
|---|
| 893 | | -xfs_alloc_find_best_extent( |
|---|
| 894 | | - struct xfs_alloc_arg *args, /* allocation argument structure */ |
|---|
| 895 | | - struct xfs_btree_cur **gcur, /* good cursor */ |
|---|
| 896 | | - struct xfs_btree_cur **scur, /* searching cursor */ |
|---|
| 897 | | - xfs_agblock_t gdiff, /* difference for search comparison */ |
|---|
| 898 | | - xfs_agblock_t *sbno, /* extent found by search */ |
|---|
| 899 | | - xfs_extlen_t *slen, /* extent length */ |
|---|
| 900 | | - xfs_agblock_t *sbnoa, /* aligned extent found by search */ |
|---|
| 901 | | - xfs_extlen_t *slena, /* aligned extent length */ |
|---|
| 902 | | - int dir) /* 0 = search right, 1 = search left */ |
|---|
| 1315 | +xfs_alloc_walk_iter( |
|---|
| 1316 | + struct xfs_alloc_arg *args, |
|---|
| 1317 | + struct xfs_alloc_cur *acur, |
|---|
| 1318 | + struct xfs_btree_cur *cur, |
|---|
| 1319 | + bool increment, |
|---|
| 1320 | + bool find_one, /* quit on first candidate */ |
|---|
| 1321 | + int count, /* rec count (-1 for infinite) */ |
|---|
| 1322 | + int *stat) |
|---|
| 903 | 1323 | { |
|---|
| 904 | | - xfs_agblock_t new; |
|---|
| 905 | | - xfs_agblock_t sdiff; |
|---|
| 906 | 1324 | int error; |
|---|
| 907 | 1325 | int i; |
|---|
| 908 | | - unsigned busy_gen; |
|---|
| 909 | 1326 | |
|---|
| 910 | | - /* The good extent is perfect, no need to search. */ |
|---|
| 911 | | - if (!gdiff) |
|---|
| 912 | | - goto out_use_good; |
|---|
| 1327 | + *stat = 0; |
|---|
| 913 | 1328 | |
|---|
| 914 | 1329 | /* |
|---|
| 915 | | - * Look until we find a better one, run out of space or run off the end. |
|---|
| 1330 | + * Search so long as the cursor is active or we find a better extent. |
|---|
| 1331 | + * The cursor is deactivated if it extends beyond the range of the |
|---|
| 1332 | + * current allocation candidate. |
|---|
| 916 | 1333 | */ |
|---|
| 917 | | - do { |
|---|
| 918 | | - error = xfs_alloc_get_rec(*scur, sbno, slen, &i); |
|---|
| 1334 | + while (xfs_alloc_cur_active(cur) && count) { |
|---|
| 1335 | + error = xfs_alloc_cur_check(args, acur, cur, &i); |
|---|
| 919 | 1336 | if (error) |
|---|
| 920 | | - goto error0; |
|---|
| 921 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 922 | | - xfs_alloc_compute_aligned(args, *sbno, *slen, |
|---|
| 923 | | - sbnoa, slena, &busy_gen); |
|---|
| 924 | | - |
|---|
| 925 | | - /* |
|---|
| 926 | | - * The good extent is closer than this one. |
|---|
| 927 | | - */ |
|---|
| 928 | | - if (!dir) { |
|---|
| 929 | | - if (*sbnoa > args->max_agbno) |
|---|
| 930 | | - goto out_use_good; |
|---|
| 931 | | - if (*sbnoa >= args->agbno + gdiff) |
|---|
| 932 | | - goto out_use_good; |
|---|
| 933 | | - } else { |
|---|
| 934 | | - if (*sbnoa < args->min_agbno) |
|---|
| 935 | | - goto out_use_good; |
|---|
| 936 | | - if (*sbnoa <= args->agbno - gdiff) |
|---|
| 937 | | - goto out_use_good; |
|---|
| 1337 | + return error; |
|---|
| 1338 | + if (i == 1) { |
|---|
| 1339 | + *stat = 1; |
|---|
| 1340 | + if (find_one) |
|---|
| 1341 | + break; |
|---|
| 938 | 1342 | } |
|---|
| 1343 | + if (!xfs_alloc_cur_active(cur)) |
|---|
| 1344 | + break; |
|---|
| 939 | 1345 | |
|---|
| 940 | | - /* |
|---|
| 941 | | - * Same distance, compare length and pick the best. |
|---|
| 942 | | - */ |
|---|
| 943 | | - if (*slena >= args->minlen) { |
|---|
| 944 | | - args->len = XFS_EXTLEN_MIN(*slena, args->maxlen); |
|---|
| 945 | | - xfs_alloc_fix_len(args); |
|---|
| 946 | | - |
|---|
| 947 | | - sdiff = xfs_alloc_compute_diff(args->agbno, args->len, |
|---|
| 948 | | - args->alignment, |
|---|
| 949 | | - args->datatype, *sbnoa, |
|---|
| 950 | | - *slena, &new); |
|---|
| 951 | | - |
|---|
| 952 | | - /* |
|---|
| 953 | | - * Choose closer size and invalidate other cursor. |
|---|
| 954 | | - */ |
|---|
| 955 | | - if (sdiff < gdiff) |
|---|
| 956 | | - goto out_use_search; |
|---|
| 957 | | - goto out_use_good; |
|---|
| 958 | | - } |
|---|
| 959 | | - |
|---|
| 960 | | - if (!dir) |
|---|
| 961 | | - error = xfs_btree_increment(*scur, 0, &i); |
|---|
| 1346 | + if (increment) |
|---|
| 1347 | + error = xfs_btree_increment(cur, 0, &i); |
|---|
| 962 | 1348 | else |
|---|
| 963 | | - error = xfs_btree_decrement(*scur, 0, &i); |
|---|
| 1349 | + error = xfs_btree_decrement(cur, 0, &i); |
|---|
| 964 | 1350 | if (error) |
|---|
| 965 | | - goto error0; |
|---|
| 966 | | - } while (i); |
|---|
| 1351 | + return error; |
|---|
| 1352 | + if (i == 0) |
|---|
| 1353 | + cur->bc_ag.abt.active = false; |
|---|
| 967 | 1354 | |
|---|
| 968 | | -out_use_good: |
|---|
| 969 | | - xfs_btree_del_cursor(*scur, XFS_BTREE_NOERROR); |
|---|
| 970 | | - *scur = NULL; |
|---|
| 1355 | + if (count > 0) |
|---|
| 1356 | + count--; |
|---|
| 1357 | + } |
|---|
| 1358 | + |
|---|
| 971 | 1359 | return 0; |
|---|
| 1360 | +} |
|---|
| 972 | 1361 | |
|---|
| 973 | | -out_use_search: |
|---|
| 974 | | - xfs_btree_del_cursor(*gcur, XFS_BTREE_NOERROR); |
|---|
| 975 | | - *gcur = NULL; |
|---|
| 1362 | +/* |
|---|
| 1363 | + * Search the by-bno and by-size btrees in parallel in search of an extent with |
|---|
| 1364 | + * ideal locality based on the NEAR mode ->agbno locality hint. |
|---|
| 1365 | + */ |
|---|
| 1366 | +STATIC int |
|---|
| 1367 | +xfs_alloc_ag_vextent_locality( |
|---|
| 1368 | + struct xfs_alloc_arg *args, |
|---|
| 1369 | + struct xfs_alloc_cur *acur, |
|---|
| 1370 | + int *stat) |
|---|
| 1371 | +{ |
|---|
| 1372 | + struct xfs_btree_cur *fbcur = NULL; |
|---|
| 1373 | + int error; |
|---|
| 1374 | + int i; |
|---|
| 1375 | + bool fbinc; |
|---|
| 1376 | + |
|---|
| 1377 | + ASSERT(acur->len == 0); |
|---|
| 1378 | + ASSERT(args->type == XFS_ALLOCTYPE_NEAR_BNO); |
|---|
| 1379 | + |
|---|
| 1380 | + *stat = 0; |
|---|
| 1381 | + |
|---|
| 1382 | + error = xfs_alloc_lookup_ge(acur->cnt, args->agbno, acur->cur_len, &i); |
|---|
| 1383 | + if (error) |
|---|
| 1384 | + return error; |
|---|
| 1385 | + error = xfs_alloc_lookup_le(acur->bnolt, args->agbno, 0, &i); |
|---|
| 1386 | + if (error) |
|---|
| 1387 | + return error; |
|---|
| 1388 | + error = xfs_alloc_lookup_ge(acur->bnogt, args->agbno, 0, &i); |
|---|
| 1389 | + if (error) |
|---|
| 1390 | + return error; |
|---|
| 1391 | + |
|---|
| 1392 | + /* |
|---|
| 1393 | + * Search the bnobt and cntbt in parallel. Search the bnobt left and |
|---|
| 1394 | + * right and lookup the closest extent to the locality hint for each |
|---|
| 1395 | + * extent size key in the cntbt. The entire search terminates |
|---|
| 1396 | + * immediately on a bnobt hit because that means we've found best case |
|---|
| 1397 | + * locality. Otherwise the search continues until the cntbt cursor runs |
|---|
| 1398 | + * off the end of the tree. If no allocation candidate is found at this |
|---|
| 1399 | + * point, give up on locality, walk backwards from the end of the cntbt |
|---|
| 1400 | + * and take the first available extent. |
|---|
| 1401 | + * |
|---|
| 1402 | + * The parallel tree searches balance each other out to provide fairly |
|---|
| 1403 | + * consistent performance for various situations. The bnobt search can |
|---|
| 1404 | + * have pathological behavior in the worst case scenario of larger |
|---|
| 1405 | + * allocation requests and fragmented free space. On the other hand, the |
|---|
| 1406 | + * bnobt is able to satisfy most smaller allocation requests much more |
|---|
| 1407 | + * quickly than the cntbt. The cntbt search can sift through fragmented |
|---|
| 1408 | + * free space and sets of free extents for larger allocation requests |
|---|
| 1409 | + * more quickly than the bnobt. Since the locality hint is just a hint |
|---|
| 1410 | + * and we don't want to scan the entire bnobt for perfect locality, the |
|---|
| 1411 | + * cntbt search essentially bounds the bnobt search such that we can |
|---|
| 1412 | + * find good enough locality at reasonable performance in most cases. |
|---|
| 1413 | + */ |
|---|
| 1414 | + while (xfs_alloc_cur_active(acur->bnolt) || |
|---|
| 1415 | + xfs_alloc_cur_active(acur->bnogt) || |
|---|
| 1416 | + xfs_alloc_cur_active(acur->cnt)) { |
|---|
| 1417 | + |
|---|
| 1418 | + trace_xfs_alloc_cur_lookup(args); |
|---|
| 1419 | + |
|---|
| 1420 | + /* |
|---|
| 1421 | + * Search the bnobt left and right. In the case of a hit, finish |
|---|
| 1422 | + * the search in the opposite direction and we're done. |
|---|
| 1423 | + */ |
|---|
| 1424 | + error = xfs_alloc_walk_iter(args, acur, acur->bnolt, false, |
|---|
| 1425 | + true, 1, &i); |
|---|
| 1426 | + if (error) |
|---|
| 1427 | + return error; |
|---|
| 1428 | + if (i == 1) { |
|---|
| 1429 | + trace_xfs_alloc_cur_left(args); |
|---|
| 1430 | + fbcur = acur->bnogt; |
|---|
| 1431 | + fbinc = true; |
|---|
| 1432 | + break; |
|---|
| 1433 | + } |
|---|
| 1434 | + error = xfs_alloc_walk_iter(args, acur, acur->bnogt, true, true, |
|---|
| 1435 | + 1, &i); |
|---|
| 1436 | + if (error) |
|---|
| 1437 | + return error; |
|---|
| 1438 | + if (i == 1) { |
|---|
| 1439 | + trace_xfs_alloc_cur_right(args); |
|---|
| 1440 | + fbcur = acur->bnolt; |
|---|
| 1441 | + fbinc = false; |
|---|
| 1442 | + break; |
|---|
| 1443 | + } |
|---|
| 1444 | + |
|---|
| 1445 | + /* |
|---|
| 1446 | + * Check the extent with best locality based on the current |
|---|
| 1447 | + * extent size search key and keep track of the best candidate. |
|---|
| 1448 | + */ |
|---|
| 1449 | + error = xfs_alloc_cntbt_iter(args, acur); |
|---|
| 1450 | + if (error) |
|---|
| 1451 | + return error; |
|---|
| 1452 | + if (!xfs_alloc_cur_active(acur->cnt)) { |
|---|
| 1453 | + trace_xfs_alloc_cur_lookup_done(args); |
|---|
| 1454 | + break; |
|---|
| 1455 | + } |
|---|
| 1456 | + } |
|---|
| 1457 | + |
|---|
| 1458 | + /* |
|---|
| 1459 | + * If we failed to find anything due to busy extents, return empty |
|---|
| 1460 | + * handed so the caller can flush and retry. If no busy extents were |
|---|
| 1461 | + * found, walk backwards from the end of the cntbt as a last resort. |
|---|
| 1462 | + */ |
|---|
| 1463 | + if (!xfs_alloc_cur_active(acur->cnt) && !acur->len && !acur->busy) { |
|---|
| 1464 | + error = xfs_btree_decrement(acur->cnt, 0, &i); |
|---|
| 1465 | + if (error) |
|---|
| 1466 | + return error; |
|---|
| 1467 | + if (i) { |
|---|
| 1468 | + acur->cnt->bc_ag.abt.active = true; |
|---|
| 1469 | + fbcur = acur->cnt; |
|---|
| 1470 | + fbinc = false; |
|---|
| 1471 | + } |
|---|
| 1472 | + } |
|---|
| 1473 | + |
|---|
| 1474 | + /* |
|---|
| 1475 | + * Search in the opposite direction for a better entry in the case of |
|---|
| 1476 | + * a bnobt hit or walk backwards from the end of the cntbt. |
|---|
| 1477 | + */ |
|---|
| 1478 | + if (fbcur) { |
|---|
| 1479 | + error = xfs_alloc_walk_iter(args, acur, fbcur, fbinc, true, -1, |
|---|
| 1480 | + &i); |
|---|
| 1481 | + if (error) |
|---|
| 1482 | + return error; |
|---|
| 1483 | + } |
|---|
| 1484 | + |
|---|
| 1485 | + if (acur->len) |
|---|
| 1486 | + *stat = 1; |
|---|
| 1487 | + |
|---|
| 976 | 1488 | return 0; |
|---|
| 1489 | +} |
|---|
| 977 | 1490 | |
|---|
| 978 | | -error0: |
|---|
| 979 | | - /* caller invalidates cursors */ |
|---|
| 980 | | - return error; |
|---|
| 1491 | +/* Check the last block of the cnt btree for allocations. */ |
|---|
| 1492 | +static int |
|---|
| 1493 | +xfs_alloc_ag_vextent_lastblock( |
|---|
| 1494 | + struct xfs_alloc_arg *args, |
|---|
| 1495 | + struct xfs_alloc_cur *acur, |
|---|
| 1496 | + xfs_agblock_t *bno, |
|---|
| 1497 | + xfs_extlen_t *len, |
|---|
| 1498 | + bool *allocated) |
|---|
| 1499 | +{ |
|---|
| 1500 | + int error; |
|---|
| 1501 | + int i; |
|---|
| 1502 | + |
|---|
| 1503 | +#ifdef DEBUG |
|---|
| 1504 | + /* Randomly don't execute the first algorithm. */ |
|---|
| 1505 | + if (prandom_u32() & 1) |
|---|
| 1506 | + return 0; |
|---|
| 1507 | +#endif |
|---|
| 1508 | + |
|---|
| 1509 | + /* |
|---|
| 1510 | + * Start from the entry that lookup found, sequence through all larger |
|---|
| 1511 | + * free blocks. If we're actually pointing at a record smaller than |
|---|
| 1512 | + * maxlen, go to the start of this block, and skip all those smaller |
|---|
| 1513 | + * than minlen. |
|---|
| 1514 | + */ |
|---|
| 1515 | + if (*len || args->alignment > 1) { |
|---|
| 1516 | + acur->cnt->bc_ptrs[0] = 1; |
|---|
| 1517 | + do { |
|---|
| 1518 | + error = xfs_alloc_get_rec(acur->cnt, bno, len, &i); |
|---|
| 1519 | + if (error) |
|---|
| 1520 | + return error; |
|---|
| 1521 | + if (XFS_IS_CORRUPT(args->mp, i != 1)) |
|---|
| 1522 | + return -EFSCORRUPTED; |
|---|
| 1523 | + if (*len >= args->minlen) |
|---|
| 1524 | + break; |
|---|
| 1525 | + error = xfs_btree_increment(acur->cnt, 0, &i); |
|---|
| 1526 | + if (error) |
|---|
| 1527 | + return error; |
|---|
| 1528 | + } while (i); |
|---|
| 1529 | + ASSERT(*len >= args->minlen); |
|---|
| 1530 | + if (!i) |
|---|
| 1531 | + return 0; |
|---|
| 1532 | + } |
|---|
| 1533 | + |
|---|
| 1534 | + error = xfs_alloc_walk_iter(args, acur, acur->cnt, true, false, -1, &i); |
|---|
| 1535 | + if (error) |
|---|
| 1536 | + return error; |
|---|
| 1537 | + |
|---|
| 1538 | + /* |
|---|
| 1539 | + * It didn't work. We COULD be in a case where there's a good record |
|---|
| 1540 | + * somewhere, so try again. |
|---|
| 1541 | + */ |
|---|
| 1542 | + if (acur->len == 0) |
|---|
| 1543 | + return 0; |
|---|
| 1544 | + |
|---|
| 1545 | + trace_xfs_alloc_near_first(args); |
|---|
| 1546 | + *allocated = true; |
|---|
| 1547 | + return 0; |
|---|
| 981 | 1548 | } |
|---|
| 982 | 1549 | |
|---|
| 983 | 1550 | /* |
|---|
| .. | .. |
|---|
| 986 | 1553 | * and of the form k * prod + mod unless there's nothing that large. |
|---|
| 987 | 1554 | * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. |
|---|
| 988 | 1555 | */ |
|---|
| 989 | | -STATIC int /* error */ |
|---|
| 1556 | +STATIC int |
|---|
| 990 | 1557 | xfs_alloc_ag_vextent_near( |
|---|
| 991 | | - xfs_alloc_arg_t *args) /* allocation argument structure */ |
|---|
| 1558 | + struct xfs_alloc_arg *args) |
|---|
| 992 | 1559 | { |
|---|
| 993 | | - xfs_btree_cur_t *bno_cur_gt; /* cursor for bno btree, right side */ |
|---|
| 994 | | - xfs_btree_cur_t *bno_cur_lt; /* cursor for bno btree, left side */ |
|---|
| 995 | | - xfs_btree_cur_t *cnt_cur; /* cursor for count btree */ |
|---|
| 996 | | - xfs_agblock_t gtbno; /* start bno of right side entry */ |
|---|
| 997 | | - xfs_agblock_t gtbnoa; /* aligned ... */ |
|---|
| 998 | | - xfs_extlen_t gtdiff; /* difference to right side entry */ |
|---|
| 999 | | - xfs_extlen_t gtlen; /* length of right side entry */ |
|---|
| 1000 | | - xfs_extlen_t gtlena; /* aligned ... */ |
|---|
| 1001 | | - xfs_agblock_t gtnew; /* useful start bno of right side */ |
|---|
| 1002 | | - int error; /* error code */ |
|---|
| 1003 | | - int i; /* result code, temporary */ |
|---|
| 1004 | | - int j; /* result code, temporary */ |
|---|
| 1005 | | - xfs_agblock_t ltbno; /* start bno of left side entry */ |
|---|
| 1006 | | - xfs_agblock_t ltbnoa; /* aligned ... */ |
|---|
| 1007 | | - xfs_extlen_t ltdiff; /* difference to left side entry */ |
|---|
| 1008 | | - xfs_extlen_t ltlen; /* length of left side entry */ |
|---|
| 1009 | | - xfs_extlen_t ltlena; /* aligned ... */ |
|---|
| 1010 | | - xfs_agblock_t ltnew; /* useful start bno of left side */ |
|---|
| 1011 | | - xfs_extlen_t rlen; /* length of returned extent */ |
|---|
| 1012 | | - bool busy; |
|---|
| 1013 | | - unsigned busy_gen; |
|---|
| 1014 | | -#ifdef DEBUG |
|---|
| 1015 | | - /* |
|---|
| 1016 | | - * Randomly don't execute the first algorithm. |
|---|
| 1017 | | - */ |
|---|
| 1018 | | - int dofirst; /* set to do first algorithm */ |
|---|
| 1560 | + struct xfs_alloc_cur acur = {}; |
|---|
| 1561 | + int error; /* error code */ |
|---|
| 1562 | + int i; /* result code, temporary */ |
|---|
| 1563 | + xfs_agblock_t bno; |
|---|
| 1564 | + xfs_extlen_t len; |
|---|
| 1019 | 1565 | |
|---|
| 1020 | | - dofirst = prandom_u32() & 1; |
|---|
| 1021 | | -#endif |
|---|
| 1022 | | - |
|---|
| 1023 | | - /* handle unitialized agbno range so caller doesn't have to */ |
|---|
| 1566 | + /* handle uninitialized agbno range so caller doesn't have to */ |
|---|
| 1024 | 1567 | if (!args->min_agbno && !args->max_agbno) |
|---|
| 1025 | 1568 | args->max_agbno = args->mp->m_sb.sb_agblocks - 1; |
|---|
| 1026 | 1569 | ASSERT(args->min_agbno <= args->max_agbno); |
|---|
| .. | .. |
|---|
| 1032 | 1575 | args->agbno = args->max_agbno; |
|---|
| 1033 | 1576 | |
|---|
| 1034 | 1577 | restart: |
|---|
| 1035 | | - bno_cur_lt = NULL; |
|---|
| 1036 | | - bno_cur_gt = NULL; |
|---|
| 1037 | | - ltlen = 0; |
|---|
| 1038 | | - gtlena = 0; |
|---|
| 1039 | | - ltlena = 0; |
|---|
| 1040 | | - busy = false; |
|---|
| 1578 | + len = 0; |
|---|
| 1041 | 1579 | |
|---|
| 1042 | 1580 | /* |
|---|
| 1043 | | - * Get a cursor for the by-size btree. |
|---|
| 1581 | + * Set up cursors and see if there are any free extents as big as |
|---|
| 1582 | + * maxlen. If not, pick the last entry in the tree unless the tree is |
|---|
| 1583 | + * empty. |
|---|
| 1044 | 1584 | */ |
|---|
| 1045 | | - cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, |
|---|
| 1046 | | - args->agno, XFS_BTNUM_CNT); |
|---|
| 1047 | | - |
|---|
| 1048 | | - /* |
|---|
| 1049 | | - * See if there are any free extents as big as maxlen. |
|---|
| 1050 | | - */ |
|---|
| 1051 | | - if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, args->maxlen, &i))) |
|---|
| 1052 | | - goto error0; |
|---|
| 1053 | | - /* |
|---|
| 1054 | | - * If none, then pick up the last entry in the tree unless the |
|---|
| 1055 | | - * tree is empty. |
|---|
| 1056 | | - */ |
|---|
| 1057 | | - if (!i) { |
|---|
| 1058 | | - if ((error = xfs_alloc_ag_vextent_small(args, cnt_cur, <bno, |
|---|
| 1059 | | - <len, &i))) |
|---|
| 1060 | | - goto error0; |
|---|
| 1061 | | - if (i == 0 || ltlen == 0) { |
|---|
| 1062 | | - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
|---|
| 1585 | + error = xfs_alloc_cur_setup(args, &acur); |
|---|
| 1586 | + if (error == -ENOSPC) { |
|---|
| 1587 | + error = xfs_alloc_ag_vextent_small(args, acur.cnt, &bno, |
|---|
| 1588 | + &len, &i); |
|---|
| 1589 | + if (error) |
|---|
| 1590 | + goto out; |
|---|
| 1591 | + if (i == 0 || len == 0) { |
|---|
| 1063 | 1592 | trace_xfs_alloc_near_noentry(args); |
|---|
| 1064 | | - return 0; |
|---|
| 1593 | + goto out; |
|---|
| 1065 | 1594 | } |
|---|
| 1066 | 1595 | ASSERT(i == 1); |
|---|
| 1596 | + } else if (error) { |
|---|
| 1597 | + goto out; |
|---|
| 1067 | 1598 | } |
|---|
| 1068 | | - args->wasfromfl = 0; |
|---|
| 1069 | 1599 | |
|---|
| 1070 | 1600 | /* |
|---|
| 1071 | 1601 | * First algorithm. |
|---|
| .. | .. |
|---|
| 1074 | 1604 | * near the right edge of the tree. If it's in the last btree leaf |
|---|
| 1075 | 1605 | * block, then we just examine all the entries in that block |
|---|
| 1076 | 1606 | * that are big enough, and pick the best one. |
|---|
| 1077 | | - * This is written as a while loop so we can break out of it, |
|---|
| 1078 | | - * but we never loop back to the top. |
|---|
| 1079 | 1607 | */ |
|---|
| 1080 | | - while (xfs_btree_islastblock(cnt_cur, 0)) { |
|---|
| 1081 | | - xfs_extlen_t bdiff; |
|---|
| 1082 | | - int besti=0; |
|---|
| 1083 | | - xfs_extlen_t blen=0; |
|---|
| 1084 | | - xfs_agblock_t bnew=0; |
|---|
| 1608 | + if (xfs_btree_islastblock(acur.cnt, 0)) { |
|---|
| 1609 | + bool allocated = false; |
|---|
| 1085 | 1610 | |
|---|
| 1086 | | -#ifdef DEBUG |
|---|
| 1087 | | - if (dofirst) |
|---|
| 1088 | | - break; |
|---|
| 1089 | | -#endif |
|---|
| 1090 | | - /* |
|---|
| 1091 | | - * Start from the entry that lookup found, sequence through |
|---|
| 1092 | | - * all larger free blocks. If we're actually pointing at a |
|---|
| 1093 | | - * record smaller than maxlen, go to the start of this block, |
|---|
| 1094 | | - * and skip all those smaller than minlen. |
|---|
| 1095 | | - */ |
|---|
| 1096 | | - if (ltlen || args->alignment > 1) { |
|---|
| 1097 | | - cnt_cur->bc_ptrs[0] = 1; |
|---|
| 1098 | | - do { |
|---|
| 1099 | | - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, |
|---|
| 1100 | | - <len, &i))) |
|---|
| 1101 | | - goto error0; |
|---|
| 1102 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1103 | | - if (ltlen >= args->minlen) |
|---|
| 1104 | | - break; |
|---|
| 1105 | | - if ((error = xfs_btree_increment(cnt_cur, 0, &i))) |
|---|
| 1106 | | - goto error0; |
|---|
| 1107 | | - } while (i); |
|---|
| 1108 | | - ASSERT(ltlen >= args->minlen); |
|---|
| 1109 | | - if (!i) |
|---|
| 1110 | | - break; |
|---|
| 1111 | | - } |
|---|
| 1112 | | - i = cnt_cur->bc_ptrs[0]; |
|---|
| 1113 | | - for (j = 1, blen = 0, bdiff = 0; |
|---|
| 1114 | | - !error && j && (blen < args->maxlen || bdiff > 0); |
|---|
| 1115 | | - error = xfs_btree_increment(cnt_cur, 0, &j)) { |
|---|
| 1116 | | - /* |
|---|
| 1117 | | - * For each entry, decide if it's better than |
|---|
| 1118 | | - * the previous best entry. |
|---|
| 1119 | | - */ |
|---|
| 1120 | | - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) |
|---|
| 1121 | | - goto error0; |
|---|
| 1122 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1123 | | - busy = xfs_alloc_compute_aligned(args, ltbno, ltlen, |
|---|
| 1124 | | - <bnoa, <lena, &busy_gen); |
|---|
| 1125 | | - if (ltlena < args->minlen) |
|---|
| 1126 | | - continue; |
|---|
| 1127 | | - if (ltbnoa < args->min_agbno || ltbnoa > args->max_agbno) |
|---|
| 1128 | | - continue; |
|---|
| 1129 | | - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); |
|---|
| 1130 | | - xfs_alloc_fix_len(args); |
|---|
| 1131 | | - ASSERT(args->len >= args->minlen); |
|---|
| 1132 | | - if (args->len < blen) |
|---|
| 1133 | | - continue; |
|---|
| 1134 | | - ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, |
|---|
| 1135 | | - args->alignment, args->datatype, ltbnoa, |
|---|
| 1136 | | - ltlena, <new); |
|---|
| 1137 | | - if (ltnew != NULLAGBLOCK && |
|---|
| 1138 | | - (args->len > blen || ltdiff < bdiff)) { |
|---|
| 1139 | | - bdiff = ltdiff; |
|---|
| 1140 | | - bnew = ltnew; |
|---|
| 1141 | | - blen = args->len; |
|---|
| 1142 | | - besti = cnt_cur->bc_ptrs[0]; |
|---|
| 1143 | | - } |
|---|
| 1144 | | - } |
|---|
| 1145 | | - /* |
|---|
| 1146 | | - * It didn't work. We COULD be in a case where |
|---|
| 1147 | | - * there's a good record somewhere, so try again. |
|---|
| 1148 | | - */ |
|---|
| 1149 | | - if (blen == 0) |
|---|
| 1150 | | - break; |
|---|
| 1151 | | - /* |
|---|
| 1152 | | - * Point at the best entry, and retrieve it again. |
|---|
| 1153 | | - */ |
|---|
| 1154 | | - cnt_cur->bc_ptrs[0] = besti; |
|---|
| 1155 | | - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) |
|---|
| 1156 | | - goto error0; |
|---|
| 1157 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1158 | | - ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); |
|---|
| 1159 | | - args->len = blen; |
|---|
| 1160 | | - |
|---|
| 1161 | | - /* |
|---|
| 1162 | | - * We are allocating starting at bnew for blen blocks. |
|---|
| 1163 | | - */ |
|---|
| 1164 | | - args->agbno = bnew; |
|---|
| 1165 | | - ASSERT(bnew >= ltbno); |
|---|
| 1166 | | - ASSERT(bnew + blen <= ltbno + ltlen); |
|---|
| 1167 | | - /* |
|---|
| 1168 | | - * Set up a cursor for the by-bno tree. |
|---|
| 1169 | | - */ |
|---|
| 1170 | | - bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, |
|---|
| 1171 | | - args->agbp, args->agno, XFS_BTNUM_BNO); |
|---|
| 1172 | | - /* |
|---|
| 1173 | | - * Fix up the btree entries. |
|---|
| 1174 | | - */ |
|---|
| 1175 | | - if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, |
|---|
| 1176 | | - ltlen, bnew, blen, XFSA_FIXUP_CNT_OK))) |
|---|
| 1177 | | - goto error0; |
|---|
| 1178 | | - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
|---|
| 1179 | | - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); |
|---|
| 1180 | | - |
|---|
| 1181 | | - trace_xfs_alloc_near_first(args); |
|---|
| 1182 | | - return 0; |
|---|
| 1183 | | - } |
|---|
| 1184 | | - /* |
|---|
| 1185 | | - * Second algorithm. |
|---|
| 1186 | | - * Search in the by-bno tree to the left and to the right |
|---|
| 1187 | | - * simultaneously, until in each case we find a space big enough, |
|---|
| 1188 | | - * or run into the edge of the tree. When we run into the edge, |
|---|
| 1189 | | - * we deallocate that cursor. |
|---|
| 1190 | | - * If both searches succeed, we compare the two spaces and pick |
|---|
| 1191 | | - * the better one. |
|---|
| 1192 | | - * With alignment, it's possible for both to fail; the upper |
|---|
| 1193 | | - * level algorithm that picks allocation groups for allocations |
|---|
| 1194 | | - * is not supposed to do this. |
|---|
| 1195 | | - */ |
|---|
| 1196 | | - /* |
|---|
| 1197 | | - * Allocate and initialize the cursor for the leftward search. |
|---|
| 1198 | | - */ |
|---|
| 1199 | | - bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, |
|---|
| 1200 | | - args->agno, XFS_BTNUM_BNO); |
|---|
| 1201 | | - /* |
|---|
| 1202 | | - * Lookup <= bno to find the leftward search's starting point. |
|---|
| 1203 | | - */ |
|---|
| 1204 | | - if ((error = xfs_alloc_lookup_le(bno_cur_lt, args->agbno, args->maxlen, &i))) |
|---|
| 1205 | | - goto error0; |
|---|
| 1206 | | - if (!i) { |
|---|
| 1207 | | - /* |
|---|
| 1208 | | - * Didn't find anything; use this cursor for the rightward |
|---|
| 1209 | | - * search. |
|---|
| 1210 | | - */ |
|---|
| 1211 | | - bno_cur_gt = bno_cur_lt; |
|---|
| 1212 | | - bno_cur_lt = NULL; |
|---|
| 1213 | | - } |
|---|
| 1214 | | - /* |
|---|
| 1215 | | - * Found something. Duplicate the cursor for the rightward search. |
|---|
| 1216 | | - */ |
|---|
| 1217 | | - else if ((error = xfs_btree_dup_cursor(bno_cur_lt, &bno_cur_gt))) |
|---|
| 1218 | | - goto error0; |
|---|
| 1219 | | - /* |
|---|
| 1220 | | - * Increment the cursor, so we will point at the entry just right |
|---|
| 1221 | | - * of the leftward entry if any, or to the leftmost entry. |
|---|
| 1222 | | - */ |
|---|
| 1223 | | - if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) |
|---|
| 1224 | | - goto error0; |
|---|
| 1225 | | - if (!i) { |
|---|
| 1226 | | - /* |
|---|
| 1227 | | - * It failed, there are no rightward entries. |
|---|
| 1228 | | - */ |
|---|
| 1229 | | - xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR); |
|---|
| 1230 | | - bno_cur_gt = NULL; |
|---|
| 1231 | | - } |
|---|
| 1232 | | - /* |
|---|
| 1233 | | - * Loop going left with the leftward cursor, right with the |
|---|
| 1234 | | - * rightward cursor, until either both directions give up or |
|---|
| 1235 | | - * we find an entry at least as big as minlen. |
|---|
| 1236 | | - */ |
|---|
| 1237 | | - do { |
|---|
| 1238 | | - if (bno_cur_lt) { |
|---|
| 1239 | | - if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i))) |
|---|
| 1240 | | - goto error0; |
|---|
| 1241 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1242 | | - busy |= xfs_alloc_compute_aligned(args, ltbno, ltlen, |
|---|
| 1243 | | - <bnoa, <lena, &busy_gen); |
|---|
| 1244 | | - if (ltlena >= args->minlen && ltbnoa >= args->min_agbno) |
|---|
| 1245 | | - break; |
|---|
| 1246 | | - if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) |
|---|
| 1247 | | - goto error0; |
|---|
| 1248 | | - if (!i || ltbnoa < args->min_agbno) { |
|---|
| 1249 | | - xfs_btree_del_cursor(bno_cur_lt, |
|---|
| 1250 | | - XFS_BTREE_NOERROR); |
|---|
| 1251 | | - bno_cur_lt = NULL; |
|---|
| 1252 | | - } |
|---|
| 1253 | | - } |
|---|
| 1254 | | - if (bno_cur_gt) { |
|---|
| 1255 | | - if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i))) |
|---|
| 1256 | | - goto error0; |
|---|
| 1257 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1258 | | - busy |= xfs_alloc_compute_aligned(args, gtbno, gtlen, |
|---|
| 1259 | | - >bnoa, >lena, &busy_gen); |
|---|
| 1260 | | - if (gtlena >= args->minlen && gtbnoa <= args->max_agbno) |
|---|
| 1261 | | - break; |
|---|
| 1262 | | - if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) |
|---|
| 1263 | | - goto error0; |
|---|
| 1264 | | - if (!i || gtbnoa > args->max_agbno) { |
|---|
| 1265 | | - xfs_btree_del_cursor(bno_cur_gt, |
|---|
| 1266 | | - XFS_BTREE_NOERROR); |
|---|
| 1267 | | - bno_cur_gt = NULL; |
|---|
| 1268 | | - } |
|---|
| 1269 | | - } |
|---|
| 1270 | | - } while (bno_cur_lt || bno_cur_gt); |
|---|
| 1271 | | - |
|---|
| 1272 | | - /* |
|---|
| 1273 | | - * Got both cursors still active, need to find better entry. |
|---|
| 1274 | | - */ |
|---|
| 1275 | | - if (bno_cur_lt && bno_cur_gt) { |
|---|
| 1276 | | - if (ltlena >= args->minlen) { |
|---|
| 1277 | | - /* |
|---|
| 1278 | | - * Left side is good, look for a right side entry. |
|---|
| 1279 | | - */ |
|---|
| 1280 | | - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); |
|---|
| 1281 | | - xfs_alloc_fix_len(args); |
|---|
| 1282 | | - ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, |
|---|
| 1283 | | - args->alignment, args->datatype, ltbnoa, |
|---|
| 1284 | | - ltlena, <new); |
|---|
| 1285 | | - |
|---|
| 1286 | | - error = xfs_alloc_find_best_extent(args, |
|---|
| 1287 | | - &bno_cur_lt, &bno_cur_gt, |
|---|
| 1288 | | - ltdiff, >bno, >len, |
|---|
| 1289 | | - >bnoa, >lena, |
|---|
| 1290 | | - 0 /* search right */); |
|---|
| 1291 | | - } else { |
|---|
| 1292 | | - ASSERT(gtlena >= args->minlen); |
|---|
| 1293 | | - |
|---|
| 1294 | | - /* |
|---|
| 1295 | | - * Right side is good, look for a left side entry. |
|---|
| 1296 | | - */ |
|---|
| 1297 | | - args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen); |
|---|
| 1298 | | - xfs_alloc_fix_len(args); |
|---|
| 1299 | | - gtdiff = xfs_alloc_compute_diff(args->agbno, args->len, |
|---|
| 1300 | | - args->alignment, args->datatype, gtbnoa, |
|---|
| 1301 | | - gtlena, >new); |
|---|
| 1302 | | - |
|---|
| 1303 | | - error = xfs_alloc_find_best_extent(args, |
|---|
| 1304 | | - &bno_cur_gt, &bno_cur_lt, |
|---|
| 1305 | | - gtdiff, <bno, <len, |
|---|
| 1306 | | - <bnoa, <lena, |
|---|
| 1307 | | - 1 /* search left */); |
|---|
| 1308 | | - } |
|---|
| 1309 | | - |
|---|
| 1611 | + error = xfs_alloc_ag_vextent_lastblock(args, &acur, &bno, &len, |
|---|
| 1612 | + &allocated); |
|---|
| 1310 | 1613 | if (error) |
|---|
| 1311 | | - goto error0; |
|---|
| 1614 | + goto out; |
|---|
| 1615 | + if (allocated) |
|---|
| 1616 | + goto alloc_finish; |
|---|
| 1312 | 1617 | } |
|---|
| 1618 | + |
|---|
| 1619 | + /* |
|---|
| 1620 | + * Second algorithm. Combined cntbt and bnobt search to find ideal |
|---|
| 1621 | + * locality. |
|---|
| 1622 | + */ |
|---|
| 1623 | + error = xfs_alloc_ag_vextent_locality(args, &acur, &i); |
|---|
| 1624 | + if (error) |
|---|
| 1625 | + goto out; |
|---|
| 1313 | 1626 | |
|---|
| 1314 | 1627 | /* |
|---|
| 1315 | 1628 | * If we couldn't get anything, give up. |
|---|
| 1316 | 1629 | */ |
|---|
| 1317 | | - if (bno_cur_lt == NULL && bno_cur_gt == NULL) { |
|---|
| 1318 | | - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
|---|
| 1319 | | - |
|---|
| 1320 | | - if (busy) { |
|---|
| 1630 | + if (!acur.len) { |
|---|
| 1631 | + if (acur.busy) { |
|---|
| 1321 | 1632 | trace_xfs_alloc_near_busy(args); |
|---|
| 1322 | | - xfs_extent_busy_flush(args->mp, args->pag, busy_gen); |
|---|
| 1633 | + xfs_extent_busy_flush(args->mp, args->pag, |
|---|
| 1634 | + acur.busy_gen); |
|---|
| 1323 | 1635 | goto restart; |
|---|
| 1324 | 1636 | } |
|---|
| 1325 | 1637 | trace_xfs_alloc_size_neither(args); |
|---|
| 1326 | 1638 | args->agbno = NULLAGBLOCK; |
|---|
| 1327 | | - return 0; |
|---|
| 1639 | + goto out; |
|---|
| 1328 | 1640 | } |
|---|
| 1329 | 1641 | |
|---|
| 1330 | | - /* |
|---|
| 1331 | | - * At this point we have selected a freespace entry, either to the |
|---|
| 1332 | | - * left or to the right. If it's on the right, copy all the |
|---|
| 1333 | | - * useful variables to the "left" set so we only have one |
|---|
| 1334 | | - * copy of this code. |
|---|
| 1335 | | - */ |
|---|
| 1336 | | - if (bno_cur_gt) { |
|---|
| 1337 | | - bno_cur_lt = bno_cur_gt; |
|---|
| 1338 | | - bno_cur_gt = NULL; |
|---|
| 1339 | | - ltbno = gtbno; |
|---|
| 1340 | | - ltbnoa = gtbnoa; |
|---|
| 1341 | | - ltlen = gtlen; |
|---|
| 1342 | | - ltlena = gtlena; |
|---|
| 1343 | | - j = 1; |
|---|
| 1344 | | - } else |
|---|
| 1345 | | - j = 0; |
|---|
| 1642 | +alloc_finish: |
|---|
| 1643 | + /* fix up btrees on a successful allocation */ |
|---|
| 1644 | + error = xfs_alloc_cur_finish(args, &acur); |
|---|
| 1346 | 1645 | |
|---|
| 1347 | | - /* |
|---|
| 1348 | | - * Fix up the length and compute the useful address. |
|---|
| 1349 | | - */ |
|---|
| 1350 | | - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); |
|---|
| 1351 | | - xfs_alloc_fix_len(args); |
|---|
| 1352 | | - rlen = args->len; |
|---|
| 1353 | | - (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, |
|---|
| 1354 | | - args->datatype, ltbnoa, ltlena, <new); |
|---|
| 1355 | | - ASSERT(ltnew >= ltbno); |
|---|
| 1356 | | - ASSERT(ltnew + rlen <= ltbnoa + ltlena); |
|---|
| 1357 | | - ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); |
|---|
| 1358 | | - ASSERT(ltnew >= args->min_agbno && ltnew <= args->max_agbno); |
|---|
| 1359 | | - args->agbno = ltnew; |
|---|
| 1360 | | - |
|---|
| 1361 | | - if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, |
|---|
| 1362 | | - ltnew, rlen, XFSA_FIXUP_BNO_OK))) |
|---|
| 1363 | | - goto error0; |
|---|
| 1364 | | - |
|---|
| 1365 | | - if (j) |
|---|
| 1366 | | - trace_xfs_alloc_near_greater(args); |
|---|
| 1367 | | - else |
|---|
| 1368 | | - trace_xfs_alloc_near_lesser(args); |
|---|
| 1369 | | - |
|---|
| 1370 | | - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
|---|
| 1371 | | - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); |
|---|
| 1372 | | - return 0; |
|---|
| 1373 | | - |
|---|
| 1374 | | - error0: |
|---|
| 1375 | | - trace_xfs_alloc_near_error(args); |
|---|
| 1376 | | - if (cnt_cur != NULL) |
|---|
| 1377 | | - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); |
|---|
| 1378 | | - if (bno_cur_lt != NULL) |
|---|
| 1379 | | - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_ERROR); |
|---|
| 1380 | | - if (bno_cur_gt != NULL) |
|---|
| 1381 | | - xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_ERROR); |
|---|
| 1646 | +out: |
|---|
| 1647 | + xfs_alloc_cur_close(&acur, error); |
|---|
| 1382 | 1648 | return error; |
|---|
| 1383 | 1649 | } |
|---|
| 1384 | 1650 | |
|---|
| .. | .. |
|---|
| 1392 | 1658 | xfs_alloc_ag_vextent_size( |
|---|
| 1393 | 1659 | xfs_alloc_arg_t *args) /* allocation argument structure */ |
|---|
| 1394 | 1660 | { |
|---|
| 1661 | + struct xfs_agf *agf = args->agbp->b_addr; |
|---|
| 1395 | 1662 | xfs_btree_cur_t *bno_cur; /* cursor for bno btree */ |
|---|
| 1396 | 1663 | xfs_btree_cur_t *cnt_cur; /* cursor for cnt btree */ |
|---|
| 1397 | 1664 | int error; /* error result */ |
|---|
| .. | .. |
|---|
| 1447 | 1714 | error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i); |
|---|
| 1448 | 1715 | if (error) |
|---|
| 1449 | 1716 | goto error0; |
|---|
| 1450 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1717 | + if (XFS_IS_CORRUPT(args->mp, i != 1)) { |
|---|
| 1718 | + error = -EFSCORRUPTED; |
|---|
| 1719 | + goto error0; |
|---|
| 1720 | + } |
|---|
| 1451 | 1721 | |
|---|
| 1452 | 1722 | busy = xfs_alloc_compute_aligned(args, fbno, flen, |
|---|
| 1453 | 1723 | &rbno, &rlen, &busy_gen); |
|---|
| .. | .. |
|---|
| 1481 | 1751 | * This can't happen in the second case above. |
|---|
| 1482 | 1752 | */ |
|---|
| 1483 | 1753 | rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); |
|---|
| 1484 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 || |
|---|
| 1485 | | - (rlen <= flen && rbno + rlen <= fbno + flen), error0); |
|---|
| 1754 | + if (XFS_IS_CORRUPT(args->mp, |
|---|
| 1755 | + rlen != 0 && |
|---|
| 1756 | + (rlen > flen || |
|---|
| 1757 | + rbno + rlen > fbno + flen))) { |
|---|
| 1758 | + error = -EFSCORRUPTED; |
|---|
| 1759 | + goto error0; |
|---|
| 1760 | + } |
|---|
| 1486 | 1761 | if (rlen < args->maxlen) { |
|---|
| 1487 | 1762 | xfs_agblock_t bestfbno; |
|---|
| 1488 | 1763 | xfs_extlen_t bestflen; |
|---|
| .. | .. |
|---|
| 1501 | 1776 | if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, |
|---|
| 1502 | 1777 | &i))) |
|---|
| 1503 | 1778 | goto error0; |
|---|
| 1504 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1779 | + if (XFS_IS_CORRUPT(args->mp, i != 1)) { |
|---|
| 1780 | + error = -EFSCORRUPTED; |
|---|
| 1781 | + goto error0; |
|---|
| 1782 | + } |
|---|
| 1505 | 1783 | if (flen < bestrlen) |
|---|
| 1506 | 1784 | break; |
|---|
| 1507 | 1785 | busy = xfs_alloc_compute_aligned(args, fbno, flen, |
|---|
| 1508 | 1786 | &rbno, &rlen, &busy_gen); |
|---|
| 1509 | 1787 | rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); |
|---|
| 1510 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 || |
|---|
| 1511 | | - (rlen <= flen && rbno + rlen <= fbno + flen), |
|---|
| 1512 | | - error0); |
|---|
| 1788 | + if (XFS_IS_CORRUPT(args->mp, |
|---|
| 1789 | + rlen != 0 && |
|---|
| 1790 | + (rlen > flen || |
|---|
| 1791 | + rbno + rlen > fbno + flen))) { |
|---|
| 1792 | + error = -EFSCORRUPTED; |
|---|
| 1793 | + goto error0; |
|---|
| 1794 | + } |
|---|
| 1513 | 1795 | if (rlen > bestrlen) { |
|---|
| 1514 | 1796 | bestrlen = rlen; |
|---|
| 1515 | 1797 | bestrbno = rbno; |
|---|
| .. | .. |
|---|
| 1522 | 1804 | if ((error = xfs_alloc_lookup_eq(cnt_cur, bestfbno, bestflen, |
|---|
| 1523 | 1805 | &i))) |
|---|
| 1524 | 1806 | goto error0; |
|---|
| 1525 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1807 | + if (XFS_IS_CORRUPT(args->mp, i != 1)) { |
|---|
| 1808 | + error = -EFSCORRUPTED; |
|---|
| 1809 | + goto error0; |
|---|
| 1810 | + } |
|---|
| 1526 | 1811 | rlen = bestrlen; |
|---|
| 1527 | 1812 | rbno = bestrbno; |
|---|
| 1528 | 1813 | flen = bestflen; |
|---|
| .. | .. |
|---|
| 1545 | 1830 | xfs_alloc_fix_len(args); |
|---|
| 1546 | 1831 | |
|---|
| 1547 | 1832 | rlen = args->len; |
|---|
| 1548 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0); |
|---|
| 1833 | + if (XFS_IS_CORRUPT(args->mp, rlen > flen)) { |
|---|
| 1834 | + error = -EFSCORRUPTED; |
|---|
| 1835 | + goto error0; |
|---|
| 1836 | + } |
|---|
| 1549 | 1837 | /* |
|---|
| 1550 | 1838 | * Allocate and initialize a cursor for the by-block tree. |
|---|
| 1551 | 1839 | */ |
|---|
| .. | .. |
|---|
| 1559 | 1847 | cnt_cur = bno_cur = NULL; |
|---|
| 1560 | 1848 | args->len = rlen; |
|---|
| 1561 | 1849 | args->agbno = rbno; |
|---|
| 1562 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, |
|---|
| 1563 | | - args->agbno + args->len <= |
|---|
| 1564 | | - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), |
|---|
| 1565 | | - error0); |
|---|
| 1850 | + if (XFS_IS_CORRUPT(args->mp, |
|---|
| 1851 | + args->agbno + args->len > |
|---|
| 1852 | + be32_to_cpu(agf->agf_length))) { |
|---|
| 1853 | + error = -EFSCORRUPTED; |
|---|
| 1854 | + goto error0; |
|---|
| 1855 | + } |
|---|
| 1566 | 1856 | trace_xfs_alloc_size_done(args); |
|---|
| 1567 | 1857 | return 0; |
|---|
| 1568 | 1858 | |
|---|
| .. | .. |
|---|
| 1582 | 1872 | } |
|---|
| 1583 | 1873 | |
|---|
| 1584 | 1874 | /* |
|---|
| 1585 | | - * Deal with the case where only small freespaces remain. |
|---|
| 1586 | | - * Either return the contents of the last freespace record, |
|---|
| 1587 | | - * or allocate space from the freelist if there is nothing in the tree. |
|---|
| 1588 | | - */ |
|---|
| 1589 | | -STATIC int /* error */ |
|---|
| 1590 | | -xfs_alloc_ag_vextent_small( |
|---|
| 1591 | | - xfs_alloc_arg_t *args, /* allocation argument structure */ |
|---|
| 1592 | | - xfs_btree_cur_t *ccur, /* by-size cursor */ |
|---|
| 1593 | | - xfs_agblock_t *fbnop, /* result block number */ |
|---|
| 1594 | | - xfs_extlen_t *flenp, /* result length */ |
|---|
| 1595 | | - int *stat) /* status: 0-freelist, 1-normal/none */ |
|---|
| 1596 | | -{ |
|---|
| 1597 | | - struct xfs_owner_info oinfo; |
|---|
| 1598 | | - int error; |
|---|
| 1599 | | - xfs_agblock_t fbno; |
|---|
| 1600 | | - xfs_extlen_t flen; |
|---|
| 1601 | | - int i; |
|---|
| 1602 | | - |
|---|
| 1603 | | - if ((error = xfs_btree_decrement(ccur, 0, &i))) |
|---|
| 1604 | | - goto error0; |
|---|
| 1605 | | - if (i) { |
|---|
| 1606 | | - if ((error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i))) |
|---|
| 1607 | | - goto error0; |
|---|
| 1608 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
|---|
| 1609 | | - } |
|---|
| 1610 | | - /* |
|---|
| 1611 | | - * Nothing in the btree, try the freelist. Make sure |
|---|
| 1612 | | - * to respect minleft even when pulling from the |
|---|
| 1613 | | - * freelist. |
|---|
| 1614 | | - */ |
|---|
| 1615 | | - else if (args->minlen == 1 && args->alignment == 1 && |
|---|
| 1616 | | - args->resv != XFS_AG_RESV_AGFL && |
|---|
| 1617 | | - (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) |
|---|
| 1618 | | - > args->minleft)) { |
|---|
| 1619 | | - error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); |
|---|
| 1620 | | - if (error) |
|---|
| 1621 | | - goto error0; |
|---|
| 1622 | | - if (fbno != NULLAGBLOCK) { |
|---|
| 1623 | | - xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, |
|---|
| 1624 | | - xfs_alloc_allow_busy_reuse(args->datatype)); |
|---|
| 1625 | | - |
|---|
| 1626 | | - if (xfs_alloc_is_userdata(args->datatype)) { |
|---|
| 1627 | | - xfs_buf_t *bp; |
|---|
| 1628 | | - |
|---|
| 1629 | | - bp = xfs_btree_get_bufs(args->mp, args->tp, |
|---|
| 1630 | | - args->agno, fbno, 0); |
|---|
| 1631 | | - if (!bp) { |
|---|
| 1632 | | - error = -EFSCORRUPTED; |
|---|
| 1633 | | - goto error0; |
|---|
| 1634 | | - } |
|---|
| 1635 | | - xfs_trans_binval(args->tp, bp); |
|---|
| 1636 | | - } |
|---|
| 1637 | | - args->len = 1; |
|---|
| 1638 | | - args->agbno = fbno; |
|---|
| 1639 | | - XFS_WANT_CORRUPTED_GOTO(args->mp, |
|---|
| 1640 | | - args->agbno + args->len <= |
|---|
| 1641 | | - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), |
|---|
| 1642 | | - error0); |
|---|
| 1643 | | - args->wasfromfl = 1; |
|---|
| 1644 | | - trace_xfs_alloc_small_freelist(args); |
|---|
| 1645 | | - |
|---|
| 1646 | | - /* |
|---|
| 1647 | | - * If we're feeding an AGFL block to something that |
|---|
| 1648 | | - * doesn't live in the free space, we need to clear |
|---|
| 1649 | | - * out the OWN_AG rmap. |
|---|
| 1650 | | - */ |
|---|
| 1651 | | - xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG); |
|---|
| 1652 | | - error = xfs_rmap_free(args->tp, args->agbp, args->agno, |
|---|
| 1653 | | - fbno, 1, &oinfo); |
|---|
| 1654 | | - if (error) |
|---|
| 1655 | | - goto error0; |
|---|
| 1656 | | - |
|---|
| 1657 | | - *stat = 0; |
|---|
| 1658 | | - return 0; |
|---|
| 1659 | | - } |
|---|
| 1660 | | - /* |
|---|
| 1661 | | - * Nothing in the freelist. |
|---|
| 1662 | | - */ |
|---|
| 1663 | | - else |
|---|
| 1664 | | - flen = 0; |
|---|
| 1665 | | - } |
|---|
| 1666 | | - /* |
|---|
| 1667 | | - * Can't allocate from the freelist for some reason. |
|---|
| 1668 | | - */ |
|---|
| 1669 | | - else { |
|---|
| 1670 | | - fbno = NULLAGBLOCK; |
|---|
| 1671 | | - flen = 0; |
|---|
| 1672 | | - } |
|---|
| 1673 | | - /* |
|---|
| 1674 | | - * Can't do the allocation, give up. |
|---|
| 1675 | | - */ |
|---|
| 1676 | | - if (flen < args->minlen) { |
|---|
| 1677 | | - args->agbno = NULLAGBLOCK; |
|---|
| 1678 | | - trace_xfs_alloc_small_notenough(args); |
|---|
| 1679 | | - flen = 0; |
|---|
| 1680 | | - } |
|---|
| 1681 | | - *fbnop = fbno; |
|---|
| 1682 | | - *flenp = flen; |
|---|
| 1683 | | - *stat = 1; |
|---|
| 1684 | | - trace_xfs_alloc_small_done(args); |
|---|
| 1685 | | - return 0; |
|---|
| 1686 | | - |
|---|
| 1687 | | -error0: |
|---|
| 1688 | | - trace_xfs_alloc_small_error(args); |
|---|
| 1689 | | - return error; |
|---|
| 1690 | | -} |
|---|
| 1691 | | - |
|---|
| 1692 | | -/* |
|---|
| 1693 | 1875 | * Free the extent starting at agno/bno for length. |
|---|
| 1694 | 1876 | */ |
|---|
| 1695 | 1877 | STATIC int |
|---|
| 1696 | 1878 | xfs_free_ag_extent( |
|---|
| 1697 | | - xfs_trans_t *tp, |
|---|
| 1698 | | - xfs_buf_t *agbp, |
|---|
| 1699 | | - xfs_agnumber_t agno, |
|---|
| 1700 | | - xfs_agblock_t bno, |
|---|
| 1701 | | - xfs_extlen_t len, |
|---|
| 1702 | | - struct xfs_owner_info *oinfo, |
|---|
| 1703 | | - enum xfs_ag_resv_type type) |
|---|
| 1879 | + struct xfs_trans *tp, |
|---|
| 1880 | + struct xfs_buf *agbp, |
|---|
| 1881 | + xfs_agnumber_t agno, |
|---|
| 1882 | + xfs_agblock_t bno, |
|---|
| 1883 | + xfs_extlen_t len, |
|---|
| 1884 | + const struct xfs_owner_info *oinfo, |
|---|
| 1885 | + enum xfs_ag_resv_type type) |
|---|
| 1704 | 1886 | { |
|---|
| 1705 | | - xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */ |
|---|
| 1706 | | - xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */ |
|---|
| 1707 | | - int error; /* error return value */ |
|---|
| 1708 | | - xfs_agblock_t gtbno; /* start of right neighbor block */ |
|---|
| 1709 | | - xfs_extlen_t gtlen; /* length of right neighbor block */ |
|---|
| 1710 | | - int haveleft; /* have a left neighbor block */ |
|---|
| 1711 | | - int haveright; /* have a right neighbor block */ |
|---|
| 1712 | | - int i; /* temp, result code */ |
|---|
| 1713 | | - xfs_agblock_t ltbno; /* start of left neighbor block */ |
|---|
| 1714 | | - xfs_extlen_t ltlen; /* length of left neighbor block */ |
|---|
| 1715 | | - xfs_mount_t *mp; /* mount point struct for filesystem */ |
|---|
| 1716 | | - xfs_agblock_t nbno; /* new starting block of freespace */ |
|---|
| 1717 | | - xfs_extlen_t nlen; /* new length of freespace */ |
|---|
| 1718 | | - xfs_perag_t *pag; /* per allocation group data */ |
|---|
| 1887 | + struct xfs_mount *mp; |
|---|
| 1888 | + struct xfs_btree_cur *bno_cur; |
|---|
| 1889 | + struct xfs_btree_cur *cnt_cur; |
|---|
| 1890 | + xfs_agblock_t gtbno; /* start of right neighbor */ |
|---|
| 1891 | + xfs_extlen_t gtlen; /* length of right neighbor */ |
|---|
| 1892 | + xfs_agblock_t ltbno; /* start of left neighbor */ |
|---|
| 1893 | + xfs_extlen_t ltlen; /* length of left neighbor */ |
|---|
| 1894 | + xfs_agblock_t nbno; /* new starting block of freesp */ |
|---|
| 1895 | + xfs_extlen_t nlen; /* new length of freespace */ |
|---|
| 1896 | + int haveleft; /* have a left neighbor */ |
|---|
| 1897 | + int haveright; /* have a right neighbor */ |
|---|
| 1898 | + int i; |
|---|
| 1899 | + int error; |
|---|
| 1719 | 1900 | |
|---|
| 1720 | 1901 | bno_cur = cnt_cur = NULL; |
|---|
| 1721 | 1902 | mp = tp->t_mountp; |
|---|
| .. | .. |
|---|
| 1742 | 1923 | */ |
|---|
| 1743 | 1924 | if ((error = xfs_alloc_get_rec(bno_cur, <bno, <len, &i))) |
|---|
| 1744 | 1925 | goto error0; |
|---|
| 1745 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 1926 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 1927 | + error = -EFSCORRUPTED; |
|---|
| 1928 | + goto error0; |
|---|
| 1929 | + } |
|---|
| 1746 | 1930 | /* |
|---|
| 1747 | 1931 | * It's not contiguous, though. |
|---|
| 1748 | 1932 | */ |
|---|
| .. | .. |
|---|
| 1754 | 1938 | * space was invalid, it's (partly) already free. |
|---|
| 1755 | 1939 | * Very bad. |
|---|
| 1756 | 1940 | */ |
|---|
| 1757 | | - XFS_WANT_CORRUPTED_GOTO(mp, |
|---|
| 1758 | | - ltbno + ltlen <= bno, error0); |
|---|
| 1941 | + if (XFS_IS_CORRUPT(mp, ltbno + ltlen > bno)) { |
|---|
| 1942 | + error = -EFSCORRUPTED; |
|---|
| 1943 | + goto error0; |
|---|
| 1944 | + } |
|---|
| 1759 | 1945 | } |
|---|
| 1760 | 1946 | } |
|---|
| 1761 | 1947 | /* |
|---|
| .. | .. |
|---|
| 1770 | 1956 | */ |
|---|
| 1771 | 1957 | if ((error = xfs_alloc_get_rec(bno_cur, >bno, >len, &i))) |
|---|
| 1772 | 1958 | goto error0; |
|---|
| 1773 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 1959 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 1960 | + error = -EFSCORRUPTED; |
|---|
| 1961 | + goto error0; |
|---|
| 1962 | + } |
|---|
| 1774 | 1963 | /* |
|---|
| 1775 | 1964 | * It's not contiguous, though. |
|---|
| 1776 | 1965 | */ |
|---|
| .. | .. |
|---|
| 1782 | 1971 | * space was invalid, it's (partly) already free. |
|---|
| 1783 | 1972 | * Very bad. |
|---|
| 1784 | 1973 | */ |
|---|
| 1785 | | - XFS_WANT_CORRUPTED_GOTO(mp, gtbno >= bno + len, error0); |
|---|
| 1974 | + if (XFS_IS_CORRUPT(mp, bno + len > gtbno)) { |
|---|
| 1975 | + error = -EFSCORRUPTED; |
|---|
| 1976 | + goto error0; |
|---|
| 1977 | + } |
|---|
| 1786 | 1978 | } |
|---|
| 1787 | 1979 | } |
|---|
| 1788 | 1980 | /* |
|---|
| .. | .. |
|---|
| 1799 | 1991 | */ |
|---|
| 1800 | 1992 | if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i))) |
|---|
| 1801 | 1993 | goto error0; |
|---|
| 1802 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 1994 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 1995 | + error = -EFSCORRUPTED; |
|---|
| 1996 | + goto error0; |
|---|
| 1997 | + } |
|---|
| 1803 | 1998 | if ((error = xfs_btree_delete(cnt_cur, &i))) |
|---|
| 1804 | 1999 | goto error0; |
|---|
| 1805 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2000 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2001 | + error = -EFSCORRUPTED; |
|---|
| 2002 | + goto error0; |
|---|
| 2003 | + } |
|---|
| 1806 | 2004 | /* |
|---|
| 1807 | 2005 | * Delete the old by-size entry on the right. |
|---|
| 1808 | 2006 | */ |
|---|
| 1809 | 2007 | if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i))) |
|---|
| 1810 | 2008 | goto error0; |
|---|
| 1811 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2009 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2010 | + error = -EFSCORRUPTED; |
|---|
| 2011 | + goto error0; |
|---|
| 2012 | + } |
|---|
| 1812 | 2013 | if ((error = xfs_btree_delete(cnt_cur, &i))) |
|---|
| 1813 | 2014 | goto error0; |
|---|
| 1814 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2015 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2016 | + error = -EFSCORRUPTED; |
|---|
| 2017 | + goto error0; |
|---|
| 2018 | + } |
|---|
| 1815 | 2019 | /* |
|---|
| 1816 | 2020 | * Delete the old by-block entry for the right block. |
|---|
| 1817 | 2021 | */ |
|---|
| 1818 | 2022 | if ((error = xfs_btree_delete(bno_cur, &i))) |
|---|
| 1819 | 2023 | goto error0; |
|---|
| 1820 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2024 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2025 | + error = -EFSCORRUPTED; |
|---|
| 2026 | + goto error0; |
|---|
| 2027 | + } |
|---|
| 1821 | 2028 | /* |
|---|
| 1822 | 2029 | * Move the by-block cursor back to the left neighbor. |
|---|
| 1823 | 2030 | */ |
|---|
| 1824 | 2031 | if ((error = xfs_btree_decrement(bno_cur, 0, &i))) |
|---|
| 1825 | 2032 | goto error0; |
|---|
| 1826 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2033 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2034 | + error = -EFSCORRUPTED; |
|---|
| 2035 | + goto error0; |
|---|
| 2036 | + } |
|---|
| 1827 | 2037 | #ifdef DEBUG |
|---|
| 1828 | 2038 | /* |
|---|
| 1829 | 2039 | * Check that this is the right record: delete didn't |
|---|
| .. | .. |
|---|
| 1836 | 2046 | if ((error = xfs_alloc_get_rec(bno_cur, &xxbno, &xxlen, |
|---|
| 1837 | 2047 | &i))) |
|---|
| 1838 | 2048 | goto error0; |
|---|
| 1839 | | - XFS_WANT_CORRUPTED_GOTO(mp, |
|---|
| 1840 | | - i == 1 && xxbno == ltbno && xxlen == ltlen, |
|---|
| 1841 | | - error0); |
|---|
| 2049 | + if (XFS_IS_CORRUPT(mp, |
|---|
| 2050 | + i != 1 || |
|---|
| 2051 | + xxbno != ltbno || |
|---|
| 2052 | + xxlen != ltlen)) { |
|---|
| 2053 | + error = -EFSCORRUPTED; |
|---|
| 2054 | + goto error0; |
|---|
| 2055 | + } |
|---|
| 1842 | 2056 | } |
|---|
| 1843 | 2057 | #endif |
|---|
| 1844 | 2058 | /* |
|---|
| .. | .. |
|---|
| 1859 | 2073 | */ |
|---|
| 1860 | 2074 | if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i))) |
|---|
| 1861 | 2075 | goto error0; |
|---|
| 1862 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2076 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2077 | + error = -EFSCORRUPTED; |
|---|
| 2078 | + goto error0; |
|---|
| 2079 | + } |
|---|
| 1863 | 2080 | if ((error = xfs_btree_delete(cnt_cur, &i))) |
|---|
| 1864 | 2081 | goto error0; |
|---|
| 1865 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2082 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2083 | + error = -EFSCORRUPTED; |
|---|
| 2084 | + goto error0; |
|---|
| 2085 | + } |
|---|
| 1866 | 2086 | /* |
|---|
| 1867 | 2087 | * Back up the by-block cursor to the left neighbor, and |
|---|
| 1868 | 2088 | * update its length. |
|---|
| 1869 | 2089 | */ |
|---|
| 1870 | 2090 | if ((error = xfs_btree_decrement(bno_cur, 0, &i))) |
|---|
| 1871 | 2091 | goto error0; |
|---|
| 1872 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2092 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2093 | + error = -EFSCORRUPTED; |
|---|
| 2094 | + goto error0; |
|---|
| 2095 | + } |
|---|
| 1873 | 2096 | nbno = ltbno; |
|---|
| 1874 | 2097 | nlen = len + ltlen; |
|---|
| 1875 | 2098 | if ((error = xfs_alloc_update(bno_cur, nbno, nlen))) |
|---|
| .. | .. |
|---|
| 1885 | 2108 | */ |
|---|
| 1886 | 2109 | if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i))) |
|---|
| 1887 | 2110 | goto error0; |
|---|
| 1888 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2111 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2112 | + error = -EFSCORRUPTED; |
|---|
| 2113 | + goto error0; |
|---|
| 2114 | + } |
|---|
| 1889 | 2115 | if ((error = xfs_btree_delete(cnt_cur, &i))) |
|---|
| 1890 | 2116 | goto error0; |
|---|
| 1891 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2117 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2118 | + error = -EFSCORRUPTED; |
|---|
| 2119 | + goto error0; |
|---|
| 2120 | + } |
|---|
| 1892 | 2121 | /* |
|---|
| 1893 | 2122 | * Update the starting block and length of the right |
|---|
| 1894 | 2123 | * neighbor in the by-block tree. |
|---|
| .. | .. |
|---|
| 1907 | 2136 | nlen = len; |
|---|
| 1908 | 2137 | if ((error = xfs_btree_insert(bno_cur, &i))) |
|---|
| 1909 | 2138 | goto error0; |
|---|
| 1910 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2139 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2140 | + error = -EFSCORRUPTED; |
|---|
| 2141 | + goto error0; |
|---|
| 2142 | + } |
|---|
| 1911 | 2143 | } |
|---|
| 1912 | 2144 | xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); |
|---|
| 1913 | 2145 | bno_cur = NULL; |
|---|
| .. | .. |
|---|
| 1916 | 2148 | */ |
|---|
| 1917 | 2149 | if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i))) |
|---|
| 1918 | 2150 | goto error0; |
|---|
| 1919 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, error0); |
|---|
| 2151 | + if (XFS_IS_CORRUPT(mp, i != 0)) { |
|---|
| 2152 | + error = -EFSCORRUPTED; |
|---|
| 2153 | + goto error0; |
|---|
| 2154 | + } |
|---|
| 1920 | 2155 | if ((error = xfs_btree_insert(cnt_cur, &i))) |
|---|
| 1921 | 2156 | goto error0; |
|---|
| 1922 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); |
|---|
| 2157 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 2158 | + error = -EFSCORRUPTED; |
|---|
| 2159 | + goto error0; |
|---|
| 2160 | + } |
|---|
| 1923 | 2161 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
|---|
| 1924 | 2162 | cnt_cur = NULL; |
|---|
| 1925 | 2163 | |
|---|
| 1926 | 2164 | /* |
|---|
| 1927 | 2165 | * Update the freespace totals in the ag and superblock. |
|---|
| 1928 | 2166 | */ |
|---|
| 1929 | | - pag = xfs_perag_get(mp, agno); |
|---|
| 1930 | | - error = xfs_alloc_update_counters(tp, pag, agbp, len); |
|---|
| 1931 | | - xfs_ag_resv_free_extent(pag, type, tp, len); |
|---|
| 1932 | | - xfs_perag_put(pag); |
|---|
| 2167 | + error = xfs_alloc_update_counters(tp, agbp, len); |
|---|
| 2168 | + xfs_ag_resv_free_extent(agbp->b_pag, type, tp, len); |
|---|
| 1933 | 2169 | if (error) |
|---|
| 1934 | 2170 | goto error0; |
|---|
| 1935 | 2171 | |
|---|
| .. | .. |
|---|
| 1999 | 2235 | * reservations and AGFL rules in place, we can return this extent. |
|---|
| 2000 | 2236 | */ |
|---|
| 2001 | 2237 | if (pag->pagf_longest > delta) |
|---|
| 2002 | | - return pag->pagf_longest - delta; |
|---|
| 2238 | + return min_t(xfs_extlen_t, pag->pag_mount->m_ag_max_usable, |
|---|
| 2239 | + pag->pagf_longest - delta); |
|---|
| 2003 | 2240 | |
|---|
| 2004 | 2241 | /* Otherwise, let the caller try for 1 block if there's space. */ |
|---|
| 2005 | 2242 | return pag->pagf_flcount > 0 || pag->pagf_longest > 0; |
|---|
| 2006 | 2243 | } |
|---|
| 2007 | 2244 | |
|---|
| 2245 | +/* |
|---|
| 2246 | + * Compute the minimum length of the AGFL in the given AG. If @pag is NULL, |
|---|
| 2247 | + * return the largest possible minimum length. |
|---|
| 2248 | + */ |
|---|
| 2008 | 2249 | unsigned int |
|---|
| 2009 | 2250 | xfs_alloc_min_freelist( |
|---|
| 2010 | 2251 | struct xfs_mount *mp, |
|---|
| 2011 | 2252 | struct xfs_perag *pag) |
|---|
| 2012 | 2253 | { |
|---|
| 2254 | + /* AG btrees have at least 1 level. */ |
|---|
| 2255 | + static const uint8_t fake_levels[XFS_BTNUM_AGF] = {1, 1, 1}; |
|---|
| 2256 | + const uint8_t *levels = pag ? pag->pagf_levels : fake_levels; |
|---|
| 2013 | 2257 | unsigned int min_free; |
|---|
| 2014 | 2258 | |
|---|
| 2259 | + ASSERT(mp->m_ag_maxlevels > 0); |
|---|
| 2260 | + |
|---|
| 2015 | 2261 | /* space needed by-bno freespace btree */ |
|---|
| 2016 | | - min_free = min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_BNOi] + 1, |
|---|
| 2262 | + min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1, |
|---|
| 2017 | 2263 | mp->m_ag_maxlevels); |
|---|
| 2018 | 2264 | /* space needed by-size freespace btree */ |
|---|
| 2019 | | - min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_CNTi] + 1, |
|---|
| 2265 | + min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1, |
|---|
| 2020 | 2266 | mp->m_ag_maxlevels); |
|---|
| 2021 | 2267 | /* space needed reverse mapping used space btree */ |
|---|
| 2022 | 2268 | if (xfs_sb_version_hasrmapbt(&mp->m_sb)) |
|---|
| 2023 | | - min_free += min_t(unsigned int, |
|---|
| 2024 | | - pag->pagf_levels[XFS_BTNUM_RMAPi] + 1, |
|---|
| 2025 | | - mp->m_rmap_maxlevels); |
|---|
| 2269 | + min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1, |
|---|
| 2270 | + mp->m_rmap_maxlevels); |
|---|
| 2026 | 2271 | |
|---|
| 2027 | 2272 | return min_free; |
|---|
| 2028 | 2273 | } |
|---|
| .. | .. |
|---|
| 2043 | 2288 | xfs_extlen_t alloc_len, longest; |
|---|
| 2044 | 2289 | xfs_extlen_t reservation; /* blocks that are still reserved */ |
|---|
| 2045 | 2290 | int available; |
|---|
| 2291 | + xfs_extlen_t agflcount; |
|---|
| 2046 | 2292 | |
|---|
| 2047 | 2293 | if (flags & XFS_ALLOC_FLAG_FREEING) |
|---|
| 2048 | 2294 | return true; |
|---|
| .. | .. |
|---|
| 2055 | 2301 | if (longest < alloc_len) |
|---|
| 2056 | 2302 | return false; |
|---|
| 2057 | 2303 | |
|---|
| 2058 | | - /* do we have enough free space remaining for the allocation? */ |
|---|
| 2059 | | - available = (int)(pag->pagf_freeblks + pag->pagf_flcount - |
|---|
| 2304 | + /* |
|---|
| 2305 | + * Do we have enough free space remaining for the allocation? Don't |
|---|
| 2306 | + * account extra agfl blocks because we are about to defer free them, |
|---|
| 2307 | + * making them unavailable until the current transaction commits. |
|---|
| 2308 | + */ |
|---|
| 2309 | + agflcount = min_t(xfs_extlen_t, pag->pagf_flcount, min_free); |
|---|
| 2310 | + available = (int)(pag->pagf_freeblks + agflcount - |
|---|
| 2060 | 2311 | reservation - min_free - args->minleft); |
|---|
| 2061 | 2312 | if (available < (int)max(args->total, alloc_len)) |
|---|
| 2062 | 2313 | return false; |
|---|
| .. | .. |
|---|
| 2090 | 2341 | if (error) |
|---|
| 2091 | 2342 | return error; |
|---|
| 2092 | 2343 | |
|---|
| 2093 | | - bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno, 0); |
|---|
| 2094 | | - if (!bp) |
|---|
| 2095 | | - return -EFSCORRUPTED; |
|---|
| 2344 | + error = xfs_trans_get_buf(tp, tp->t_mountp->m_ddev_targp, |
|---|
| 2345 | + XFS_AGB_TO_DADDR(tp->t_mountp, agno, agbno), |
|---|
| 2346 | + tp->t_mountp->m_bsize, 0, &bp); |
|---|
| 2347 | + if (error) |
|---|
| 2348 | + return error; |
|---|
| 2096 | 2349 | xfs_trans_binval(tp, bp); |
|---|
| 2097 | 2350 | |
|---|
| 2098 | 2351 | return 0; |
|---|
| .. | .. |
|---|
| 2165 | 2418 | struct xfs_perag *pag) |
|---|
| 2166 | 2419 | { |
|---|
| 2167 | 2420 | struct xfs_mount *mp = tp->t_mountp; |
|---|
| 2168 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 2421 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 2169 | 2422 | |
|---|
| 2170 | 2423 | ASSERT(pag->pagf_agflreset); |
|---|
| 2171 | 2424 | trace_xfs_agfl_reset(mp, agf, 0, _RET_IP_); |
|---|
| .. | .. |
|---|
| 2209 | 2462 | ASSERT(xfs_bmap_free_item_zone != NULL); |
|---|
| 2210 | 2463 | ASSERT(oinfo != NULL); |
|---|
| 2211 | 2464 | |
|---|
| 2212 | | - new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); |
|---|
| 2465 | + new = kmem_cache_alloc(xfs_bmap_free_item_zone, |
|---|
| 2466 | + GFP_KERNEL | __GFP_NOFAIL); |
|---|
| 2213 | 2467 | new->xefi_startblock = XFS_AGB_TO_FSB(mp, agno, agbno); |
|---|
| 2214 | 2468 | new->xefi_blockcount = 1; |
|---|
| 2215 | 2469 | new->xefi_oinfo = *oinfo; |
|---|
| .. | .. |
|---|
| 2239 | 2493 | xfs_extlen_t need; /* total blocks needed in freelist */ |
|---|
| 2240 | 2494 | int error = 0; |
|---|
| 2241 | 2495 | |
|---|
| 2496 | + /* deferred ops (AGFL block frees) require permanent transactions */ |
|---|
| 2497 | + ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); |
|---|
| 2498 | + |
|---|
| 2242 | 2499 | if (!pag->pagf_init) { |
|---|
| 2243 | 2500 | error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); |
|---|
| 2244 | | - if (error) |
|---|
| 2501 | + if (error) { |
|---|
| 2502 | + /* Couldn't lock the AGF so skip this AG. */ |
|---|
| 2503 | + if (error == -EAGAIN) |
|---|
| 2504 | + error = 0; |
|---|
| 2245 | 2505 | goto out_no_agbp; |
|---|
| 2246 | | - if (!pag->pagf_init) { |
|---|
| 2247 | | - ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); |
|---|
| 2248 | | - ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); |
|---|
| 2249 | | - goto out_agbp_relse; |
|---|
| 2250 | 2506 | } |
|---|
| 2251 | 2507 | } |
|---|
| 2252 | 2508 | |
|---|
| .. | .. |
|---|
| 2255 | 2511 | * somewhere else if we are not being asked to try harder at this |
|---|
| 2256 | 2512 | * point |
|---|
| 2257 | 2513 | */ |
|---|
| 2258 | | - if (pag->pagf_metadata && xfs_alloc_is_userdata(args->datatype) && |
|---|
| 2514 | + if (pag->pagf_metadata && (args->datatype & XFS_ALLOC_USERDATA) && |
|---|
| 2259 | 2515 | (flags & XFS_ALLOC_FLAG_TRYLOCK)) { |
|---|
| 2260 | 2516 | ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); |
|---|
| 2261 | 2517 | goto out_agbp_relse; |
|---|
| .. | .. |
|---|
| 2272 | 2528 | */ |
|---|
| 2273 | 2529 | if (!agbp) { |
|---|
| 2274 | 2530 | error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); |
|---|
| 2275 | | - if (error) |
|---|
| 2276 | | - goto out_no_agbp; |
|---|
| 2277 | | - if (!agbp) { |
|---|
| 2278 | | - ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); |
|---|
| 2279 | | - ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); |
|---|
| 2531 | + if (error) { |
|---|
| 2532 | + /* Couldn't lock the AGF so skip this AG. */ |
|---|
| 2533 | + if (error == -EAGAIN) |
|---|
| 2534 | + error = 0; |
|---|
| 2280 | 2535 | goto out_no_agbp; |
|---|
| 2281 | 2536 | } |
|---|
| 2282 | 2537 | } |
|---|
| .. | .. |
|---|
| 2315 | 2570 | * repair/rmap.c in xfsprogs for details. |
|---|
| 2316 | 2571 | */ |
|---|
| 2317 | 2572 | memset(&targs, 0, sizeof(targs)); |
|---|
| 2573 | + /* struct copy below */ |
|---|
| 2318 | 2574 | if (flags & XFS_ALLOC_FLAG_NORMAP) |
|---|
| 2319 | | - xfs_rmap_skip_owner_update(&targs.oinfo); |
|---|
| 2575 | + targs.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE; |
|---|
| 2320 | 2576 | else |
|---|
| 2321 | | - xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); |
|---|
| 2577 | + targs.oinfo = XFS_RMAP_OINFO_AG; |
|---|
| 2322 | 2578 | while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) { |
|---|
| 2323 | 2579 | error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); |
|---|
| 2324 | 2580 | if (error) |
|---|
| .. | .. |
|---|
| 2395 | 2651 | xfs_agblock_t *bnop, /* block address retrieved from freelist */ |
|---|
| 2396 | 2652 | int btreeblk) /* destination is a AGF btree */ |
|---|
| 2397 | 2653 | { |
|---|
| 2398 | | - xfs_agf_t *agf; /* a.g. freespace structure */ |
|---|
| 2654 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 2399 | 2655 | xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */ |
|---|
| 2400 | 2656 | xfs_agblock_t bno; /* block number returned */ |
|---|
| 2401 | 2657 | __be32 *agfl_bno; |
|---|
| .. | .. |
|---|
| 2407 | 2663 | /* |
|---|
| 2408 | 2664 | * Freelist is empty, give up. |
|---|
| 2409 | 2665 | */ |
|---|
| 2410 | | - agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 2411 | 2666 | if (!agf->agf_flcount) { |
|---|
| 2412 | 2667 | *bnop = NULLAGBLOCK; |
|---|
| 2413 | 2668 | return 0; |
|---|
| .. | .. |
|---|
| 2424 | 2679 | /* |
|---|
| 2425 | 2680 | * Get the block number and update the data structures. |
|---|
| 2426 | 2681 | */ |
|---|
| 2427 | | - agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); |
|---|
| 2682 | + agfl_bno = xfs_buf_to_agfl_bno(agflbp); |
|---|
| 2428 | 2683 | bno = be32_to_cpu(agfl_bno[be32_to_cpu(agf->agf_flfirst)]); |
|---|
| 2429 | 2684 | be32_add_cpu(&agf->agf_flfirst, 1); |
|---|
| 2430 | 2685 | xfs_trans_brelse(tp, agflbp); |
|---|
| 2431 | 2686 | if (be32_to_cpu(agf->agf_flfirst) == xfs_agfl_size(mp)) |
|---|
| 2432 | 2687 | agf->agf_flfirst = 0; |
|---|
| 2433 | 2688 | |
|---|
| 2434 | | - pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno)); |
|---|
| 2689 | + pag = agbp->b_pag; |
|---|
| 2435 | 2690 | ASSERT(!pag->pagf_agflreset); |
|---|
| 2436 | 2691 | be32_add_cpu(&agf->agf_flcount, -1); |
|---|
| 2437 | 2692 | xfs_trans_agflist_delta(tp, -1); |
|---|
| 2438 | 2693 | pag->pagf_flcount--; |
|---|
| 2439 | | - xfs_perag_put(pag); |
|---|
| 2440 | 2694 | |
|---|
| 2441 | 2695 | logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT; |
|---|
| 2442 | 2696 | if (btreeblk) { |
|---|
| .. | .. |
|---|
| 2485 | 2739 | sizeof(xfs_agf_t) |
|---|
| 2486 | 2740 | }; |
|---|
| 2487 | 2741 | |
|---|
| 2488 | | - trace_xfs_agf(tp->t_mountp, XFS_BUF_TO_AGF(bp), fields, _RET_IP_); |
|---|
| 2742 | + trace_xfs_agf(tp->t_mountp, bp->b_addr, fields, _RET_IP_); |
|---|
| 2489 | 2743 | |
|---|
| 2490 | 2744 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGF_BUF); |
|---|
| 2491 | 2745 | |
|---|
| .. | .. |
|---|
| 2506 | 2760 | xfs_buf_t *bp; |
|---|
| 2507 | 2761 | int error; |
|---|
| 2508 | 2762 | |
|---|
| 2509 | | - if ((error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp))) |
|---|
| 2510 | | - return error; |
|---|
| 2511 | | - if (bp) |
|---|
| 2763 | + error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp); |
|---|
| 2764 | + if (!error) |
|---|
| 2512 | 2765 | xfs_trans_brelse(tp, bp); |
|---|
| 2513 | | - return 0; |
|---|
| 2766 | + return error; |
|---|
| 2514 | 2767 | } |
|---|
| 2515 | 2768 | |
|---|
| 2516 | 2769 | /* |
|---|
| .. | .. |
|---|
| 2524 | 2777 | xfs_agblock_t bno, /* block being freed */ |
|---|
| 2525 | 2778 | int btreeblk) /* block came from a AGF btree */ |
|---|
| 2526 | 2779 | { |
|---|
| 2527 | | - xfs_agf_t *agf; /* a.g. freespace structure */ |
|---|
| 2780 | + struct xfs_mount *mp = tp->t_mountp; |
|---|
| 2781 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 2528 | 2782 | __be32 *blockp;/* pointer to array entry */ |
|---|
| 2529 | 2783 | int error; |
|---|
| 2530 | 2784 | int logflags; |
|---|
| 2531 | | - xfs_mount_t *mp; /* mount structure */ |
|---|
| 2532 | 2785 | xfs_perag_t *pag; /* per allocation group data */ |
|---|
| 2533 | 2786 | __be32 *agfl_bno; |
|---|
| 2534 | 2787 | int startoff; |
|---|
| 2535 | | - |
|---|
| 2536 | | - agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 2537 | | - mp = tp->t_mountp; |
|---|
| 2538 | 2788 | |
|---|
| 2539 | 2789 | if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp, |
|---|
| 2540 | 2790 | be32_to_cpu(agf->agf_seqno), &agflbp))) |
|---|
| .. | .. |
|---|
| 2543 | 2793 | if (be32_to_cpu(agf->agf_fllast) == xfs_agfl_size(mp)) |
|---|
| 2544 | 2794 | agf->agf_fllast = 0; |
|---|
| 2545 | 2795 | |
|---|
| 2546 | | - pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno)); |
|---|
| 2796 | + pag = agbp->b_pag; |
|---|
| 2547 | 2797 | ASSERT(!pag->pagf_agflreset); |
|---|
| 2548 | 2798 | be32_add_cpu(&agf->agf_flcount, 1); |
|---|
| 2549 | 2799 | xfs_trans_agflist_delta(tp, 1); |
|---|
| .. | .. |
|---|
| 2555 | 2805 | pag->pagf_btreeblks--; |
|---|
| 2556 | 2806 | logflags |= XFS_AGF_BTREEBLKS; |
|---|
| 2557 | 2807 | } |
|---|
| 2558 | | - xfs_perag_put(pag); |
|---|
| 2559 | 2808 | |
|---|
| 2560 | 2809 | xfs_alloc_log_agf(tp, agbp, logflags); |
|---|
| 2561 | 2810 | |
|---|
| 2562 | 2811 | ASSERT(be32_to_cpu(agf->agf_flcount) <= xfs_agfl_size(mp)); |
|---|
| 2563 | 2812 | |
|---|
| 2564 | | - agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); |
|---|
| 2813 | + agfl_bno = xfs_buf_to_agfl_bno(agflbp); |
|---|
| 2565 | 2814 | blockp = &agfl_bno[be32_to_cpu(agf->agf_fllast)]; |
|---|
| 2566 | 2815 | *blockp = cpu_to_be32(bno); |
|---|
| 2567 | 2816 | startoff = (char *)blockp - (char *)agflbp->b_addr; |
|---|
| .. | .. |
|---|
| 2578 | 2827 | xfs_agf_verify( |
|---|
| 2579 | 2828 | struct xfs_buf *bp) |
|---|
| 2580 | 2829 | { |
|---|
| 2581 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
|---|
| 2582 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(bp); |
|---|
| 2830 | + struct xfs_mount *mp = bp->b_mount; |
|---|
| 2831 | + struct xfs_agf *agf = bp->b_addr; |
|---|
| 2583 | 2832 | |
|---|
| 2584 | 2833 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
|---|
| 2585 | 2834 | if (!uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) |
|---|
| 2586 | 2835 | return __this_address; |
|---|
| 2587 | | - if (!xfs_log_check_lsn(mp, |
|---|
| 2588 | | - be64_to_cpu(XFS_BUF_TO_AGF(bp)->agf_lsn))) |
|---|
| 2836 | + if (!xfs_log_check_lsn(mp, be64_to_cpu(agf->agf_lsn))) |
|---|
| 2589 | 2837 | return __this_address; |
|---|
| 2590 | 2838 | } |
|---|
| 2591 | 2839 | |
|---|
| 2592 | | - if (!(agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) && |
|---|
| 2593 | | - XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) && |
|---|
| 2840 | + if (!xfs_verify_magic(bp, agf->agf_magicnum)) |
|---|
| 2841 | + return __this_address; |
|---|
| 2842 | + |
|---|
| 2843 | + if (!(XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) && |
|---|
| 2594 | 2844 | be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) && |
|---|
| 2595 | 2845 | be32_to_cpu(agf->agf_flfirst) < xfs_agfl_size(mp) && |
|---|
| 2596 | 2846 | be32_to_cpu(agf->agf_fllast) < xfs_agfl_size(mp) && |
|---|
| .. | .. |
|---|
| 2650 | 2900 | xfs_agf_read_verify( |
|---|
| 2651 | 2901 | struct xfs_buf *bp) |
|---|
| 2652 | 2902 | { |
|---|
| 2653 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
|---|
| 2903 | + struct xfs_mount *mp = bp->b_mount; |
|---|
| 2654 | 2904 | xfs_failaddr_t fa; |
|---|
| 2655 | 2905 | |
|---|
| 2656 | 2906 | if (xfs_sb_version_hascrc(&mp->m_sb) && |
|---|
| .. | .. |
|---|
| 2667 | 2917 | xfs_agf_write_verify( |
|---|
| 2668 | 2918 | struct xfs_buf *bp) |
|---|
| 2669 | 2919 | { |
|---|
| 2670 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
|---|
| 2920 | + struct xfs_mount *mp = bp->b_mount; |
|---|
| 2671 | 2921 | struct xfs_buf_log_item *bip = bp->b_log_item; |
|---|
| 2922 | + struct xfs_agf *agf = bp->b_addr; |
|---|
| 2672 | 2923 | xfs_failaddr_t fa; |
|---|
| 2673 | 2924 | |
|---|
| 2674 | 2925 | fa = xfs_agf_verify(bp); |
|---|
| .. | .. |
|---|
| 2681 | 2932 | return; |
|---|
| 2682 | 2933 | |
|---|
| 2683 | 2934 | if (bip) |
|---|
| 2684 | | - XFS_BUF_TO_AGF(bp)->agf_lsn = cpu_to_be64(bip->bli_item.li_lsn); |
|---|
| 2935 | + agf->agf_lsn = cpu_to_be64(bip->bli_item.li_lsn); |
|---|
| 2685 | 2936 | |
|---|
| 2686 | 2937 | xfs_buf_update_cksum(bp, XFS_AGF_CRC_OFF); |
|---|
| 2687 | 2938 | } |
|---|
| 2688 | 2939 | |
|---|
| 2689 | 2940 | const struct xfs_buf_ops xfs_agf_buf_ops = { |
|---|
| 2690 | 2941 | .name = "xfs_agf", |
|---|
| 2942 | + .magic = { cpu_to_be32(XFS_AGF_MAGIC), cpu_to_be32(XFS_AGF_MAGIC) }, |
|---|
| 2691 | 2943 | .verify_read = xfs_agf_read_verify, |
|---|
| 2692 | 2944 | .verify_write = xfs_agf_write_verify, |
|---|
| 2693 | 2945 | .verify_struct = xfs_agf_verify, |
|---|
| .. | .. |
|---|
| 2709 | 2961 | trace_xfs_read_agf(mp, agno); |
|---|
| 2710 | 2962 | |
|---|
| 2711 | 2963 | ASSERT(agno != NULLAGNUMBER); |
|---|
| 2712 | | - error = xfs_trans_read_buf( |
|---|
| 2713 | | - mp, tp, mp->m_ddev_targp, |
|---|
| 2964 | + error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, |
|---|
| 2714 | 2965 | XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), |
|---|
| 2715 | 2966 | XFS_FSS_TO_BB(mp, 1), flags, bpp, &xfs_agf_buf_ops); |
|---|
| 2716 | 2967 | if (error) |
|---|
| 2717 | 2968 | return error; |
|---|
| 2718 | | - if (!*bpp) |
|---|
| 2719 | | - return 0; |
|---|
| 2720 | 2969 | |
|---|
| 2721 | 2970 | ASSERT(!(*bpp)->b_error); |
|---|
| 2722 | 2971 | xfs_buf_set_ref(*bpp, XFS_AGF_REF); |
|---|
| .. | .. |
|---|
| 2740 | 2989 | |
|---|
| 2741 | 2990 | trace_xfs_alloc_read_agf(mp, agno); |
|---|
| 2742 | 2991 | |
|---|
| 2992 | + /* We don't support trylock when freeing. */ |
|---|
| 2993 | + ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) != |
|---|
| 2994 | + (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)); |
|---|
| 2743 | 2995 | ASSERT(agno != NULLAGNUMBER); |
|---|
| 2744 | 2996 | error = xfs_read_agf(mp, tp, agno, |
|---|
| 2745 | 2997 | (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0, |
|---|
| 2746 | 2998 | bpp); |
|---|
| 2747 | 2999 | if (error) |
|---|
| 2748 | 3000 | return error; |
|---|
| 2749 | | - if (!*bpp) |
|---|
| 2750 | | - return 0; |
|---|
| 2751 | 3001 | ASSERT(!(*bpp)->b_error); |
|---|
| 2752 | 3002 | |
|---|
| 2753 | | - agf = XFS_BUF_TO_AGF(*bpp); |
|---|
| 2754 | | - pag = xfs_perag_get(mp, agno); |
|---|
| 3003 | + agf = (*bpp)->b_addr; |
|---|
| 3004 | + pag = (*bpp)->b_pag; |
|---|
| 2755 | 3005 | if (!pag->pagf_init) { |
|---|
| 2756 | 3006 | pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks); |
|---|
| 2757 | 3007 | pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks); |
|---|
| .. | .. |
|---|
| 2779 | 3029 | be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); |
|---|
| 2780 | 3030 | } |
|---|
| 2781 | 3031 | #endif |
|---|
| 2782 | | - xfs_perag_put(pag); |
|---|
| 2783 | 3032 | return 0; |
|---|
| 2784 | 3033 | } |
|---|
| 2785 | 3034 | |
|---|
| .. | .. |
|---|
| 2970 | 3219 | args->len); |
|---|
| 2971 | 3220 | #endif |
|---|
| 2972 | 3221 | |
|---|
| 2973 | | - /* Zero the extent if we were asked to do so */ |
|---|
| 2974 | | - if (args->datatype & XFS_ALLOC_USERDATA_ZERO) { |
|---|
| 2975 | | - error = xfs_zero_extent(args->ip, args->fsbno, args->len); |
|---|
| 2976 | | - if (error) |
|---|
| 2977 | | - goto error0; |
|---|
| 2978 | | - } |
|---|
| 2979 | | - |
|---|
| 2980 | 3222 | } |
|---|
| 2981 | 3223 | xfs_perag_put(args->pag); |
|---|
| 2982 | 3224 | return 0; |
|---|
| .. | .. |
|---|
| 3025 | 3267 | * Just break up the extent address and hand off to xfs_free_ag_extent |
|---|
| 3026 | 3268 | * after fixing up the freelist. |
|---|
| 3027 | 3269 | */ |
|---|
| 3028 | | -int /* error */ |
|---|
| 3270 | +int |
|---|
| 3029 | 3271 | __xfs_free_extent( |
|---|
| 3030 | | - struct xfs_trans *tp, /* transaction pointer */ |
|---|
| 3031 | | - xfs_fsblock_t bno, /* starting block number of extent */ |
|---|
| 3032 | | - xfs_extlen_t len, /* length of extent */ |
|---|
| 3033 | | - struct xfs_owner_info *oinfo, /* extent owner */ |
|---|
| 3034 | | - enum xfs_ag_resv_type type, /* block reservation type */ |
|---|
| 3035 | | - bool skip_discard) |
|---|
| 3272 | + struct xfs_trans *tp, |
|---|
| 3273 | + xfs_fsblock_t bno, |
|---|
| 3274 | + xfs_extlen_t len, |
|---|
| 3275 | + const struct xfs_owner_info *oinfo, |
|---|
| 3276 | + enum xfs_ag_resv_type type, |
|---|
| 3277 | + bool skip_discard) |
|---|
| 3036 | 3278 | { |
|---|
| 3037 | | - struct xfs_mount *mp = tp->t_mountp; |
|---|
| 3038 | | - struct xfs_buf *agbp; |
|---|
| 3039 | | - xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno); |
|---|
| 3040 | | - xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno); |
|---|
| 3041 | | - int error; |
|---|
| 3042 | | - unsigned int busy_flags = 0; |
|---|
| 3279 | + struct xfs_mount *mp = tp->t_mountp; |
|---|
| 3280 | + struct xfs_buf *agbp; |
|---|
| 3281 | + xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno); |
|---|
| 3282 | + xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno); |
|---|
| 3283 | + struct xfs_agf *agf; |
|---|
| 3284 | + int error; |
|---|
| 3285 | + unsigned int busy_flags = 0; |
|---|
| 3043 | 3286 | |
|---|
| 3044 | 3287 | ASSERT(len != 0); |
|---|
| 3045 | 3288 | ASSERT(type != XFS_AG_RESV_AGFL); |
|---|
| .. | .. |
|---|
| 3051 | 3294 | error = xfs_free_extent_fix_freelist(tp, agno, &agbp); |
|---|
| 3052 | 3295 | if (error) |
|---|
| 3053 | 3296 | return error; |
|---|
| 3297 | + agf = agbp->b_addr; |
|---|
| 3054 | 3298 | |
|---|
| 3055 | | - XFS_WANT_CORRUPTED_GOTO(mp, agbno < mp->m_sb.sb_agblocks, err); |
|---|
| 3299 | + if (XFS_IS_CORRUPT(mp, agbno >= mp->m_sb.sb_agblocks)) { |
|---|
| 3300 | + error = -EFSCORRUPTED; |
|---|
| 3301 | + goto err; |
|---|
| 3302 | + } |
|---|
| 3056 | 3303 | |
|---|
| 3057 | 3304 | /* validate the extent size is legal now we have the agf locked */ |
|---|
| 3058 | | - XFS_WANT_CORRUPTED_GOTO(mp, |
|---|
| 3059 | | - agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), |
|---|
| 3060 | | - err); |
|---|
| 3305 | + if (XFS_IS_CORRUPT(mp, agbno + len > be32_to_cpu(agf->agf_length))) { |
|---|
| 3306 | + error = -EFSCORRUPTED; |
|---|
| 3307 | + goto err; |
|---|
| 3308 | + } |
|---|
| 3061 | 3309 | |
|---|
| 3062 | 3310 | error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type); |
|---|
| 3063 | 3311 | if (error) |
|---|
| .. | .. |
|---|
| 3151 | 3399 | |
|---|
| 3152 | 3400 | /* |
|---|
| 3153 | 3401 | * Walk all the blocks in the AGFL. The @walk_fn can return any negative |
|---|
| 3154 | | - * error code or XFS_BTREE_QUERY_RANGE_ABORT. |
|---|
| 3402 | + * error code or XFS_ITER_*. |
|---|
| 3155 | 3403 | */ |
|---|
| 3156 | 3404 | int |
|---|
| 3157 | 3405 | xfs_agfl_walk( |
|---|
| .. | .. |
|---|
| 3165 | 3413 | unsigned int i; |
|---|
| 3166 | 3414 | int error; |
|---|
| 3167 | 3415 | |
|---|
| 3168 | | - agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); |
|---|
| 3416 | + agfl_bno = xfs_buf_to_agfl_bno(agflbp); |
|---|
| 3169 | 3417 | i = be32_to_cpu(agf->agf_flfirst); |
|---|
| 3170 | 3418 | |
|---|
| 3171 | 3419 | /* Nothing to walk in an empty AGFL. */ |
|---|