Skip to content

Commit

Permalink
Btrfs: only reserve space in fallocate if we have to do a preallocate
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Josef Bacik committed Oct 19, 2011
1 parent 5e962c7 commit 1b9c332
Showing 1 changed file with 16 additions and 6 deletions.
22 changes: 16 additions & 6 deletions fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1615,10 +1615,6 @@ static long btrfs_fallocate(struct file *file, int mode,
goto out;
}

ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
if (ret)
goto out;

locked_end = alloc_end - 1;
while (1) {
struct btrfs_ordered_extent *ordered;
Expand Down Expand Up @@ -1664,11 +1660,27 @@ static long btrfs_fallocate(struct file *file, int mode,
if (em->block_start == EXTENT_MAP_HOLE ||
(cur_offset >= inode->i_size &&
!test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {

/*
* Make sure we have enough space before we do the
* allocation.
*/
ret = btrfs_check_data_free_space(inode, last_byte -
cur_offset);
if (ret) {
free_extent_map(em);
break;
}

ret = btrfs_prealloc_file_range(inode, mode, cur_offset,
last_byte - cur_offset,
1 << inode->i_blkbits,
offset + len,
&alloc_hint);

/* Let go of our reservation. */
btrfs_free_reserved_data_space(inode, last_byte -
cur_offset);
if (ret < 0) {
free_extent_map(em);
break;
Expand All @@ -1694,8 +1706,6 @@ static long btrfs_fallocate(struct file *file, int mode,
}
unlock_extent_cached(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
&cached_state, GFP_NOFS);

btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
out:
mutex_unlock(&inode->i_mutex);
return ret;
Expand Down

0 comments on commit 1b9c332

Please sign in to comment.