Implement the designed locking around j_checkpoint_transactions.  It was all
pretty much there actually.



 25-akpm/fs/jbd/journal.c |   20 ++++++++++++++++----
 fs/jbd/checkpoint.c      |    0 
 fs/jbd/commit.c          |    0 
 3 files changed, 16 insertions(+), 4 deletions(-)

diff -puN fs/jbd/checkpoint.c~jbd-180-j_checkpoint_transactions fs/jbd/checkpoint.c
diff -puN fs/jbd/commit.c~jbd-180-j_checkpoint_transactions fs/jbd/commit.c
diff -puN fs/jbd/journal.c~jbd-180-j_checkpoint_transactions fs/jbd/journal.c
--- 25/fs/jbd/journal.c~jbd-180-j_checkpoint_transactions	Thu Jun  5 15:14:26 2003
+++ 25-akpm/fs/jbd/journal.c	Thu Jun  5 15:14:26 2003
@@ -1016,11 +1016,11 @@ recovery_error:
 /**
  * void journal_destroy() - Release a journal_t structure.
  * @journal: Journal to act on.
-* 
+ *
  * Release a journal_t structure once it is no longer in use by the
  * journaled object.
  */
-void journal_destroy (journal_t *journal)
+void journal_destroy(journal_t *journal)
 {
 	/* Wait for the commit thread to wake up and die. */
 	journal_kill_thread(journal);
@@ -1031,12 +1031,19 @@ void journal_destroy (journal_t *journal
 
 	/* Force any old transactions to disk */
 	lock_journal(journal);
-	while (journal->j_checkpoint_transactions != NULL)
+
+	/* Totally anal locking here... */
+	spin_lock(&journal->j_list_lock);
+	while (journal->j_checkpoint_transactions != NULL) {
+		spin_unlock(&journal->j_list_lock);
 		log_do_checkpoint(journal, 1);
+		spin_lock(&journal->j_list_lock);
+	}
 
 	J_ASSERT(journal->j_running_transaction == NULL);
 	J_ASSERT(journal->j_committing_transaction == NULL);
 	J_ASSERT(journal->j_checkpoint_transactions == NULL);
+	spin_unlock(&journal->j_list_lock);
 
 	/* We can now mark the journal as empty. */
 	journal->j_tail = 0;
@@ -1237,8 +1244,13 @@ int journal_flush(journal_t *journal)
 
 	/* ...and flush everything in the log out to disk. */
 	lock_journal(journal);
-	while (!err && journal->j_checkpoint_transactions != NULL)
+	spin_lock(&journal->j_list_lock);
+	while (!err && journal->j_checkpoint_transactions != NULL) {
+		spin_unlock(&journal->j_list_lock);
 		err = log_do_checkpoint(journal, journal->j_maxlen);
+		spin_lock(&journal->j_list_lock);
+	}
+	spin_unlock(&journal->j_list_lock);
 	cleanup_journal_tail(journal);
 
 	/* Finally, mark the journal as really needing no recovery.

_