aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-06-07 15:07:51 -0400
committerJosef Bacik <josef@redhat.com>2011-07-11 09:58:47 -0400
commitb5009945be18023942ce28327893c7bc1e58fe54 (patch)
treefe2e04196c833a3b609a1cf947293aafcf90a7bd /fs/btrfs/transaction.c
parentfa09200b8334f9a6af3f656edae924a98d85630f (diff)
Btrfs: do transaction space reservation before joining the transaction
We have to do weird things when handling enospc in the transaction joining code. Because we've already joined the transaction we cannot commit the transaction within the reservation code since it will deadlock, so we have to return EAGAIN and then make sure we don't retry too many times. Instead of doing this, just do the reservation the normal way before we join the transaction, that way we can do whatever we want to try and reclaim space, and then if it fails we know for sure we are out of space and we can return ENOSPC. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c36
1 files changed, 17 insertions, 19 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 51dcec86757..654755b1895 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -260,7 +260,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
260{ 260{
261 struct btrfs_trans_handle *h; 261 struct btrfs_trans_handle *h;
262 struct btrfs_transaction *cur_trans; 262 struct btrfs_transaction *cur_trans;
263 int retries = 0; 263 u64 num_bytes = 0;
264 int ret; 264 int ret;
265 265
266 if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) 266 if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
@@ -274,6 +274,19 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
274 h->block_rsv = NULL; 274 h->block_rsv = NULL;
275 goto got_it; 275 goto got_it;
276 } 276 }
277
278 /*
279 * Do the reservation before we join the transaction so we can do all
280 * the appropriate flushing if need be.
281 */
282 if (num_items > 0 && root != root->fs_info->chunk_root) {
283 num_bytes = btrfs_calc_trans_metadata_size(root, num_items);
284 ret = btrfs_block_rsv_add(NULL, root,
285 &root->fs_info->trans_block_rsv,
286 num_bytes);
287 if (ret)
288 return ERR_PTR(ret);
289 }
277again: 290again:
278 h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); 291 h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
279 if (!h) 292 if (!h)
@@ -310,24 +323,9 @@ again:
310 goto again; 323 goto again;
311 } 324 }
312 325
313 if (num_items > 0) { 326 if (num_bytes) {
314 ret = btrfs_trans_reserve_metadata(h, root, num_items); 327 h->block_rsv = &root->fs_info->trans_block_rsv;
315 if (ret == -EAGAIN && !retries) { 328 h->bytes_reserved = num_bytes;
316 retries++;
317 btrfs_commit_transaction(h, root);
318 goto again;
319 } else if (ret == -EAGAIN) {
320 /*
321 * We have already retried and got EAGAIN, so really we
322 * don't have space, so set ret to -ENOSPC.
323 */
324 ret = -ENOSPC;
325 }
326
327 if (ret < 0) {
328 btrfs_end_transaction(h, root);
329 return ERR_PTR(ret);
330 }
331 } 329 }
332 330
333got_it: 331got_it: