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: Zheng Liu <wenqing.lz@taobao.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
@@ -433,11 +433,13 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&transaction->t_handle_lock);
|
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) {
|
if (wanted > journal->j_max_transaction_buffers) {
|
||||||
jbd_debug(3, "denied handle %p %d blocks: "
|
jbd_debug(3, "denied handle %p %d blocks: "
|
||||||
"transaction too large\n", handle, nblocks);
|
"transaction too large\n", handle, nblocks);
|
||||||
|
atomic_sub(nblocks, &transaction->t_outstanding_credits);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,6 +447,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
|
|||||||
jbd2_log_space_left(journal)) {
|
jbd2_log_space_left(journal)) {
|
||||||
jbd_debug(3, "denied handle %p %d blocks: "
|
jbd_debug(3, "denied handle %p %d blocks: "
|
||||||
"insufficient log space\n", handle, nblocks);
|
"insufficient log space\n", handle, nblocks);
|
||||||
|
atomic_sub(nblocks, &transaction->t_outstanding_credits);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +459,6 @@ int jbd2_journal_extend(handle_t *handle, int nblocks)
|
|||||||
|
|
||||||
handle->h_buffer_credits += nblocks;
|
handle->h_buffer_credits += nblocks;
|
||||||
handle->h_requested_credits += nblocks;
|
handle->h_requested_credits += nblocks;
|
||||||
atomic_add(nblocks, &transaction->t_outstanding_credits);
|
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
||||||
jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);
|
jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);
|
||||||
|
Reference in New Issue
Block a user