In start_this_handle() the caller does not have a handle ref pinning the transaction open, and so the call to log_start_commit() is racy because some other CPU could take the transaction into commit state independently. Fix that by holding j_state_lock (which pins j_running_transaction) across the log_start_commit() call. 25-akpm/fs/jbd/journal.c | 2 +- 25-akpm/fs/jbd/transaction.c | 6 +++--- 25-akpm/include/linux/jbd.h | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff -puN fs/jbd/transaction.c~jbd-580-log_start_commit-race-fix fs/jbd/transaction.c --- 25/fs/jbd/transaction.c~jbd-580-log_start_commit-race-fix Thu May 29 17:05:07 2003 +++ 25-akpm/fs/jbd/transaction.c Thu May 29 17:05:07 2003 @@ -171,12 +171,12 @@ repeat: */ DEFINE_WAIT(wait); - spin_unlock(&transaction->t_handle_lock); - spin_unlock(&journal->j_state_lock); jbd_debug(2, "Handle %p starting new commit...\n", handle); + spin_unlock(&transaction->t_handle_lock); prepare_to_wait(&journal->j_wait_transaction_locked, &wait, TASK_UNINTERRUPTIBLE); - log_start_commit(journal, transaction); + __log_start_commit(journal, transaction); + spin_unlock(&journal->j_state_lock); schedule(); finish_wait(&journal->j_wait_transaction_locked, &wait); goto repeat; diff -puN fs/jbd/journal.c~jbd-580-log_start_commit-race-fix fs/jbd/journal.c --- 25/fs/jbd/journal.c~jbd-580-log_start_commit-race-fix Thu May 29 17:05:07 2003 +++ 25-akpm/fs/jbd/journal.c Thu May 29 17:05:21 2003 @@ -442,7 +442,7 @@ int __log_space_left(journal_t *journal) /* * Called under j_state_lock. */ -static tid_t __log_start_commit(journal_t *journal, transaction_t *transaction) +tid_t __log_start_commit(journal_t *journal, transaction_t *transaction) { tid_t target = journal->j_commit_request; diff -puN include/linux/jbd.h~jbd-580-log_start_commit-race-fix include/linux/jbd.h --- 25/include/linux/jbd.h~jbd-580-log_start_commit-race-fix Thu May 29 17:05:07 2003 +++ 25-akpm/include/linux/jbd.h Thu May 29 17:05:07 2003 @@ -991,6 +991,7 @@ extern void journal_switch_revoke_table( int __log_space_left(journal_t *); /* Called with journal locked */ extern tid_t log_start_commit (journal_t *, transaction_t *); +extern tid_t __log_start_commit(journal_t *, transaction_t *); extern int log_wait_commit (journal_t *, tid_t); extern int log_do_checkpoint (journal_t *, int); _