aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c57
1 files changed, 30 insertions, 27 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 97b601bec326..bb74a4181075 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1542,30 +1542,17 @@ static void btrfs_split_extent_hook(struct inode *inode,
1542 u64 new_size; 1542 u64 new_size;
1543 1543
1544 /* 1544 /*
1545 * We need the largest size of the remaining extent to see if we 1545 * See the explanation in btrfs_merge_extent_hook, the same
1546 * need to add a new outstanding extent. Think of the following 1546 * applies here, just in reverse.
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 */ 1547 */
1561 new_size = orig->end - split + 1; 1548 new_size = orig->end - split + 1;
1562 if ((split - orig->start) > new_size) 1549 num_extents = div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
1563 new_size = split - orig->start;
1564
1565 num_extents = div64_u64(size + BTRFS_MAX_EXTENT_SIZE - 1,
1566 BTRFS_MAX_EXTENT_SIZE); 1550 BTRFS_MAX_EXTENT_SIZE);
1567 if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1, 1551 new_size = split - orig->start;
1568 BTRFS_MAX_EXTENT_SIZE) < num_extents) 1552 num_extents += div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
1553 BTRFS_MAX_EXTENT_SIZE);
1554 if (div64_u64(size + BTRFS_MAX_EXTENT_SIZE - 1,
1555 BTRFS_MAX_EXTENT_SIZE) >= num_extents)
1569 return; 1556 return;
1570 } 1557 }
1571 1558
@@ -1591,9 +1578,6 @@ static void btrfs_merge_extent_hook(struct inode *inode,
1591 if (!(other->state & EXTENT_DELALLOC)) 1578 if (!(other->state & EXTENT_DELALLOC))
1592 return; 1579 return;
1593 1580
1594 old_size = other->end - other->start + 1;
1595 if (old_size < (new->end - new->start + 1))
1596 old_size = (new->end - new->start + 1);
1597 if (new->start > other->start) 1581 if (new->start > other->start)
1598 new_size = new->end - other->start + 1; 1582 new_size = new->end - other->start + 1;
1599 else 1583 else
@@ -1608,13 +1592,32 @@ static void btrfs_merge_extent_hook(struct inode *inode,
1608 } 1592 }
1609 1593
1610 /* 1594 /*
1611 * If we grew by another max_extent, just return, we want to keep that 1595 * We have to add up either side to figure out how many extents were
1612 * reserved amount. 1596 * accounted for before we merged into one big extent. If the number of
1597 * extents we accounted for is <= the amount we need for the new range
1598 * then we can return, otherwise drop. Think of it like this
1599 *
1600 * [ 4k][MAX_SIZE]
1601 *
1602 * So we've grown the extent by a MAX_SIZE extent, this would mean we
1603 * need 2 outstanding extents, on one side we have 1 and the other side
1604 * we have 1 so they are == and we can return. But in this case
1605 *
1606 * [MAX_SIZE+4k][MAX_SIZE+4k]
1607 *
1608 * Each range on their own accounts for 2 extents, but merged together
1609 * they are only 3 extents worth of accounting, so we need to drop in
1610 * this case.
1613 */ 1611 */
1612 old_size = other->end - other->start + 1;
1614 num_extents = div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1, 1613 num_extents = div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1,
1615 BTRFS_MAX_EXTENT_SIZE); 1614 BTRFS_MAX_EXTENT_SIZE);
1615 old_size = new->end - new->start + 1;
1616 num_extents += div64_u64(old_size + BTRFS_MAX_EXTENT_SIZE - 1,
1617 BTRFS_MAX_EXTENT_SIZE);
1618
1616 if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1, 1619 if (div64_u64(new_size + BTRFS_MAX_EXTENT_SIZE - 1,
1617 BTRFS_MAX_EXTENT_SIZE) > num_extents) 1620 BTRFS_MAX_EXTENT_SIZE) >= num_extents)
1618 return; 1621 return;
1619 1622
1620 spin_lock(&BTRFS_I(inode)->lock); 1623 spin_lock(&BTRFS_I(inode)->lock);