Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -497,11 +497,18 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
	}

	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);
		else
		} else {
			wake_up_process(info->transaction_kthread);
		}
	}

	WARN_ON(cur_trans != info->running_transaction);
	WARN_ON(atomic_read(&cur_trans->num_writers) < 1);