Commit 87e628f7 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ext3: i_disksize locking fix

From: Alex Tomas <alex@clusterfs.com>

The setting of i_disksize can race against concurrent invokations of
ext3_get_block().  Moving this inside i_truncate_sem fixes it up.
parent df5e207c
......@@ -769,7 +769,6 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
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 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
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;
......
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