]> Pileus Git - ~andy/linux/commitdiff
Btrfs: if we aren't committing just end the transaction if we error out
authorJosef Bacik <jbacik@fusionio.com>
Wed, 6 Feb 2013 21:55:41 +0000 (16:55 -0500)
committerJosef Bacik <jbacik@fusionio.com>
Wed, 20 Feb 2013 17:59:35 +0000 (12:59 -0500)
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>
fs/btrfs/transaction.c

index baf6d74fd0f29d618d60c15921a482f627d67fe7..5144ad19ef47a0b2fa3cdaa699eb94e7a06dad7c 100644 (file)
@@ -1476,21 +1476,25 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        ret = btrfs_run_ordered_operations(root, 0);
        if (ret) {
                btrfs_abort_transaction(trans, root, ret);
-               goto cleanup_transaction;
+               btrfs_end_transaction(trans, root);
+               return ret;
        }
 
        /* Stop the commit early if ->aborted is set */
        if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
                ret = cur_trans->aborted;
-               goto cleanup_transaction;
+               btrfs_end_transaction(trans, root);
+               return ret;
        }
 
        /* make a pass through all the delayed refs we have so far
         * any runnings procs may add more while we are here
         */
        ret = btrfs_run_delayed_refs(trans, root, 0);
-       if (ret)
-               goto cleanup_transaction;
+       if (ret) {
+               btrfs_end_transaction(trans, root);
+               return ret;
+       }
 
        btrfs_trans_release_metadata(trans, root);
        trans->block_rsv = NULL;
@@ -1507,8 +1511,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                btrfs_create_pending_block_groups(trans, root);
 
        ret = btrfs_run_delayed_refs(trans, root, 0);
-       if (ret)
-               goto cleanup_transaction;
+       if (ret) {
+               btrfs_end_transaction(trans, root);
+               return ret;
+       }
 
        spin_lock(&cur_trans->commit_lock);
        if (cur_trans->in_commit) {