From: Chris Mason Sometimes barriers fail asynchronously (after the submit_bh call). This patch changes both ext3 and reiserfs to handle that without mistaking the barrier failures for io errors. Signed-off-by: Andrew Morton --- 25-akpm/fs/jbd/commit.c | 13 +++++++++++-- 25-akpm/fs/reiserfs/journal.c | 13 +++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff -puN fs/jbd/commit.c~handle-async-barrier-failures fs/jbd/commit.c --- 25/fs/jbd/commit.c~handle-async-barrier-failures Thu Jun 10 13:38:30 2004 +++ 25-akpm/fs/jbd/commit.c Thu Jun 10 13:38:30 2004 @@ -640,12 +640,20 @@ wait_for_iobuf: { struct buffer_head *bh = jh2bh(descriptor); int ret; + int barrier_done = 0; set_buffer_dirty(bh); - if (journal->j_flags & JFS_BARRIER) + if (journal->j_flags & JFS_BARRIER) { set_buffer_ordered(bh); + barrier_done = 1; + } ret = sync_dirty_buffer(bh); - if (ret == -EOPNOTSUPP && (journal->j_flags & JFS_BARRIER)) { + /* is it possible for another commit to fail at roughly + * the same time as this one? If so, we don't want to + * trust the barrier flag in the super, but instead want + * to remember if we sent a barrier request + */ + if (ret == -EOPNOTSUPP && barrier_done) { char b[BDEVNAME_SIZE]; printk(KERN_WARNING @@ -658,6 +666,7 @@ wait_for_iobuf: /* And try again, without the barrier */ clear_buffer_ordered(bh); + set_buffer_uptodate(bh); set_buffer_dirty(bh); ret = sync_dirty_buffer(bh); } diff -puN fs/reiserfs/journal.c~handle-async-barrier-failures fs/reiserfs/journal.c --- 25/fs/reiserfs/journal.c~handle-async-barrier-failures Thu Jun 10 13:38:30 2004 +++ 25-akpm/fs/reiserfs/journal.c Thu Jun 10 13:38:30 2004 @@ -655,6 +655,17 @@ static int submit_barrier_buffer(struct return submit_bh(WRITE_BARRIER, bh) ; } +static void check_barrier_completion(struct super_block *s, + struct buffer_head *bh) { + if (buffer_eopnotsupp(bh)) { + clear_buffer_eopnotsupp(bh); + disable_barrier(s); + set_buffer_uptodate(bh); + set_buffer_dirty(bh); + sync_dirty_buffer(bh); + } +} + #define CHUNK_SIZE 32 struct buffer_chunk { struct buffer_head *bh[CHUNK_SIZE]; @@ -1032,6 +1043,7 @@ static int flush_commit_list(struct supe } else wait_on_buffer(jl->j_commit_bh); + check_barrier_completion(s, jl->j_commit_bh); if (!buffer_uptodate(jl->j_commit_bh)) { reiserfs_panic(s, "journal-615: buffer write failed\n") ; } @@ -1142,6 +1154,7 @@ static int _update_journal_header_block( goto sync; } wait_on_buffer(SB_JOURNAL(p_s_sb)->j_header_bh); + check_barrier_completion(p_s_sb, SB_JOURNAL(p_s_sb)->j_header_bh); } else { sync: set_buffer_dirty(SB_JOURNAL(p_s_sb)->j_header_bh) ; _