Commit 77b070cb authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix race in ext3_getblk

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.
parent bca17d03
...@@ -938,15 +938,15 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode, ...@@ -938,15 +938,15 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
lock_buffer(bh); lock_buffer(bh);
BUFFER_TRACE(bh, "call get_create_access"); BUFFER_TRACE(bh, "call get_create_access");
fatal = ext3_journal_get_create_access(handle, bh); fatal = ext3_journal_get_create_access(handle, bh);
if (!fatal) { if (!fatal && !buffer_uptodate(bh)) {
memset(bh->b_data, 0, memset(bh->b_data, 0, inode->i_sb->s_blocksize);
inode->i_sb->s_blocksize);
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
} }
unlock_buffer(bh); unlock_buffer(bh);
BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
err = ext3_journal_dirty_metadata(handle, bh); err = ext3_journal_dirty_metadata(handle, bh);
if (!fatal) fatal = err; if (!fatal)
fatal = err;
} else { } else {
BUFFER_TRACE(bh, "not a new buffer"); BUFFER_TRACE(bh, "not a new buffer");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment