summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2012-02-01 02:27:41 +0100
committerChris Mason <chris.mason@oracle.com>2012-02-01 02:27:41 +0100
commitd98456fcafa6f3fd1985f9b7429aaa3531c6bfa0 (patch)
tree7cf01b839f68a612b8d612e7eb6315955f792d73
parentBtrfs: fix reservations in btrfs_page_mkwrite (diff)
downloadlinux-d98456fcafa6f3fd1985f9b7429aaa3531c6bfa0.tar.xz
linux-d98456fcafa6f3fd1985f9b7429aaa3531c6bfa0.zip
Btrfs: don't reserve data with extents locked in btrfs_fallocate
btrfs_fallocate tries to allocate space only if ranges in the file don't already exist. But the enospc checks it does are not allowed with extents locked. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/file.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 0f61e11a2998..0621a3a7d5d1 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1604,6 +1604,14 @@ static long btrfs_fallocate(struct file *file, int mode,
return -EOPNOTSUPP;
/*
+ * Make sure we have enough space before we do the
+ * allocation.
+ */
+ ret = btrfs_check_data_free_space(inode, len);
+ if (ret)
+ return ret;
+
+ /*
* wait for ordered IO before we have any locks. We'll loop again
* below with the locks held.
*/
@@ -1666,27 +1674,12 @@ 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;
@@ -1714,6 +1707,8 @@ static long btrfs_fallocate(struct file *file, int mode,
&cached_state, GFP_NOFS);
out:
mutex_unlock(&inode->i_mutex);
+ /* Let go of our reservation. */
+ btrfs_free_reserved_data_space(inode, len);
return ret;
}