--- /dev/null
+diff -rup linux-2.4.20-uml linux-2.4.21-rc2
+--- linux-2.4.20-uml/fs/jbd/transaction.c Thu Nov 28 16:53:15 2002
++++ linux-2.4.21-rc2/fs/jbd/transaction.c Fri May 16 11:00:40 2003
+@@ -666,7 +673,8 @@ repeat:
+ spin_unlock(&journal_datalist_lock);
+ unlock_journal(journal);
+ /* commit wakes up all shadow buffers after IO */
+- sleep_on(&jh2bh(jh)->b_wait);
++ wait_event(jh2bh(jh)->b_wait,
++ jh->b_jlist != BJ_Shadow);
+ lock_journal(journal);
+ goto repeat;
+ }
--- /dev/null
+diff -rup linux-2.4.20-uml linux-2.4.21-rc2
+--- linux-2.4.20-uml/fs/jbd/transaction.c Thu Nov 28 16:53:15 2002
++++ linux-2.4.21-rc2/fs/jbd/transaction.c Fri May 16 11:00:40 2003
+@@ -1109,7 +1142,6 @@ int journal_dirty_metadata (handle_t *ha
+
+ spin_lock(&journal_datalist_lock);
+ set_bit(BH_JBDDirty, &bh->b_state);
+- set_buffer_flushtime(bh);
+
+ J_ASSERT_JH(jh, jh->b_transaction != NULL);
+
+@@ -2035,6 +2093,13 @@ void journal_file_buffer(struct journal_
+ spin_unlock(&journal_datalist_lock);
+ }
+
++static void jbd_refile_buffer(struct buffer_head *bh)
++{
++ if (buffer_dirty(bh) && (bh->b_list != BUF_DIRTY))
++ set_buffer_flushtime(bh);
++ refile_buffer(bh);
++}
++
+ /*
+ * Remove a buffer from its current buffer list in preparation for
+ * dropping it from its current transaction entirely. If the buffer has
+@@ -2055,7 +2120,7 @@ void __journal_refile_buffer(struct jour
+ __journal_unfile_buffer(jh);
+ jh->b_transaction = NULL;
+ /* Onto BUF_DIRTY for writeback */
+- refile_buffer(jh2bh(jh));
++ jbd_refile_buffer(jh2bh(jh));
+ return;
+ }
+
--- /dev/null
+diff -rup linux-2.4.20-uml linux-2.4.21-rc2
+--- linux-2.4.20-uml/fs/jbd/transaction.c Thu Nov 28 16:53:15 2002
++++ linux-2.4.21-rc2/fs/jbd/transaction.c Fri May 16 11:00:40 2003
+@@ -735,7 +743,8 @@ done_locked:
+ int offset;
+ char *source;
+
+- J_ASSERT_JH(jh, buffer_uptodate(jh2bh(jh)));
++ J_EXPECT_JH(jh, buffer_uptodate(jh2bh(jh)),
++ "Possible IO failure.\n");
+ page = jh2bh(jh)->b_page;
+ offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK;
+ source = kmap(page);
+diff -rup linux-2.4.20-uml linux-2.4.21-rc2
+--- linux-2.4.20-uml/include/linux/jbd.h Mon Aug 25 16:16:57 2003
++++ linux-2.4.21-rc2/include/linux/jbd.h Tue May 13 13:28:29 2003
+@@ -40,6 +40,15 @@
+ */
+ #undef JBD_PARANOID_WRITES
+
++/*
++ * Define JBD_PARANIOD_IOFAIL to cause a kernel BUG() if ext3 finds
++ * certain classes of error which can occur due to failed IOs. Under
++ * normal use we want ext3 to continue after such errors, because
++ * hardware _can_ fail, but for debugging purposes when running tests on
++ * known-good hardware we may want to trap these errors.
++ */
++#undef JBD_PARANOID_IOFAIL
++
+ #ifdef CONFIG_JBD_DEBUG
+ /*
+ * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal
+@@ -232,6 +272,23 @@ void buffer_assertion_failure(struct buf
+ #define J_ASSERT(assert) do { } while (0)
+ #endif /* JBD_ASSERTIONS */
+
++#if defined(JBD_PARANOID_IOFAIL)
++#define J_EXPECT(expr, why...) J_ASSERT(expr)
++#define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr)
++#define J_EXPECT_JH(jh, expr, why...) J_ASSERT_JH(jh, expr)
++#else
++#define __journal_expect(expr, why...) \
++ do { \
++ if (!(expr)) { \
++ printk(KERN_ERR "EXT3-fs unexpected failure: %s;\n", # expr); \
++ printk(KERN_ERR why); \
++ } \
++ } while (0)
++#define J_EXPECT(expr, why...) __journal_expect(expr, ## why)
++#define J_EXPECT_BH(bh, expr, why...) __journal_expect(expr, ## why)
++#define J_EXPECT_JH(jh, expr, why...) __journal_expect(expr, ## why)
++#endif
++
+ enum jbd_state_bits {
+ BH_JWrite
+ = BH_PrivateStart, /* 1 if being written to log (@@@ DEBUGGING) */