With delayed allocation we delay the allocation of blocks
and request for blocks in multiple chunks. We should not
update i_disksize to inode.i_size unless we are allocating
blocks corresponding to the end of file.
Signed-off-by: Aneesh Kumar K.V <[email protected]>
---
fs/ext4/extents.c | 10 ++++++++--
fs/ext4/inode.c | 10 ++++++++--
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index dae3b60..27cfd30 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2698,6 +2698,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
int err = 0, depth, ret;
unsigned long allocated = 0;
struct ext4_allocation_request ar;
+ loff_t disksize;
__clear_bit(BH_New, &bh_result->b_state);
ext_debug("blocks %u/%lu requested for inode %u\n",
@@ -2885,8 +2886,13 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
goto out2;
}
- if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize)
- EXT4_I(inode)->i_disksize = inode->i_size;
+ if (extend_disksize) {
+ disksize = ((loff_t) iblock + ar.len) << inode->i_blkbits;
+ if (disksize > i_size_read(inode))
+ disksize = i_size_read(inode);
+ if (disksize > EXT4_I(inode)->i_disksize)
+ EXT4_I(inode)->i_disksize = disksize;
+ }
/* previous routine could use block we allocated */
newblock = ext_pblock(&newex);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a51d5f4..5265933 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -846,6 +846,7 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
struct ext4_inode_info *ei = EXT4_I(inode);
int count = 0;
ext4_fsblk_t first_block = 0;
+ loff_t disksize;
J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
@@ -921,8 +922,13 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
* protect it if you're about to implement concurrent
* ext4_get_block() -bzzz
*/
- if (!err && extend_disksize && inode->i_size > ei->i_disksize)
- ei->i_disksize = inode->i_size;
+ if (!err && extend_disksize) {
+ disksize = ((loff_t) iblock + count) << inode->i_blkbits;
+ if (disksize > i_size_read(inode))
+ disksize = i_size_read(inode);
+ if (disksize > ei->i_disksize)
+ ei->i_disksize = disksize;
+ }
if (err)
goto cleanup;
--
1.5.6.rc2.15.g457bb.dirty
When allocating blocks from an falloc area which was initialized with
FALLOC_FL_KEEP_SIZE we need to extent disksize.
These changes are for code correctness. We do update the i_disksize
in the write_end callback of filesystem properly.
Signed-off-by: Aneesh Kumar K.V <[email protected]>
---
fs/ext4/extents.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 27cfd30..362211c 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2885,7 +2885,10 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
ext4_ext_get_actual_len(&newex), 0);
goto out2;
}
-
+ /* previous routine could use block we allocated */
+ newblock = ext_pblock(&newex);
+ allocated = ext4_ext_get_actual_len(&newex);
+outnew:
if (extend_disksize) {
disksize = ((loff_t) iblock + ar.len) << inode->i_blkbits;
if (disksize > i_size_read(inode))
@@ -2893,11 +2896,6 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
if (disksize > EXT4_I(inode)->i_disksize)
EXT4_I(inode)->i_disksize = disksize;
}