.. | .. |
---|
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. */ |
---|