From: Alex Tomas <bzzz@tmi.comex.ru>


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");
 		}

_