Processes can sleep in do_get_write_access(), waiting for buffers to be removed from the BJ_Shadow state. We did this by doing a wake_up_buffer() in the commit path and sleeping on the buffer in do_get_write_access(). With the filtered bit-level wakeup code this doesn't work properly any more - the wake_up_buffer() accidentally wakes up tasks which are sleeping in lock_buffer() as well. Those tasks now implicitly assume that the buffer came unlocked. Net effect: Bogus I/O errors when reading journal blocks, because the buffer isn't up to date yet. Hence the recently spate of journal_bmap() failure reports. The patch creates a new jbd-private BH flag purely for this wakeup function. So a wake_up_bit(..., BH_Unshadow) doesn't wake up someone who is waiting for a wake_up_bit(BH_Lock). JBD was the only user of wake_up_buffer(), so remove it altogether. Signed-off-by: Andrew Morton --- 25-akpm/fs/buffer.c | 11 ++--------- 25-akpm/fs/jbd/commit.c | 2 +- 25-akpm/fs/jbd/transaction.c | 7 ++++--- 25-akpm/include/linux/buffer_head.h | 1 - 25-akpm/include/linux/jbd.h | 1 + 5 files changed, 8 insertions(+), 14 deletions(-) diff -puN fs/jbd/commit.c~jbd-wakeup-fix fs/jbd/commit.c --- 25/fs/jbd/commit.c~jbd-wakeup-fix Mon Sep 20 15:38:55 2004 +++ 25-akpm/fs/jbd/commit.c Mon Sep 20 15:38:55 2004 @@ -577,7 +577,7 @@ wait_for_iobuf: journal_file_buffer(jh, commit_transaction, BJ_Forget); /* Wake up any transactions which were waiting for this IO to complete */ - wake_up_buffer(bh); + wake_up_bit(&bh->b_state, BH_Unshadow); JBUFFER_TRACE(jh, "brelse shadowed buffer"); __brelse(bh); } diff -puN fs/jbd/transaction.c~jbd-wakeup-fix fs/jbd/transaction.c --- 25/fs/jbd/transaction.c~jbd-wakeup-fix Mon Sep 20 15:38:55 2004 +++ 25-akpm/fs/jbd/transaction.c Mon Sep 20 15:38:55 2004 @@ -633,9 +633,10 @@ repeat: * disk then we cannot do copy-out here. */ if (jh->b_jlist == BJ_Shadow) { - DEFINE_WAIT_BIT(wait, &bh->b_state, BH_Lock); - wait_queue_head_t *wqh - = bit_waitqueue(&bh->b_state, BH_Lock); + DEFINE_WAIT_BIT(wait, &bh->b_state, BH_Unshadow); + wait_queue_head_t *wqh; + + wqh = bit_waitqueue(&bh->b_state, BH_Unshadow); JBUFFER_TRACE(jh, "on shadow: sleep"); jbd_unlock_bh_state(bh); diff -puN include/linux/jbd.h~jbd-wakeup-fix include/linux/jbd.h --- 25/include/linux/jbd.h~jbd-wakeup-fix Mon Sep 20 15:38:55 2004 +++ 25-akpm/include/linux/jbd.h Mon Sep 20 15:38:55 2004 @@ -299,6 +299,7 @@ enum jbd_state_bits { BH_JBDDirty, /* Is dirty but journaled */ BH_State, /* Pins most journal_head state */ BH_JournalHead, /* Pins bh->b_private and jh->b_bh */ + BH_Unshadow, /* Dummy bit, for BJ_Shadow wakeup filtering */ }; BUFFER_FNS(JBD, jbd) diff -puN include/linux/buffer_head.h~jbd-wakeup-fix include/linux/buffer_head.h --- 25/include/linux/buffer_head.h~jbd-wakeup-fix Mon Sep 20 15:38:55 2004 +++ 25-akpm/include/linux/buffer_head.h Mon Sep 20 15:38:55 2004 @@ -155,7 +155,6 @@ void invalidate_bdev(struct block_device int sync_blockdev(struct block_device *bdev); void __wait_on_buffer(struct buffer_head *); wait_queue_head_t *bh_waitq_head(struct buffer_head *bh); -void wake_up_buffer(struct buffer_head *bh); int fsync_bdev(struct block_device *); struct super_block *freeze_bdev(struct block_device *); void thaw_bdev(struct block_device *, struct super_block *); diff -puN fs/buffer.c~jbd-wakeup-fix fs/buffer.c --- 25/fs/buffer.c~jbd-wakeup-fix Mon Sep 20 15:38:55 2004 +++ 25-akpm/fs/buffer.c Mon Sep 20 15:39:24 2004 @@ -52,13 +52,6 @@ init_buffer(struct buffer_head *bh, bh_e bh->b_private = private; } -void wake_up_buffer(struct buffer_head *bh) -{ - smp_mb(); - wake_up_bit(&bh->b_state, BH_Lock); -} -EXPORT_SYMBOL(wake_up_buffer); - static int sync_buffer(void *word) { struct block_device *bd; @@ -83,8 +76,8 @@ EXPORT_SYMBOL(__lock_buffer); void fastcall unlock_buffer(struct buffer_head *bh) { clear_buffer_locked(bh); - smp_mb__after_clear_bit(); - wake_up_buffer(bh); + smp_mb(); + wake_up_bit(&bh->b_state, BH_Lock); } /* _