aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@redhat.com>2009-06-27 21:07:34 -0400
committerChris Mason <chris.mason@oracle.com>2009-07-02 13:41:16 -0400
commita970b0a16cc416a509d5ae8b1d70978664e6f4fe (patch)
treefa371ca55fd97cd00ddb3b27ba1a784551a469a0
parentc8a894d77de4a1e0a544577fd4eabc9aacd453a8 (diff)
Btrfs: account for space we may use in fallocate
Using Eric Sandeen's xfstest for fallocate, you can easily trigger a ENOSPC panic on btrfs. This is because we do not account for data we may use when doing the fallocate. This patch fixes the problem by properly reserving space, and then just freeing it when we are done. The reservation stuff was made with delalloc in mind, so its a little crude for this case, but it keeps the box from panicing. Signed-off-by: Josef Bacik <jbacik@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/inode.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5b68330f8585..1eacc78f6614 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5103,6 +5103,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
5103 u64 mask = BTRFS_I(inode)->root->sectorsize - 1; 5103 u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
5104 struct extent_map *em; 5104 struct extent_map *em;
5105 struct btrfs_trans_handle *trans; 5105 struct btrfs_trans_handle *trans;
5106 struct btrfs_root *root;
5106 int ret; 5107 int ret;
5107 5108
5108 alloc_start = offset & ~mask; 5109 alloc_start = offset & ~mask;
@@ -5121,6 +5122,13 @@ static long btrfs_fallocate(struct inode *inode, int mode,
5121 goto out; 5122 goto out;
5122 } 5123 }
5123 5124
5125 root = BTRFS_I(inode)->root;
5126
5127 ret = btrfs_check_data_free_space(root, inode,
5128 alloc_end - alloc_start);
5129 if (ret)
5130 goto out;
5131
5124 locked_end = alloc_end - 1; 5132 locked_end = alloc_end - 1;
5125 while (1) { 5133 while (1) {
5126 struct btrfs_ordered_extent *ordered; 5134 struct btrfs_ordered_extent *ordered;
@@ -5128,7 +5136,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
5128 trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1); 5136 trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
5129 if (!trans) { 5137 if (!trans) {
5130 ret = -EIO; 5138 ret = -EIO;
5131 goto out; 5139 goto out_free;
5132 } 5140 }
5133 5141
5134 /* the extent lock is ordered inside the running 5142 /* the extent lock is ordered inside the running
@@ -5189,6 +5197,8 @@ static long btrfs_fallocate(struct inode *inode, int mode,
5189 GFP_NOFS); 5197 GFP_NOFS);
5190 5198
5191 btrfs_end_transaction(trans, BTRFS_I(inode)->root); 5199 btrfs_end_transaction(trans, BTRFS_I(inode)->root);
5200out_free:
5201 btrfs_free_reserved_data_space(root, inode, alloc_end - alloc_start);
5192out: 5202out:
5193 mutex_unlock(&inode->i_mutex); 5203 mutex_unlock(&inode->i_mutex);
5194 return ret; 5204 return ret;