

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-06-04 01:58:40.000000000 -0700
+++ 25-akpm/fs/jbd/commit.c	2003-06-04 01:58:40.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-06-04 01:58:40.000000000 -0700
+++ 25-akpm/fs/jbd/checkpoint.c	2003-06-04 01:58:40.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);
 }
-

_
