From: Alex Tomas ext3_getblk() memsets a newly allocated buffer, but forgets to check whether a different thread brought it uptodate while we waited for the buffer lock. It's OK normally because we're serialised by the page lock. But lustre apparently is doing something different with getblk and hits this race. Plus I suspect it's racy with competing O_DIRECT writes. fs/ext3/inode.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff -puN fs/ext3/inode.c~ext3_getblk-race-fix fs/ext3/inode.c --- 25/fs/ext3/inode.c~ext3_getblk-race-fix 2003-07-25 20:09:37.000000000 -0700 +++ 25-akpm/fs/ext3/inode.c 2003-07-25 20:09:44.000000000 -0700 @@ -938,15 +938,15 @@ struct buffer_head *ext3_getblk(handle_t lock_buffer(bh); BUFFER_TRACE(bh, "call get_create_access"); fatal = ext3_journal_get_create_access(handle, bh); - if (!fatal) { - memset(bh->b_data, 0, - inode->i_sb->s_blocksize); + if (!fatal && !buffer_uptodate(bh)) { + memset(bh->b_data, 0, inode->i_sb->s_blocksize); set_buffer_uptodate(bh); } unlock_buffer(bh); BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); err = ext3_journal_dirty_metadata(handle, bh); - if (!fatal) fatal = err; + if (!fatal) + fatal = err; } else { BUFFER_TRACE(bh, "not a new buffer"); } _