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