diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_alloc.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_alloc.c | 227 |
1 files changed, 109 insertions, 118 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index a9ff3cf82cce..372ad55631fc 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include "xfs_sb.h" | 13 | #include "xfs_sb.h" |
14 | #include "xfs_mount.h" | 14 | #include "xfs_mount.h" |
15 | #include "xfs_defer.h" | 15 | #include "xfs_defer.h" |
16 | #include "xfs_inode.h" | ||
17 | #include "xfs_btree.h" | 16 | #include "xfs_btree.h" |
18 | #include "xfs_rmap.h" | 17 | #include "xfs_rmap.h" |
19 | #include "xfs_alloc_btree.h" | 18 | #include "xfs_alloc_btree.h" |
@@ -21,7 +20,6 @@ | |||
21 | #include "xfs_extent_busy.h" | 20 | #include "xfs_extent_busy.h" |
22 | #include "xfs_errortag.h" | 21 | #include "xfs_errortag.h" |
23 | #include "xfs_error.h" | 22 | #include "xfs_error.h" |
24 | #include "xfs_cksum.h" | ||
25 | #include "xfs_trace.h" | 23 | #include "xfs_trace.h" |
26 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
27 | #include "xfs_buf_item.h" | 25 | #include "xfs_buf_item.h" |
@@ -41,8 +39,6 @@ struct workqueue_struct *xfs_alloc_wq; | |||
41 | STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *); | 39 | STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *); |
42 | STATIC int xfs_alloc_ag_vextent_near(xfs_alloc_arg_t *); | 40 | STATIC int xfs_alloc_ag_vextent_near(xfs_alloc_arg_t *); |
43 | STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); | 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 | * Size of the AGFL. For CRC-enabled filesystes we steal a couple of slots in | 44 | * Size of the AGFL. For CRC-enabled filesystes we steal a couple of slots in |
@@ -555,7 +551,7 @@ static xfs_failaddr_t | |||
555 | xfs_agfl_verify( | 551 | xfs_agfl_verify( |
556 | struct xfs_buf *bp) | 552 | struct xfs_buf *bp) |
557 | { | 553 | { |
558 | struct xfs_mount *mp = bp->b_target->bt_mount; | 554 | struct xfs_mount *mp = bp->b_mount; |
559 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); | 555 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); |
560 | int i; | 556 | int i; |
561 | 557 | ||
@@ -596,7 +592,7 @@ static void | |||
596 | xfs_agfl_read_verify( | 592 | xfs_agfl_read_verify( |
597 | struct xfs_buf *bp) | 593 | struct xfs_buf *bp) |
598 | { | 594 | { |
599 | struct xfs_mount *mp = bp->b_target->bt_mount; | 595 | struct xfs_mount *mp = bp->b_mount; |
600 | xfs_failaddr_t fa; | 596 | xfs_failaddr_t fa; |
601 | 597 | ||
602 | /* | 598 | /* |
@@ -621,7 +617,7 @@ static void | |||
621 | xfs_agfl_write_verify( | 617 | xfs_agfl_write_verify( |
622 | struct xfs_buf *bp) | 618 | struct xfs_buf *bp) |
623 | { | 619 | { |
624 | struct xfs_mount *mp = bp->b_target->bt_mount; | 620 | struct xfs_mount *mp = bp->b_mount; |
625 | struct xfs_buf_log_item *bip = bp->b_log_item; | 621 | struct xfs_buf_log_item *bip = bp->b_log_item; |
626 | xfs_failaddr_t fa; | 622 | xfs_failaddr_t fa; |
627 | 623 | ||
@@ -700,6 +696,107 @@ xfs_alloc_update_counters( | |||
700 | */ | 696 | */ |
701 | 697 | ||
702 | /* | 698 | /* |
699 | * Deal with the case where only small freespaces remain. Either return the | ||
700 | * contents of the last freespace record, or allocate space from the freelist if | ||
701 | * there is nothing in the tree. | ||
702 | */ | ||
703 | STATIC int /* error */ | ||
704 | xfs_alloc_ag_vextent_small( | ||
705 | struct xfs_alloc_arg *args, /* allocation argument structure */ | ||
706 | struct xfs_btree_cur *ccur, /* optional by-size cursor */ | ||
707 | xfs_agblock_t *fbnop, /* result block number */ | ||
708 | xfs_extlen_t *flenp, /* result length */ | ||
709 | int *stat) /* status: 0-freelist, 1-normal/none */ | ||
710 | { | ||
711 | int error = 0; | ||
712 | xfs_agblock_t fbno = NULLAGBLOCK; | ||
713 | xfs_extlen_t flen = 0; | ||
714 | int i = 0; | ||
715 | |||
716 | /* | ||
717 | * If a cntbt cursor is provided, try to allocate the largest record in | ||
718 | * the tree. Try the AGFL if the cntbt is empty, otherwise fail the | ||
719 | * allocation. Make sure to respect minleft even when pulling from the | ||
720 | * freelist. | ||
721 | */ | ||
722 | if (ccur) | ||
723 | error = xfs_btree_decrement(ccur, 0, &i); | ||
724 | if (error) | ||
725 | goto error; | ||
726 | if (i) { | ||
727 | error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i); | ||
728 | if (error) | ||
729 | goto error; | ||
730 | XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error); | ||
731 | goto out; | ||
732 | } | ||
733 | |||
734 | if (args->minlen != 1 || args->alignment != 1 || | ||
735 | args->resv == XFS_AG_RESV_AGFL || | ||
736 | (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) <= | ||
737 | args->minleft)) | ||
738 | goto out; | ||
739 | |||
740 | error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); | ||
741 | if (error) | ||
742 | goto error; | ||
743 | if (fbno == NULLAGBLOCK) | ||
744 | goto out; | ||
745 | |||
746 | xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, | ||
747 | xfs_alloc_allow_busy_reuse(args->datatype)); | ||
748 | |||
749 | if (xfs_alloc_is_userdata(args->datatype)) { | ||
750 | struct xfs_buf *bp; | ||
751 | |||
752 | bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno); | ||
753 | if (!bp) { | ||
754 | error = -EFSCORRUPTED; | ||
755 | goto error; | ||
756 | } | ||
757 | xfs_trans_binval(args->tp, bp); | ||
758 | } | ||
759 | *fbnop = args->agbno = fbno; | ||
760 | *flenp = args->len = 1; | ||
761 | XFS_WANT_CORRUPTED_GOTO(args->mp, | ||
762 | fbno < be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), | ||
763 | error); | ||
764 | args->wasfromfl = 1; | ||
765 | trace_xfs_alloc_small_freelist(args); | ||
766 | |||
767 | /* | ||
768 | * If we're feeding an AGFL block to something that doesn't live in the | ||
769 | * free space, we need to clear out the OWN_AG rmap. | ||
770 | */ | ||
771 | error = xfs_rmap_free(args->tp, args->agbp, args->agno, fbno, 1, | ||
772 | &XFS_RMAP_OINFO_AG); | ||
773 | if (error) | ||
774 | goto error; | ||
775 | |||
776 | *stat = 0; | ||
777 | return 0; | ||
778 | |||
779 | out: | ||
780 | /* | ||
781 | * Can't do the allocation, give up. | ||
782 | */ | ||
783 | if (flen < args->minlen) { | ||
784 | args->agbno = NULLAGBLOCK; | ||
785 | trace_xfs_alloc_small_notenough(args); | ||
786 | flen = 0; | ||
787 | } | ||
788 | *fbnop = fbno; | ||
789 | *flenp = flen; | ||
790 | *stat = 1; | ||
791 | trace_xfs_alloc_small_done(args); | ||
792 | return 0; | ||
793 | |||
794 | error: | ||
795 | trace_xfs_alloc_small_error(args); | ||
796 | return error; | ||
797 | } | ||
798 | |||
799 | /* | ||
703 | * Allocate a variable extent in the allocation group agno. | 800 | * Allocate a variable extent in the allocation group agno. |
704 | * Type and bno are used to determine where in the allocation group the | 801 | * Type and bno are used to determine where in the allocation group the |
705 | * extent will start. | 802 | * extent will start. |
@@ -1583,112 +1680,6 @@ out_nominleft: | |||
1583 | } | 1680 | } |
1584 | 1681 | ||
1585 | /* | 1682 | /* |
1586 | * Deal with the case where only small freespaces remain. | ||
1587 | * Either return the contents of the last freespace record, | ||
1588 | * or allocate space from the freelist if there is nothing in the tree. | ||
1589 | */ | ||
1590 | STATIC int /* error */ | ||
1591 | xfs_alloc_ag_vextent_small( | ||
1592 | xfs_alloc_arg_t *args, /* allocation argument structure */ | ||
1593 | xfs_btree_cur_t *ccur, /* by-size cursor */ | ||
1594 | xfs_agblock_t *fbnop, /* result block number */ | ||
1595 | xfs_extlen_t *flenp, /* result length */ | ||
1596 | int *stat) /* status: 0-freelist, 1-normal/none */ | ||
1597 | { | ||
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 | error = xfs_rmap_free(args->tp, args->agbp, args->agno, | ||
1652 | fbno, 1, &XFS_RMAP_OINFO_AG); | ||
1653 | if (error) | ||
1654 | goto error0; | ||
1655 | |||
1656 | *stat = 0; | ||
1657 | return 0; | ||
1658 | } | ||
1659 | /* | ||
1660 | * Nothing in the freelist. | ||
1661 | */ | ||
1662 | else | ||
1663 | flen = 0; | ||
1664 | } | ||
1665 | /* | ||
1666 | * Can't allocate from the freelist for some reason. | ||
1667 | */ | ||
1668 | else { | ||
1669 | fbno = NULLAGBLOCK; | ||
1670 | flen = 0; | ||
1671 | } | ||
1672 | /* | ||
1673 | * Can't do the allocation, give up. | ||
1674 | */ | ||
1675 | if (flen < args->minlen) { | ||
1676 | args->agbno = NULLAGBLOCK; | ||
1677 | trace_xfs_alloc_small_notenough(args); | ||
1678 | flen = 0; | ||
1679 | } | ||
1680 | *fbnop = fbno; | ||
1681 | *flenp = flen; | ||
1682 | *stat = 1; | ||
1683 | trace_xfs_alloc_small_done(args); | ||
1684 | return 0; | ||
1685 | |||
1686 | error0: | ||
1687 | trace_xfs_alloc_small_error(args); | ||
1688 | return error; | ||
1689 | } | ||
1690 | |||
1691 | /* | ||
1692 | * Free the extent starting at agno/bno for length. | 1683 | * Free the extent starting at agno/bno for length. |
1693 | */ | 1684 | */ |
1694 | STATIC int | 1685 | STATIC int |
@@ -2095,7 +2086,7 @@ xfs_free_agfl_block( | |||
2095 | if (error) | 2086 | if (error) |
2096 | return error; | 2087 | return error; |
2097 | 2088 | ||
2098 | bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno, 0); | 2089 | bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno); |
2099 | if (!bp) | 2090 | if (!bp) |
2100 | return -EFSCORRUPTED; | 2091 | return -EFSCORRUPTED; |
2101 | xfs_trans_binval(tp, bp); | 2092 | xfs_trans_binval(tp, bp); |
@@ -2586,7 +2577,7 @@ static xfs_failaddr_t | |||
2586 | xfs_agf_verify( | 2577 | xfs_agf_verify( |
2587 | struct xfs_buf *bp) | 2578 | struct xfs_buf *bp) |
2588 | { | 2579 | { |
2589 | struct xfs_mount *mp = bp->b_target->bt_mount; | 2580 | struct xfs_mount *mp = bp->b_mount; |
2590 | struct xfs_agf *agf = XFS_BUF_TO_AGF(bp); | 2581 | struct xfs_agf *agf = XFS_BUF_TO_AGF(bp); |
2591 | 2582 | ||
2592 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 2583 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
@@ -2644,7 +2635,7 @@ static void | |||
2644 | xfs_agf_read_verify( | 2635 | xfs_agf_read_verify( |
2645 | struct xfs_buf *bp) | 2636 | struct xfs_buf *bp) |
2646 | { | 2637 | { |
2647 | struct xfs_mount *mp = bp->b_target->bt_mount; | 2638 | struct xfs_mount *mp = bp->b_mount; |
2648 | xfs_failaddr_t fa; | 2639 | xfs_failaddr_t fa; |
2649 | 2640 | ||
2650 | if (xfs_sb_version_hascrc(&mp->m_sb) && | 2641 | if (xfs_sb_version_hascrc(&mp->m_sb) && |
@@ -2661,7 +2652,7 @@ static void | |||
2661 | xfs_agf_write_verify( | 2652 | xfs_agf_write_verify( |
2662 | struct xfs_buf *bp) | 2653 | struct xfs_buf *bp) |
2663 | { | 2654 | { |
2664 | struct xfs_mount *mp = bp->b_target->bt_mount; | 2655 | struct xfs_mount *mp = bp->b_mount; |
2665 | struct xfs_buf_log_item *bip = bp->b_log_item; | 2656 | struct xfs_buf_log_item *bip = bp->b_log_item; |
2666 | xfs_failaddr_t fa; | 2657 | xfs_failaddr_t fa; |
2667 | 2658 | ||
@@ -3146,7 +3137,7 @@ xfs_alloc_has_record( | |||
3146 | 3137 | ||
3147 | /* | 3138 | /* |
3148 | * Walk all the blocks in the AGFL. The @walk_fn can return any negative | 3139 | * Walk all the blocks in the AGFL. The @walk_fn can return any negative |
3149 | * error code or XFS_BTREE_QUERY_RANGE_ABORT. | 3140 | * error code or XFS_ITER_*. |
3150 | */ | 3141 | */ |
3151 | int | 3142 | int |
3152 | xfs_agfl_walk( | 3143 | xfs_agfl_walk( |