diff -urN 2.3.36pre5/fs/ext2/fsync.c 2.3.36pre5-ext2/fs/ext2/fsync.c --- 2.3.36pre5/fs/ext2/fsync.c Wed Dec 8 00:05:27 1999 +++ 2.3.36pre5-ext2/fs/ext2/fsync.c Tue Jan 4 17:39:51 2000 @@ -23,6 +23,7 @@ */ #include +#include @@ -40,10 +41,21 @@ if (!bh) return 0; if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { - brelse(bh); - return -1; + /* There can be a parallell read(2) that started read-I/O + on the buffer so we can't assume that there's been + an I/O error without first waiting I/O completation. */ + wait_on_buffer(bh); + if (!buffer_uptodate(bh)) + { + brelse (bh); + return -1; + } } if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { + if (wait) + /* when we return from fsync all the blocks + must be _just_ stored on disk */ + wait_on_buffer(bh); brelse(bh); return 0; } diff -urN 2.3.36pre5/fs/ext2/inode.c 2.3.36pre5-ext2/fs/ext2/inode.c --- 2.3.36pre5/fs/ext2/inode.c Tue Dec 14 15:48:51 1999 +++ 2.3.36pre5-ext2/fs/ext2/inode.c Tue Jan 4 17:31:28 2000 @@ -254,6 +254,8 @@ } if (metadata) { result = getblk (inode->i_dev, tmp, blocksize); + if (!buffer_uptodate(result)) + wait_on_buffer(result); memset(result->b_data, 0, blocksize); mark_buffer_uptodate(result, 1); mark_buffer_dirty(result, 1); @@ -363,6 +365,8 @@ goto out; if (metadata) { result = getblk (bh->b_dev, tmp, blocksize); + if (!buffer_uptodate(result)) + wait_on_buffer(result); memset(result->b_data, 0, inode->i_sb->s_blocksize); mark_buffer_uptodate(result, 1); mark_buffer_dirty(result, 1); @@ -542,6 +546,8 @@ struct buffer_head *bh; bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); if (buffer_new(&dummy)) { + if (!buffer_uptodate(bh)) + wait_on_buffer(bh); memset(bh->b_data, 0, inode->i_sb->s_blocksize); mark_buffer_uptodate(bh, 1); mark_buffer_dirty(bh, 1);