diff -urpN --exclude-from=/home/davej/.exclude bk-linus/fs/jbd/checkpoint.c linux-2.5/fs/jbd/checkpoint.c
--- bk-linus/fs/jbd/checkpoint.c	2002-11-21 02:20:15.000000000 +0000
+++ linux-2.5/fs/jbd/checkpoint.c	2002-11-21 18:02:15.000000000 +0000
@@ -443,11 +443,8 @@ int __journal_clean_checkpoint_list(jour
 			struct journal_head *last_jh = jh->b_cpprev;
 			struct journal_head *next_jh = jh;
 			do {
-				struct buffer_head *bh;
-
 				jh = next_jh;
 				next_jh = jh->b_cpnext;
-				bh = jh2bh(jh);
 				ret += __try_to_free_cp_buf(jh);
 			} while (jh != last_jh);
 		}
diff -urpN --exclude-from=/home/davej/.exclude bk-linus/fs/jbd/commit.c linux-2.5/fs/jbd/commit.c
--- bk-linus/fs/jbd/commit.c	2002-11-21 02:20:15.000000000 +0000
+++ linux-2.5/fs/jbd/commit.c	2002-11-21 18:02:15.000000000 +0000
@@ -25,7 +25,7 @@ extern spinlock_t journal_datalist_lock;
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
  */
-static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
+void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
 {
 	BUFFER_TRACE(bh, "");
 	if (uptodate)
@@ -406,6 +406,7 @@ sync_datalist_empty:
 		flags = journal_write_metadata_buffer(commit_transaction,
 						      jh, &new_jh, blocknr);
 		set_bit(BH_JWrite, &jh2bh(new_jh)->b_state);
+		set_bit(BH_Lock, &jh2bh(new_jh)->b_state);
 		wbuf[bufs++] = jh2bh(new_jh);
 
 		/* Record the new block's tag in the current descriptor
@@ -557,8 +558,7 @@ start_journal_io:
 		journal_unfile_buffer(jh);
 		jh->b_transaction = NULL;
 		journal_unlock_journal_head(jh);
-		__brelse(bh);		/* One for getblk */
-		/* AKPM: bforget here */
+		put_bh(bh);			/* One for getblk */
 	}
 
 	jbd_debug(3, "JBD: commit phase 6\n");
@@ -594,9 +594,10 @@ start_journal_io:
 	{
 		struct buffer_head *bh = jh2bh(descriptor);
 		set_buffer_uptodate(bh);
-		ll_rw_block(WRITE, 1, &bh);
+		bh->b_end_io = journal_end_buffer_io_sync;
+		submit_bh(WRITE, bh);
 		wait_on_buffer(bh);
-		__brelse(bh);		/* One for getblk() */
+		put_bh(bh);		/* One for getblk() */
 		journal_unlock_journal_head(descriptor);
 	}
 
diff -urpN --exclude-from=/home/davej/.exclude bk-linus/fs/jbd/journal.c linux-2.5/fs/jbd/journal.c
--- bk-linus/fs/jbd/journal.c	2002-11-21 02:20:15.000000000 +0000
+++ linux-2.5/fs/jbd/journal.c	2002-11-21 18:02:16.000000000 +0000
@@ -661,6 +661,8 @@ int journal_bmap(journal_t *journal, uns
  * We play buffer_head aliasing tricks to write data/metadata blocks to
  * the journal without copying their contents, but for journal
  * descriptor blocks we do need to generate bona fide buffers.
+ *
+ * We return a jh whose bh is locked and ready to be populated.
  */
 
 struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
@@ -675,7 +677,7 @@ struct journal_head * journal_get_descri
 		return NULL;
 
 	bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
-	bh->b_state |= (1 << BH_Dirty);
+	lock_buffer(bh);
 	BUFFER_TRACE(bh, "return this buffer");
 	return journal_add_journal_head(bh);
 }
diff -urpN --exclude-from=/home/davej/.exclude bk-linus/fs/jbd/revoke.c linux-2.5/fs/jbd/revoke.c
--- bk-linus/fs/jbd/revoke.c	2002-11-21 02:20:16.000000000 +0000
+++ linux-2.5/fs/jbd/revoke.c	2002-11-21 18:02:16.000000000 +0000
@@ -530,6 +530,7 @@ static void flush_descriptor(journal_t *
 
 	if (is_journal_aborted(journal)) {
 		JBUFFER_TRACE(descriptor, "brelse");
+		unlock_buffer(jh2bh(descriptor));
 		__brelse(jh2bh(descriptor));
 		return;
 	}
@@ -541,7 +542,8 @@ static void flush_descriptor(journal_t *
 		struct buffer_head *bh = jh2bh(descriptor);
 		BUFFER_TRACE(bh, "write");
 		set_buffer_uptodate(bh);
-		ll_rw_block (WRITE, 1, &bh);
+		bh->b_end_io = journal_end_buffer_io_sync;
+		submit_bh(WRITE, bh);
 	}
 }
 
diff -urpN --exclude-from=/home/davej/.exclude bk-linus/fs/jbd/transaction.c linux-2.5/fs/jbd/transaction.c
--- bk-linus/fs/jbd/transaction.c	2002-11-21 02:20:16.000000000 +0000
+++ linux-2.5/fs/jbd/transaction.c	2002-11-21 18:02:16.000000000 +0000
@@ -105,6 +105,8 @@ repeat:
 
 	lock_journal(journal);
 
+repeat_locked:
+
 	if (is_journal_aborted(journal) ||
 	    (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) {
 		unlock_journal(journal);
@@ -118,7 +120,6 @@ repeat:
 		goto repeat;
 	}
 	
-repeat_locked:
 	if (!journal->j_running_transaction)
 		get_transaction(journal, 0);
 	/* @@@ Error? */
diff -urpN --exclude-from=/home/davej/.exclude bk-linus/include/linux/jbd.h linux-2.5/include/linux/jbd.h
--- bk-linus/include/linux/jbd.h	2002-11-21 02:23:56.000000000 +0000
+++ linux-2.5/include/linux/jbd.h	2002-11-21 18:04:46.000000000 +0000
@@ -585,6 +585,7 @@ extern struct journal_head * journal_get
 int journal_next_log_block(journal_t *, unsigned long *);
 
 /* Commit management */
+void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate);
 extern void journal_commit_transaction(journal_t *);
 
 /* Checkpoint list management */
@@ -822,8 +823,6 @@ extern int journal_blocks_per_page(struc
 #define BJ_Reserved	8	/* Buffer is reserved for access by journal */
 #define BJ_Types	9
  
-extern int jbd_blocks_per_page(struct inode *inode);
-
 #ifdef __KERNEL__
 
 extern spinlock_t jh_splice_lock;