diff options
author | Chris Mason <chris.mason@oracle.com> | 2012-02-01 05:27:41 +0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-02-01 05:27:41 +0400 |
commit | d98456fcafa6f3fd1985f9b7429aaa3531c6bfa0 (patch) | |
tree | 7cf01b839f68a612b8d612e7eb6315955f792d73 | |
parent | 9998eb703490589c3e8f1bf09b15203156776edb (diff) | |
download | linux-d98456fcafa6f3fd1985f9b7429aaa3531c6bfa0.tar.xz |
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.c | 25 |
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; } |