Commit 81317fde authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: fix deadlock when throttling transactions

Hit this nice little deadlock.  What happens is this

__btrfs_end_transaction with throttle set, --use_count so it equals 0
  btrfs_commit_transaction
    <somebody else actually manages to start the commit>
    btrfs_end_transaction --use_count so now its -1 <== BAD
      we just return and wait on the transaction

This is bad because we just return after our use_count is -1 and don't let go
of our num_writer count on the transaction, so the guy committing the
transaction just sits there forever.  Fix this by inc'ing our use_count if we're
going to call commit_transaction so that if we call btrfs_end_transaction it's
valid.  Thanks,
Signed-off-by: default avatarJosef Bacik <josef@redhat.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent a6591715
...@@ -497,11 +497,18 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, ...@@ -497,11 +497,18 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
} }
if (lock && cur_trans->blocked && !cur_trans->in_commit) { if (lock && cur_trans->blocked && !cur_trans->in_commit) {
if (throttle) if (throttle) {
/*
* We may race with somebody else here so end up having
* to call end_transaction on ourselves again, so inc
* our use_count.
*/
trans->use_count++;
return btrfs_commit_transaction(trans, root); return btrfs_commit_transaction(trans, root);
else } else {
wake_up_process(info->transaction_kthread); wake_up_process(info->transaction_kthread);
} }
}
WARN_ON(cur_trans != info->running_transaction); WARN_ON(cur_trans != info->running_transaction);
WARN_ON(atomic_read(&cur_trans->num_writers) < 1); WARN_ON(atomic_read(&cur_trans->num_writers) < 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment