aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c16
-rw-r--r--fs/btrfs/extent_io.c2
-rw-r--r--fs/btrfs/inode.c63
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 */
4972static unsigned drop_outstanding_extent(struct inode *inode) 4973static 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
5147out_fail: 5153out_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,
1530static void btrfs_split_extent_hook(struct inode *inode, 1530static 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