aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-08-17 10:19:52 -0400
committerJosef Bacik <josef@redhat.com>2011-10-19 15:12:36 -0400
commit1b9c332b6c92e992b1971a08412c6f460a54b514 (patch)
treeefdff83971345340faaf57823c0316962445a458
parent5e962c7850c273b483acc747b41bd5cddf631049 (diff)
Btrfs: only reserve space in fallocate if we have to do a preallocate
Lukas found a problem where if he tries to fallocate over the same region twice and the first fallocate took up all the space we would fail with ENOSPC. This is because we reserve the total space we want to use for fallocate, regardless of wether or not we will have to actually preallocate. So instead move the check into the loop where we actually have to do the preallocate. Thanks, Tested-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: Josef Bacik <josef@redhat.com>
-rw-r--r--fs/btrfs/file.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index e4e57d59edb7..de569af766fe 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1615,10 +1615,6 @@ static long btrfs_fallocate(struct file *file, int mode,
1615 goto out; 1615 goto out;
1616 } 1616 }
1617 1617
1618 ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
1619 if (ret)
1620 goto out;
1621
1622 locked_end = alloc_end - 1; 1618 locked_end = alloc_end - 1;
1623 while (1) { 1619 while (1) {
1624 struct btrfs_ordered_extent *ordered; 1620 struct btrfs_ordered_extent *ordered;
@@ -1664,11 +1660,27 @@ static long btrfs_fallocate(struct file *file, int mode,
1664 if (em->block_start == EXTENT_MAP_HOLE || 1660 if (em->block_start == EXTENT_MAP_HOLE ||
1665 (cur_offset >= inode->i_size && 1661 (cur_offset >= inode->i_size &&
1666 !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { 1662 !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
1663
1664 /*
1665 * Make sure we have enough space before we do the
1666 * allocation.
1667 */
1668 ret = btrfs_check_data_free_space(inode, last_byte -
1669 cur_offset);
1670 if (ret) {
1671 free_extent_map(em);
1672 break;
1673 }
1674
1667 ret = btrfs_prealloc_file_range(inode, mode, cur_offset, 1675 ret = btrfs_prealloc_file_range(inode, mode, cur_offset,
1668 last_byte - cur_offset, 1676 last_byte - cur_offset,
1669 1 << inode->i_blkbits, 1677 1 << inode->i_blkbits,
1670 offset + len, 1678 offset + len,
1671 &alloc_hint); 1679 &alloc_hint);
1680
1681 /* Let go of our reservation. */
1682 btrfs_free_reserved_data_space(inode, last_byte -
1683 cur_offset);
1672 if (ret < 0) { 1684 if (ret < 0) {
1673 free_extent_map(em); 1685 free_extent_map(em);
1674 break; 1686 break;
@@ -1694,8 +1706,6 @@ static long btrfs_fallocate(struct file *file, int mode,
1694 } 1706 }
1695 unlock_extent_cached(&BTRFS_I(inode)->io_tree, alloc_start, locked_end, 1707 unlock_extent_cached(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
1696 &cached_state, GFP_NOFS); 1708 &cached_state, GFP_NOFS);
1697
1698 btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
1699out: 1709out:
1700 mutex_unlock(&inode->i_mutex); 1710 mutex_unlock(&inode->i_mutex);
1701 return ret; 1711 return ret;