Skip to content

Commit

Permalink
jbd2: fix race in t_outstanding_credits update in jbd2_journal_extend()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jan Kara authored and Theodore Ts'o committed Jun 4, 2013
1 parent 76c3990 commit fe1e8db
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions fs/jbd2/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,18 +433,21 @@ 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;
}

if (wanted + (wanted >> JBD2_CONTROL_BLOCKS_SHIFT) >
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;
}

Expand All @@ -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);
Expand Down

0 comments on commit fe1e8db

Please sign in to comment.