diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2013-01-28 07:36:22 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-02-05 16:09:11 -0500 |
commit | 843fcf35733164076a77ad833c72c32da8228ad0 (patch) | |
tree | 4da55ef848c61857624dc29e41b2fb1f8d52af1d /fs/btrfs/transaction.c | |
parent | 0a3404dcff29a7589e8d6ce8c36f97c5411f85b4 (diff) |
Btrfs: fix missing release of the space/qgroup reservation in start_transaction()
When we fail to start a transaction, we need to release the reserved free space
and qgroup space, fix it.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Reviewed-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f15494699f3b..fc03aa60b684 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -333,12 +333,14 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type, | |||
333 | &root->fs_info->trans_block_rsv, | 333 | &root->fs_info->trans_block_rsv, |
334 | num_bytes, flush); | 334 | num_bytes, flush); |
335 | if (ret) | 335 | if (ret) |
336 | return ERR_PTR(ret); | 336 | goto reserve_fail; |
337 | } | 337 | } |
338 | again: | 338 | again: |
339 | h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | 339 | h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); |
340 | if (!h) | 340 | if (!h) { |
341 | return ERR_PTR(-ENOMEM); | 341 | ret = -ENOMEM; |
342 | goto alloc_fail; | ||
343 | } | ||
342 | 344 | ||
343 | /* | 345 | /* |
344 | * If we are JOIN_NOLOCK we're already committing a transaction and | 346 | * If we are JOIN_NOLOCK we're already committing a transaction and |
@@ -365,11 +367,7 @@ again: | |||
365 | if (ret < 0) { | 367 | if (ret < 0) { |
366 | /* We must get the transaction if we are JOIN_NOLOCK. */ | 368 | /* We must get the transaction if we are JOIN_NOLOCK. */ |
367 | BUG_ON(type == TRANS_JOIN_NOLOCK); | 369 | BUG_ON(type == TRANS_JOIN_NOLOCK); |
368 | 370 | goto join_fail; | |
369 | if (type < TRANS_JOIN_NOLOCK) | ||
370 | sb_end_intwrite(root->fs_info->sb); | ||
371 | kmem_cache_free(btrfs_trans_handle_cachep, h); | ||
372 | return ERR_PTR(ret); | ||
373 | } | 371 | } |
374 | 372 | ||
375 | cur_trans = root->fs_info->running_transaction; | 373 | cur_trans = root->fs_info->running_transaction; |
@@ -410,6 +408,19 @@ got_it: | |||
410 | if (!current->journal_info && type != TRANS_USERSPACE) | 408 | if (!current->journal_info && type != TRANS_USERSPACE) |
411 | current->journal_info = h; | 409 | current->journal_info = h; |
412 | return h; | 410 | return h; |
411 | |||
412 | join_fail: | ||
413 | if (type < TRANS_JOIN_NOLOCK) | ||
414 | sb_end_intwrite(root->fs_info->sb); | ||
415 | kmem_cache_free(btrfs_trans_handle_cachep, h); | ||
416 | alloc_fail: | ||
417 | if (num_bytes) | ||
418 | btrfs_block_rsv_release(root, &root->fs_info->trans_block_rsv, | ||
419 | num_bytes); | ||
420 | reserve_fail: | ||
421 | if (qgroup_reserved) | ||
422 | btrfs_qgroup_free(root, qgroup_reserved); | ||
423 | return ERR_PTR(ret); | ||
413 | } | 424 | } |
414 | 425 | ||
415 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | 426 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, |