diff -ruN linux-2.4.20/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.20/fs/buffer.c	Fri Jan 10 16:35:24 2003
+++ linux/fs/buffer.c	Wed Mar 26 12:53:19 2003
@@ -586,9 +586,10 @@
 void buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode)
 {
 	spin_lock(&lru_list_lock);
-	if (bh->b_inode)
+	if (buffer_inode(bh))
 		list_del(&bh->b_inode_buffers);
-	bh->b_inode = inode;
+	else
+		set_buffer_inode(bh);
 	list_add(&bh->b_inode_buffers, &inode->i_dirty_buffers);
 	spin_unlock(&lru_list_lock);
 }
@@ -596,9 +597,10 @@
 void buffer_insert_inode_data_queue(struct buffer_head *bh, struct inode *inode)
 {
 	spin_lock(&lru_list_lock);
-	if (bh->b_inode)
+	if (buffer_inode(bh))
 		list_del(&bh->b_inode_buffers);
-	bh->b_inode = inode;
+	else
+		set_buffer_inode(bh);
 	list_add(&bh->b_inode_buffers, &inode->i_dirty_data_buffers);
 	spin_unlock(&lru_list_lock);
 }
@@ -607,13 +609,13 @@
    remove_inode_queue functions.  */
 static void __remove_inode_queue(struct buffer_head *bh)
 {
-	bh->b_inode = NULL;
+	clear_buffer_inode(bh);
 	list_del(&bh->b_inode_buffers);
 }
 
 static inline void remove_inode_queue(struct buffer_head *bh)
 {
-	if (bh->b_inode)
+	if (buffer_inode(bh))
 		__remove_inode_queue(bh);
 }
 
@@ -741,6 +743,7 @@
 	bh->b_list = BUF_CLEAN;
 	bh->b_end_io = handler;
 	bh->b_private = private;
+	bh->b_journal_head = NULL;
 }
 
 static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
@@ -842,9 +845,9 @@
 		bh = BH_ENTRY(list->next);
 		list_del(&bh->b_inode_buffers);
 		if (!buffer_dirty(bh) && !buffer_locked(bh))
-			bh->b_inode = NULL;
+			clear_buffer_inode(bh);
 		else {
-			bh->b_inode = &tmp;
+			set_buffer_inode(bh);
 			list_add(&bh->b_inode_buffers, &tmp.i_dirty_buffers);
 			if (buffer_dirty(bh)) {
 				get_bh(bh);
@@ -1138,7 +1141,7 @@
  */
 static void __put_unused_buffer_head(struct buffer_head * bh)
 {
-	if (bh->b_inode)
+	if (buffer_inode(bh))
 		BUG();
 	if (nr_unused_buffer_heads >= MAX_UNUSED_BUFFERS) {
 		kmem_cache_free(bh_cachep, bh);
diff -ruN linux-2.4.20/fs/jbd/journal.c linux/fs/jbd/journal.c
--- linux-2.4.20/fs/jbd/journal.c	Fri Jan 10 16:35:27 2003
+++ linux/fs/jbd/journal.c	Wed Mar 26 12:53:19 2003
@@ -1664,8 +1664,8 @@
  *
  * Whenever a buffer has an attached journal_head, its ->b_state:BH_JBD bit
  * is set.  This bit is tested in core kernel code where we need to take
- * JBD-specific actions.  Testing the zeroness of ->b_private is not reliable
- * there.
+ * JBD-specific actions.  Testing the zeroness of ->b_journal_head is not
+ * reliable there.
  *
  * When a buffer has its BH_JBD bit set, its ->b_count is elevated by one.
  *
@@ -1720,9 +1720,9 @@
 
 		if (buffer_jbd(bh)) {
 			/* Someone did it for us! */
-			J_ASSERT_BH(bh, bh->b_private != NULL);
+			J_ASSERT_BH(bh, bh->b_journal_head != NULL);
 			journal_free_journal_head(jh);
-			jh = bh->b_private;
+			jh = bh->b_journal_head;
 		} else {
 			/*
 			 * We actually don't need jh_splice_lock when
@@ -1730,7 +1730,7 @@
 			 */
 			spin_lock(&jh_splice_lock);
 			set_bit(BH_JBD, &bh->b_state);
-			bh->b_private = jh;
+			bh->b_journal_head = jh;
 			jh->b_bh = bh;
 			atomic_inc(&bh->b_count);
 			spin_unlock(&jh_splice_lock);
@@ -1739,7 +1739,7 @@
 	}
 	jh->b_jcount++;
 	spin_unlock(&journal_datalist_lock);
-	return bh->b_private;
+	return bh->b_journal_head;
 }
 
 /*
@@ -1772,7 +1772,7 @@
 			J_ASSERT_BH(bh, jh2bh(jh) == bh);
 			BUFFER_TRACE(bh, "remove journal_head");
 			spin_lock(&jh_splice_lock);
-			bh->b_private = NULL;
+			bh->b_journal_head = NULL;
 			jh->b_bh = NULL;	/* debug, really */
 			clear_bit(BH_JBD, &bh->b_state);
 			__brelse(bh);
diff -ruN linux-2.4.20/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.4.20/include/linux/fs.h	Fri Jan 10 16:35:55 2003
+++ linux/include/linux/fs.h	Wed Mar 26 12:53:19 2003
@@ -220,6 +220,7 @@
 	BH_Wait_IO,	/* 1 if we should write out this buffer */
 	BH_Launder,	/* 1 if we can throttle on this buffer */
 	BH_JBD,		/* 1 if it has an attached journal_head */
+	BH_Inode,	/* 1 if it is attached to i_dirty[_data]_buffers */
 
 	BH_PrivateStart,/* not a state bit, but the first bit available
 			 * for private allocation by other entities
@@ -262,11 +263,10 @@
 	struct page *b_page;		/* the page this bh is mapped to */
 	void (*b_end_io)(struct buffer_head *bh, int uptodate); /* I/O completion */
  	void *b_private;		/* reserved for b_end_io */
-
+ 	void *b_journal_head;		/* ext3 journal_heads */
 	unsigned long b_rsector;	/* Real buffer location on disk */
 	wait_queue_head_t b_wait;
 
-	struct inode *	     b_inode;
 	struct list_head     b_inode_buffers;	/* doubly linked list of inode dirty buffers */
 };
 
@@ -1184,6 +1184,21 @@
 		set_bit(BH_Async, &bh->b_state);
 	else
 		clear_bit(BH_Async, &bh->b_state);
+}
+
+static inline void set_buffer_inode(struct buffer_head *bh)
+{
+	set_bit(BH_Inode, &bh->b_state);
+}
+
+static inline void clear_buffer_inode(struct buffer_head *bh)
+{
+	clear_bit(BH_Inode, &bh->b_state);
+}
+
+static inline int buffer_inode(struct buffer_head *bh)
+{
+	return test_bit(BH_Inode, &bh->b_state);
 }
 
 /*
diff -ruN linux-2.4.20/include/linux/jbd.h linux/include/linux/jbd.h
--- linux-2.4.20/include/linux/jbd.h	Fri Jan 10 16:35:55 2003
+++ linux/include/linux/jbd.h	Wed Mar 26 12:53:19 2003
@@ -254,7 +254,7 @@
 
 static inline struct journal_head *bh2jh(struct buffer_head *bh)
 {
-	return bh->b_private;
+	return bh->b_journal_head;
 }
 
 #define HAVE_JOURNAL_CALLBACK_STATUS