diff options
| -rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 16 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 63 |
4 files changed, 76 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index d3562dd43c66..b3dd55f52f71 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -198,6 +198,8 @@ static int btrfs_csum_sizes[] = { 4, 0 }; | |||
| 198 | 198 | ||
| 199 | #define BTRFS_DIRTY_METADATA_THRESH (32 * 1024 * 1024) | 199 | #define BTRFS_DIRTY_METADATA_THRESH (32 * 1024 * 1024) |
| 200 | 200 | ||
| 201 | #define BTRFS_MAX_EXTENT_SIZE (128 * 1024 * 1024) | ||
| 202 | |||
| 201 | /* | 203 | /* |
| 202 | * The key defines the order in the tree, and so it also defines (optimal) | 204 | * The key defines the order in the tree, and so it also defines (optimal) |
| 203 | * block layout. | 205 | * block layout. |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 50de1fa6fc9e..0f6737063142 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -4963,19 +4963,25 @@ void btrfs_subvolume_release_metadata(struct btrfs_root *root, | |||
| 4963 | /** | 4963 | /** |
| 4964 | * drop_outstanding_extent - drop an outstanding extent | 4964 | * drop_outstanding_extent - drop an outstanding extent |
| 4965 | * @inode: the inode we're dropping the extent for | 4965 | * @inode: the inode we're dropping the extent for |
| 4966 | * @num_bytes: the number of bytes we're relaseing. | ||
| 4966 | * | 4967 | * |
| 4967 | * This is called when we are freeing up an outstanding extent, either called | 4968 | * This is called when we are freeing up an outstanding extent, either called |
| 4968 | * after an error or after an extent is written. This will return the number of | 4969 | * after an error or after an extent is written. This will return the number of |
| 4969 | * reserved extents that need to be freed. This must be called with | 4970 | * reserved extents that need to be freed. This must be called with |
| 4970 | * BTRFS_I(inode)->lock held. | 4971 | * BTRFS_I(inode)->lock held. |
| 4971 | */ | 4972 | */ |
| 4972 | static unsigned drop_outstanding_extent(struct inode *inode) | 4973 | static unsigned drop_outstanding_extent(struct inode *inode, u64 num_bytes) |
| 4973 | { | 4974 | { |
| 4974 | unsigned drop_inode_space = 0; | 4975 | unsigned drop_inode_space = 0; |
| 4975 | unsigned dropped_extents = 0; | 4976 | unsigned dropped_extents = 0; |
| 4977 | unsigned num_extents = 0; | ||
| 4976 | 4978 | ||
| 4977 | BUG_ON(!BTRFS_I(inode)->outstanding_extents); | 4979 | num_extents = (unsigned)div64_u64(num_bytes + |
| 4978 | BTRFS_I(inode)->outstanding_extents--; | 4980 | BTRFS_MAX_EXTENT_SIZE - 1, |
| 4981 | BTRFS_MAX_EXTENT_SIZE); | ||
| 4982 | ASSERT(num_extents); | ||
| 4983 | ASSERT(BTRFS_I(inode)->outstanding_extents >= num_extents); | ||
| 4984 | BTRFS_I(inode)->outstanding_extents -= num_extents; | ||
| 4979 | 4985 | ||
| 4980 | if (BTRFS_I(inode)->outstanding_extents == 0 && | 4986 | if (BTRFS_I(inode)->outstanding_extents == 0 && |
| 4981 | test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED, | 4987 | test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED, |
| @@ -5146,7 +5152,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
| 5146 | 5152 | ||
| 5147 | out_fail: | 5153 | out_fail: |
| 5148 | spin_lock(&BTRFS_I(inode)->lock); | 5154 | spin_lock(&BTRFS_I(inode)->lock); |
| 5149 | dropped = drop_outstanding_extent(inode); | 5155 | dropped = drop_outstanding_extent(inode, num_bytes); |
| 5150 | /* | 5156 | /* |
| 5151 | * If the inodes csum_bytes is the same as the original | 5157 | * If the inodes csum_bytes is the same as the original |
| 5152 | * csum_bytes then we know we haven't raced with any free()ers | 5158 | * csum_bytes then we know we haven't raced with any free()ers |
| @@ -5225,7 +5231,7 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) | |||
| 5225 | 5231 | ||
| 5226 | num_bytes = ALIGN(num_bytes, root->sectorsize); | 5232 | num_bytes = ALIGN(num_bytes, root->sectorsize); |
| 5227 | spin_lock(&BTRFS_I(inode)->lock); | 5233 | spin_lock(&BTRFS_I(inode)->lock); |
| 5228 | dropped = drop_outstanding_extent(inode); | 5234 | dropped = drop_outstanding_extent(inode, num_bytes); |
| 5229 | 5235 | ||
| 5230 | if (num_bytes) | 5236 | if (num_bytes) |
| 5231 | to_free = calc_csum_metadata_size(inode, num_bytes, 0); | 5237 | to_free = calc_csum_metadata_size(inode, num_bytes, 0); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index a7f66009519a..29850d4a3827 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -3242,7 +3242,7 @@ static noinline_for_stack int writepage_delalloc(struct inode *inode, | |||
| 3242 | page, | 3242 | page, |
| 3243 | &delalloc_start, | 3243 | &delalloc_start, |
| 3244 | &delalloc_end, | 3244 | &delalloc_end, |
| 3245 | 128 * 1024 * 1024); | 3245 | BTRFS_MAX_EXTENT_SIZE); |
| 3246 | if (nr_delalloc == 0) { | 3246 | if (nr_delalloc == 0) { |
| 3247 | delalloc_start = delalloc_end + 1; | 3247 | delalloc_start = delalloc_end + 1; |
| 3248 | continue; | 3248 | continue; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3b957921ba59..8564d8ce03de 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -1530,10 +1530,45 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, | |||
| 1530 | static void btrfs_split_extent_hook(struct inode *inode, | 1530 | static void btrfs_split_extent_hook(struct inode *inode, |
| 1531 | struct extent_state *orig, u64 split) | 1531 | struct extent_state *orig, u64 split) |
| 1532 | { | 1532 | { |
| 1533 | u64 size; | ||
| 1534 | |||
| 1533 | /* not delalloc, ignore it */ | 1535 | /* not delalloc, ignore it */ |
| 1534 | if (!(orig->state & EXTENT_DELALLOC)) | 1536 | if (!(orig->state & EXTENT_DELALLOC)) |
| 1535 | return; | 1537 | return; |
| 1536 | 1538 | ||
| 1539 | size = orig->end - orig->start + 1; | ||
| 1540 | if (size > BTRFS_MAX_EXTENT_SIZE) { | ||
| 1541 | u64 num_extents; | ||
| 1542 | u64 new_size; | ||
| 1543 | |||
| 1544 | /* | ||
| 1545 | * We need the largest size of the remaining extent to see if we | ||
| 1546 | * need to add a new outstanding extent. Think of the following | ||
| 1547 | * case | ||
| 1548 | * | ||
| 1549 | * [MEAX_EXTENT_SIZEx2 - 4k][4k] | ||
| 1550 | * | ||
| 1551 | * The new_size would just be 4k and we'd think we had enough | ||
| 1552 | * outstanding extents for this if we only took one side of the | ||
| 1553 | * split, same goes for the other direction. We need to see if | ||
| 1554 | * the larger size still is the same amount of extents as the | ||
| 1555 | * original size, because if it is we need to add a new | ||
| 1556 | * outstanding extent. But if we split up and the larger size | ||
| 1557 | * is less than the original then we are good to go since we've | ||
| 1558 | * already accounted for the extra extent in our original | ||
| 1559 | * accounting. | ||
| 1560 | */ | ||
| 1561 | new_size = orig->end - split + 1; | ||
| 1562 | if ((split - orig->start) > new_size) | ||
| 1563 | new_size = split - orig->start; | ||
| 1564 | |||
| 1565 | num_extents = div64_u64(size + BTRFS_MAX_EXTENT_SIZE - 1, | ||
| 1566 | BTRFS_MAX_EXTENT_SIZE); | ||
| 1567 | if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1, | ||
| 1568 | BTRFS_MAX_EXTENT_SIZE) < num_extents) | ||
| 1569 | return; | ||
| 1570 | } | ||
| 1571 | |||
| 1537 | spin_lock(&BTRFS_I(inode)->lock); | 1572 | spin_lock(&BTRFS_I(inode)->lock); |
| 1538 | BTRFS_I(inode)->outstanding_extents++; | 1573 | BTRFS_I(inode)->outstanding_extents++; |
| 1539 | spin_unlock(&BTRFS_I(inode)->lock); | 1574 | spin_unlock(&BTRFS_I(inode)->lock); |
| @@ -1549,10 +1584,34 @@ static void btrfs_merge_extent_hook(struct inode *inode, | |||
| 1549 | struct extent_state *new, | 1584 | struct extent_state *new, |
| 1550 | struct extent_state *other) | 1585 | struct extent_state *other) |
| 1551 | { | 1586 | { |
| 1587 | u64 new_size, old_size; | ||
| 1588 | u64 num_extents; | ||
| 1589 | |||
| 1552 | /* not delalloc, ignore it */ | 1590 | /* not delalloc, ignore it */ |
| 1553 | if (!(other->state & EXTENT_DELALLOC)) | 1591 | if (!(other->state & EXTENT_DELALLOC)) |
| 1554 | return; | 1592 | return; |
| 1555 | 1593 | ||
| 1594 | old_size = other->end - other->start + 1; | ||
| 1595 | new_size = old_size + (new->end - new->start + 1); | ||
| 1596 | |||
| 1597 | /* we're not bigger than the max, unreserve the space and go */ | ||
| 1598 | if (new_size <= BTRFS_MAX_EXTENT_SIZE) { | ||
| 1599 | spin_lock(&BTRFS_I(inode)->lock); | ||
| 1600 | BTRFS_I(inode)->outstanding_extents--; | ||
| 1601 | spin_unlock(&BTRFS_I(inode)->lock); | ||
| 1602 | return; | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | /* | ||
| 1606 | * If we grew by another max_extent, just return, we want to keep that | ||
| 1607 | * reserved amount. | ||
| 1608 | */ | ||
| 1609 | num_extents = div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1, | ||
| 1610 | BTRFS_MAX_EXTENT_SIZE); | ||
| 1611 | if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1, | ||
| 1612 | BTRFS_MAX_EXTENT_SIZE) > num_extents) | ||
| 1613 | return; | ||
| 1614 | |||
| 1556 | spin_lock(&BTRFS_I(inode)->lock); | 1615 | spin_lock(&BTRFS_I(inode)->lock); |
| 1557 | BTRFS_I(inode)->outstanding_extents--; | 1616 | BTRFS_I(inode)->outstanding_extents--; |
| 1558 | spin_unlock(&BTRFS_I(inode)->lock); | 1617 | spin_unlock(&BTRFS_I(inode)->lock); |
| @@ -1648,6 +1707,8 @@ static void btrfs_clear_bit_hook(struct inode *inode, | |||
| 1648 | unsigned *bits) | 1707 | unsigned *bits) |
| 1649 | { | 1708 | { |
| 1650 | u64 len = state->end + 1 - state->start; | 1709 | u64 len = state->end + 1 - state->start; |
| 1710 | u64 num_extents = div64_u64(len + BTRFS_MAX_EXTENT_SIZE -1, | ||
| 1711 | BTRFS_MAX_EXTENT_SIZE); | ||
| 1651 | 1712 | ||
| 1652 | spin_lock(&BTRFS_I(inode)->lock); | 1713 | spin_lock(&BTRFS_I(inode)->lock); |
| 1653 | if ((state->state & EXTENT_DEFRAG) && (*bits & EXTENT_DEFRAG)) | 1714 | if ((state->state & EXTENT_DEFRAG) && (*bits & EXTENT_DEFRAG)) |
| @@ -1667,7 +1728,7 @@ static void btrfs_clear_bit_hook(struct inode *inode, | |||
| 1667 | *bits &= ~EXTENT_FIRST_DELALLOC; | 1728 | *bits &= ~EXTENT_FIRST_DELALLOC; |
| 1668 | } else if (!(*bits & EXTENT_DO_ACCOUNTING)) { | 1729 | } else if (!(*bits & EXTENT_DO_ACCOUNTING)) { |
| 1669 | spin_lock(&BTRFS_I(inode)->lock); | 1730 | spin_lock(&BTRFS_I(inode)->lock); |
| 1670 | BTRFS_I(inode)->outstanding_extents--; | 1731 | BTRFS_I(inode)->outstanding_extents -= num_extents; |
| 1671 | spin_unlock(&BTRFS_I(inode)->lock); | 1732 | spin_unlock(&BTRFS_I(inode)->lock); |
| 1672 | } | 1733 | } |
| 1673 | 1734 | ||
