Plug a conceivable race with the freeing up of trasnactions, and add some more debug checks. fs/jbd/checkpoint.c | 7 ++++--- fs/jbd/commit.c | 8 +++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff -puN fs/jbd/commit.c~jbd-570-transaction-state-locking fs/jbd/commit.c --- 25/fs/jbd/commit.c~jbd-570-transaction-state-locking 2003-05-27 23:58:34.000000000 -0700 +++ 25-akpm/fs/jbd/commit.c 2003-05-27 23:58:34.000000000 -0700 @@ -704,14 +704,20 @@ skip_commit: /* The journal should be un J_ASSERT(commit_transaction->t_state == T_COMMIT); + /* + * This is a bit sleazy. We borrow j_list_lock to protect + * journal->j_committing_transaction in __journal_remove_checkpoint. + * Really, __jornal_remove_checkpoint should be using j_state_lock but + * it's a bit hassle to hold that across __journal_remove_checkpoint + */ spin_lock(&journal->j_state_lock); + spin_lock(&journal->j_list_lock); commit_transaction->t_state = T_FINISHED; J_ASSERT(commit_transaction == journal->j_committing_transaction); journal->j_commit_sequence = commit_transaction->t_tid; journal->j_committing_transaction = NULL; spin_unlock(&journal->j_state_lock); - spin_lock(&journal->j_list_lock); if (commit_transaction->t_checkpoint_list == NULL) { __journal_drop_transaction(journal, commit_transaction); } else { diff -puN fs/jbd/checkpoint.c~jbd-570-transaction-state-locking fs/jbd/checkpoint.c --- 25/fs/jbd/checkpoint.c~jbd-570-transaction-state-locking 2003-05-27 23:58:34.000000000 -0700 +++ 25-akpm/fs/jbd/checkpoint.c 2003-05-27 23:58:34.000000000 -0700 @@ -538,7 +538,8 @@ void __journal_remove_checkpoint(struct * checkpoint list is empty, the transaction obviously cannot be * dropped! * - * AKPM2: locking here around j_committing_transaction is a bit flakey. + * The locking here around j_committing_transaction is a bit sleazy. + * See the comment at the end of journal_commit_transaction(). */ if (transaction == journal->j_committing_transaction) { JBUFFER_TRACE(jh, "belongs to committing transaction"); @@ -608,6 +609,7 @@ void __journal_drop_transaction(journal_ journal->j_checkpoint_transactions = NULL; } + J_ASSERT(transaction->t_state == T_FINISHED); J_ASSERT(transaction->t_buffers == NULL); J_ASSERT(transaction->t_sync_datalist == NULL); J_ASSERT(transaction->t_forget == NULL); @@ -617,10 +619,9 @@ void __journal_drop_transaction(journal_ J_ASSERT(transaction->t_checkpoint_list == NULL); J_ASSERT(transaction->t_updates == 0); J_ASSERT(list_empty(&transaction->t_jcb)); - J_ASSERT(journal->j_committing_transaction != transaction); + J_ASSERT(journal->j_running_transaction != transaction); jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid); kfree(transaction); } - _