Almost everywhere where JBD removes a buffer from the transaction lists the
caller then nulls out jh->b_transaction.  Sometimes, the caller does that
without holding the locks which are defined to protect b_transaction.  This
makes me queazy.

So change things so that __journal_unfile_buffer() nulls out b_transaction
inside both j_list_lock and jbd_lock_bh_state().

It cleans things up a bit, too.


---

 25-akpm/fs/jbd/commit.c      |   14 ++------------
 25-akpm/fs/jbd/transaction.c |   13 ++++---------
 2 files changed, 6 insertions(+), 21 deletions(-)

diff -puN fs/jbd/commit.c~jbd-b_transaction-zeroing-cleanup fs/jbd/commit.c
--- 25/fs/jbd/commit.c~jbd-b_transaction-zeroing-cleanup	2004-04-05 21:10:45.366713744 -0700
+++ 25-akpm/fs/jbd/commit.c	2004-04-05 21:10:45.371712984 -0700
@@ -259,7 +259,8 @@ write_out_data:
 			if (!inverted_lock(journal, bh))
 				goto write_out_data;
 			__journal_unfile_buffer(jh);
-			__journal_file_buffer(jh, jh->b_transaction, BJ_Locked);
+			__journal_file_buffer(jh, commit_transaction,
+						BJ_Locked);
 			jbd_unlock_bh_state(bh);
 			if (need_resched()) {
 				spin_unlock(&journal->j_list_lock);
@@ -284,7 +285,6 @@ write_out_data:
 				if (!inverted_lock(journal, bh))
 					goto write_out_data;
 				__journal_unfile_buffer(jh);
-				jh->b_transaction = NULL;
 				jbd_unlock_bh_state(bh);
 				journal_remove_journal_head(bh);
 				put_bh(bh);
@@ -326,7 +326,6 @@ write_out_data:
 		}
 		if (buffer_jbd(bh) && jh->b_jlist == BJ_Locked) {
 			__journal_unfile_buffer(jh);
-			jh->b_transaction = NULL;
 			jbd_unlock_bh_state(bh);
 			journal_remove_journal_head(bh);
 			put_bh(bh);
@@ -555,13 +554,6 @@ wait_for_iobuf:
 		journal_unfile_buffer(journal, jh);
 
 		/*
-		 * akpm: don't put back a buffer_head with stale pointers
-		 * dangling around.
-		 */
-		J_ASSERT_JH(jh, jh->b_transaction != NULL);
-		jh->b_transaction = NULL;
-
-		/*
 		 * ->t_iobuf_list should contain only dummy buffer_heads
 		 * which were created by journal_write_metadata_buffer().
 		 */
@@ -613,7 +605,6 @@ wait_for_iobuf:
 		BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile");
 		clear_buffer_jwrite(bh);
 		journal_unfile_buffer(journal, jh);
-		jh->b_transaction = NULL;
 		journal_put_journal_head(jh);
 		__brelse(bh);		/* One for getblk */
 		/* AKPM: bforget here */
@@ -766,7 +757,6 @@ skip_commit: /* The journal should be un
 			J_ASSERT_BH(bh, !buffer_dirty(bh));
 			J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
 			__journal_unfile_buffer(jh);
-			jh->b_transaction = 0;
 			jbd_unlock_bh_state(bh);
 			journal_remove_journal_head(bh);  /* needs a brelse */
 			release_buffer_page(bh);
diff -puN fs/jbd/transaction.c~jbd-b_transaction-zeroing-cleanup fs/jbd/transaction.c
--- 25/fs/jbd/transaction.c~jbd-b_transaction-zeroing-cleanup	2004-04-05 21:10:45.367713592 -0700
+++ 25-akpm/fs/jbd/transaction.c	2004-04-05 21:10:45.373712680 -0700
@@ -1019,7 +1019,6 @@ int journal_dirty_data(handle_t *handle,
 			if (jh->b_transaction != NULL) {
 				JBUFFER_TRACE(jh, "unfile from commit");
 				__journal_unfile_buffer(jh);
-				jh->b_transaction = NULL;
 			}
 			/* The buffer will be refiled below */
 
@@ -1034,7 +1033,6 @@ int journal_dirty_data(handle_t *handle,
 			JBUFFER_TRACE(jh, "not on correct data list: unfile");
 			J_ASSERT_JH(jh, jh->b_jlist != BJ_Shadow);
 			__journal_unfile_buffer(jh);
-			jh->b_transaction = NULL;
 			JBUFFER_TRACE(jh, "file as data");
 			__journal_file_buffer(jh, handle->h_transaction,
 						BJ_SyncData);
@@ -1205,7 +1203,6 @@ void journal_forget(handle_t *handle, st
 		J_ASSERT_JH(jh, !jh->b_committed_data);
 
 		__journal_unfile_buffer(jh);
-		jh->b_transaction = 0;
 
 		/* 
 		 * We are no longer going to journal this buffer.
@@ -1493,7 +1490,7 @@ void __journal_unfile_buffer(struct jour
 
 	switch (jh->b_jlist) {
 	case BJ_None:
-		return;
+		goto out;
 	case BJ_SyncData:
 		list = &transaction->t_sync_datalist;
 		break;
@@ -1526,6 +1523,8 @@ void __journal_unfile_buffer(struct jour
 	jh->b_jlist = BJ_None;
 	if (test_clear_buffer_jbddirty(bh))
 		mark_buffer_dirty(bh);	/* Expose it to the VM */
+out:
+	jh->b_transaction = NULL;
 }
 
 void journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
@@ -1561,7 +1560,6 @@ __journal_try_to_free_buffer(journal_t *
 			/* A written-back ordered data buffer */
 			JBUFFER_TRACE(jh, "release data");
 			__journal_unfile_buffer(jh);
-			jh->b_transaction = 0;
 			journal_remove_journal_head(bh);
 			__brelse(bh);
 		}
@@ -1667,7 +1665,6 @@ static int __dispose_buffer(struct journ
 	struct buffer_head *bh = jh2bh(jh);
 
 	__journal_unfile_buffer(jh);
-	jh->b_transaction = 0;
 
 	if (jh->b_cp_transaction) {
 		JBUFFER_TRACE(jh, "on running+cp transaction");
@@ -1936,8 +1933,7 @@ void __journal_file_buffer(struct journa
 
 	if (jh->b_transaction)
 		__journal_unfile_buffer(jh);
-	else
-		jh->b_transaction = transaction;
+	jh->b_transaction = transaction;
 
 	switch (jlist) {
 	case BJ_None:
@@ -2010,7 +2006,6 @@ void __journal_refile_buffer(struct jour
 	/* If the buffer is now unused, just drop it. */
 	if (jh->b_next_transaction == NULL) {
 		__journal_unfile_buffer(jh);
-		jh->b_transaction = NULL;
 		return;
 	}
 

_