Skip to content

Commit d7961c7

Browse files
jankaratytso
authored andcommitted
jbd2: fix assertion failure in jbd2_journal_flush()
The following race is possible between start_this_handle() and someone calling jbd2_journal_flush(). Process A Process B start_this_handle(). if (journal->j_barrier_count) # false if (!journal->j_running_transaction) { #true read_unlock(&journal->j_state_lock); jbd2_journal_lock_updates() jbd2_journal_flush() write_lock(&journal->j_state_lock); if (journal->j_running_transaction) { # false ... wait for committing trans ... write_unlock(&journal->j_state_lock); ... write_lock(&journal->j_state_lock); if (!journal->j_running_transaction) { # true jbd2_get_transaction(journal, new_transaction); write_unlock(&journal->j_state_lock); goto repeat; # eventually blocks on j_barrier_count > 0 ... J_ASSERT(!journal->j_running_transaction); # fails We fix the race by rechecking j_barrier_count after reacquiring j_state_lock in exclusive mode. Reported-by: [email protected] Signed-off-by: Jan Kara <[email protected]> Signed-off-by: "Theodore Ts'o" <[email protected]> Cc: [email protected]
1 parent 261cb20 commit d7961c7

File tree

1 file changed

+2
-1
lines changed

1 file changed

+2
-1
lines changed

fs/jbd2/transaction.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
209209
if (!new_transaction)
210210
goto alloc_transaction;
211211
write_lock(&journal->j_state_lock);
212-
if (!journal->j_running_transaction) {
212+
if (!journal->j_running_transaction &&
213+
!journal->j_barrier_count) {
213214
jbd2_get_transaction(journal, new_transaction);
214215
new_transaction = NULL;
215216
}

0 commit comments

Comments
 (0)