From: Alex Tomas The setting of i_disksize can race against concurrent invokations of ext3_get_block(). Moving this inside i_truncate_sem fixes it up. 25-akpm/fs/ext3/inode.c | 17 +++++------------ 1 files changed, 5 insertions(+), 12 deletions(-) diff -puN fs/ext3/inode.c~ext3-i_disksize-locking-fix fs/ext3/inode.c --- 25/fs/ext3/inode.c~ext3-i_disksize-locking-fix Mon Oct 13 14:31:13 2003 +++ 25-akpm/fs/ext3/inode.c Mon Oct 13 14:31:13 2003 @@ -769,7 +769,6 @@ ext3_get_block_handle(handle_t *handle, int boundary = 0; int depth = ext3_block_to_path(inode, iblock, offsets, &boundary); struct ext3_inode_info *ei = EXT3_I(inode); - loff_t new_size; J_ASSERT(handle != NULL || create == 0); @@ -834,23 +833,17 @@ out: if (!err) err = ext3_splice_branch(handle, inode, iblock, chain, partial, left); + /* i_disksize growing is protected by truncate_sem + * don't forget to protect it if you're about to implement + * concurrent ext3_get_block() -bzzz */ + if (!err && extend_disksize && inode->i_size > ei->i_disksize) + ei->i_disksize = inode->i_size; up(&ei->truncate_sem); if (err == -EAGAIN) goto changed; if (err) goto cleanup; - if (extend_disksize) { - /* - * This is not racy against ext3_truncate's modification of - * i_disksize because VM/VFS ensures that the file cannot be - * extended while truncate is in progress. It is racy between - * multiple parallel instances of get_block, but we have BKL. - */ - new_size = inode->i_size; - if (new_size > ei->i_disksize) - ei->i_disksize = new_size; - } set_buffer_new(bh_result); goto got_it; _