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-09 21:04:43.737503784 -0700 +++ 25-akpm/fs/jbd/commit.c 2004-04-09 21:04:43.744502720 -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-09 21:04:43.739503480 -0700 +++ 25-akpm/fs/jbd/transaction.c 2004-04-09 21:04:43.894479920 -0700 @@ -1038,7 +1038,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 */ @@ -1053,7 +1052,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); @@ -1228,7 +1226,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. @@ -1516,7 +1513,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; @@ -1549,6 +1546,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) @@ -1584,7 +1583,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); } @@ -1690,7 +1688,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"); @@ -1959,8 +1956,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: @@ -2033,7 +2029,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; } _