aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-02-06 16:55:41 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 12:59:35 -0500
commite4a2bcaca9643e7430207810653222fc5187f2be (patch)
tree204d6af57fbf70525359f5a2aa717a4785b89cd5
parent3e04e7f10b68999e0d8321516ea19d9d5b044dee (diff)
Btrfs: if we aren't committing just end the transaction if we error out
I hit a deadlock where transaction commit was waiting on num_writers to be 0. This happened because somebody came into btrfs_commit_transaction and noticed we had aborted and it went to cleanup_transaction. This shouldn't happen because cleanup_transaction is really to fixup a bad commit, it doesn't do the normal trans handle cleanup things. So if we have an error just do the normal btrfs_end_transaction dance and return. Once we are in the actual commit path we can use cleanup_transaction and be good to go. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
-rw-r--r--fs/btrfs/transaction.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index baf6d74fd0f2..5144ad19ef47 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1476,21 +1476,25 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1476 ret = btrfs_run_ordered_operations(root, 0); 1476 ret = btrfs_run_ordered_operations(root, 0);
1477 if (ret) { 1477 if (ret) {
1478 btrfs_abort_transaction(trans, root, ret); 1478 btrfs_abort_transaction(trans, root, ret);
1479 goto cleanup_transaction; 1479 btrfs_end_transaction(trans, root);
1480 return ret;
1480 } 1481 }
1481 1482
1482 /* Stop the commit early if ->aborted is set */ 1483 /* Stop the commit early if ->aborted is set */
1483 if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { 1484 if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
1484 ret = cur_trans->aborted; 1485 ret = cur_trans->aborted;
1485 goto cleanup_transaction; 1486 btrfs_end_transaction(trans, root);
1487 return ret;
1486 } 1488 }
1487 1489
1488 /* make a pass through all the delayed refs we have so far 1490 /* make a pass through all the delayed refs we have so far
1489 * any runnings procs may add more while we are here 1491 * any runnings procs may add more while we are here
1490 */ 1492 */
1491 ret = btrfs_run_delayed_refs(trans, root, 0); 1493 ret = btrfs_run_delayed_refs(trans, root, 0);
1492 if (ret) 1494 if (ret) {
1493 goto cleanup_transaction; 1495 btrfs_end_transaction(trans, root);
1496 return ret;
1497 }
1494 1498
1495 btrfs_trans_release_metadata(trans, root); 1499 btrfs_trans_release_metadata(trans, root);
1496 trans->block_rsv = NULL; 1500 trans->block_rsv = NULL;
@@ -1507,8 +1511,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1507 btrfs_create_pending_block_groups(trans, root); 1511 btrfs_create_pending_block_groups(trans, root);
1508 1512
1509 ret = btrfs_run_delayed_refs(trans, root, 0); 1513 ret = btrfs_run_delayed_refs(trans, root, 0);
1510 if (ret) 1514 if (ret) {
1511 goto cleanup_transaction; 1515 btrfs_end_transaction(trans, root);
1516 return ret;
1517 }
1512 1518
1513 spin_lock(&cur_trans->commit_lock); 1519 spin_lock(&cur_trans->commit_lock);
1514 if (cur_trans->in_commit) { 1520 if (cur_trans->in_commit) {