

Before taking the highly-taken j_list_lock, take a peek to seem if this
buffer is already journalled and in the appropriate state.



 25-akpm/fs/jbd/transaction.c |   21 +++++++++++++++++++--
 1 files changed, 19 insertions(+), 2 deletions(-)

diff -puN fs/jbd/transaction.c~jbd-600-journal_dirty_metadata-speedup fs/jbd/transaction.c
--- 25/fs/jbd/transaction.c~jbd-600-journal_dirty_metadata-speedup	Thu Jun  5 15:14:46 2003
+++ 25-akpm/fs/jbd/transaction.c	Thu Jun  5 15:14:46 2003
@@ -1100,6 +1100,22 @@ int journal_dirty_metadata(handle_t *han
 		goto out;
 	
 	jbd_lock_bh_state(bh);
+
+	/*
+	 * fastpath, to avoid expensive locking.  If this buffer is already
+	 * on the running transaction's metadata list there is nothing to do.
+	 * Nobody can take it off again because there is a handle open.
+	 * I _think_ we're OK here with SMP barriers - a mistaken decision will
+	 * result in this test being false, so we go in and take the locks.
+	 */
+	if (jh->b_transaction == handle->h_transaction &&
+					jh->b_jlist == BJ_Metadata) {
+		JBUFFER_TRACE(jh, "fastpath");
+		J_ASSERT_JH(jh, jh->b_transaction ==
+					journal->j_running_transaction);
+		goto out_unlock_bh;
+	}
+
 	spin_lock(&journal->j_list_lock);
 	set_buffer_jbddirty(bh);
 
@@ -1120,7 +1136,7 @@ int journal_dirty_metadata(handle_t *han
 		/* And this case is illegal: we can't reuse another
 		 * transaction's data buffer, ever. */
 		/* FIXME: writepage() should be journalled */
-		goto done_locked;
+		goto out_unlock_list;
 	}
 
 	/* That test should have eliminated the following case: */
@@ -1129,8 +1145,9 @@ int journal_dirty_metadata(handle_t *han
 	JBUFFER_TRACE(jh, "file as BJ_Metadata");
 	__journal_file_buffer(jh, handle->h_transaction, BJ_Metadata);
 
-done_locked:
+out_unlock_list:
 	spin_unlock(&journal->j_list_lock);
+out_unlock_bh:
 	jbd_unlock_bh_state(bh);
 out:
 	JBUFFER_TRACE(jh, "exit");

_
