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

Commit fe1e8db5 authored by Jan Kara's avatar Jan Kara Committed by Theodore Ts'o
Browse files

jbd2: fix race in t_outstanding_credits update in jbd2_journal_extend()



jbd2_journal_extend() first checked whether transaction can accept
extending handle with more credits and then added credits to
t_outstanding_credits.  This can race with start_this_handle() adding
another handle to a transaction and thus overbooking a transaction.
Make jbd2_journal_extend() use atomic_add_return() to close the race.

Reviewed-by: default avatarZheng Liu <wenqing.lz@taobao.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 76c39904
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -433,11 +433,13 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
	}

	spin_lock(&transaction->t_handle_lock);
	wanted = atomic_read(&transaction->t_outstanding_credits) + nblocks;
	wanted = atomic_add_return(nblocks,
				   &transaction->t_outstanding_credits);

	if (wanted > journal->j_max_transaction_buffers) {
		jbd_debug(3, "denied handle %p %d blocks: "
			  "transaction too large\n", handle, nblocks);
		atomic_sub(nblocks, &transaction->t_outstanding_credits);
		goto unlock;
	}

@@ -445,6 +447,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
	    jbd2_log_space_left(journal)) {
		jbd_debug(3, "denied handle %p %d blocks: "
			  "insufficient log space\n", handle, nblocks);
		atomic_sub(nblocks, &transaction->t_outstanding_credits);
		goto unlock;
	}

@@ -456,7 +459,6 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)

	handle->h_buffer_credits += nblocks;
	handle->h_requested_credits += nblocks;
	atomic_add(nblocks, &transaction->t_outstanding_credits);
	result = 0;

	jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);