diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2011-10-25 08:15:12 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-10-25 08:15:12 -0400 |
commit | a4e5d88b1b24827f4f6a3cba43228936a67d81ba (patch) | |
tree | 0f5b0309f290f5fc23478794c6f4adcd7c18896a /fs/ext4/extents.c | |
parent | 750c9c47a5f9daa88333ac435a1afe4d4b428230 (diff) |
ext4: update EOFBLOCKS flag on fallocate properly
EOFBLOCK_FL should be updated if called w/o FALLOCATE_FL_KEEP_SIZE
Currently it happens only if new extent was allocated.
TESTCASE:
fallocate test_file -n -l4096
fallocate test_file -l4096
Last fallocate cmd has updated size, but keept EOFBLOCK_FL set. And
fsck will complain about that.
Also remove ping pong in ext4_fallocate() in case of new extents,
where ext4_ext_map_blocks() clear EOFBLOCKS bit, and later
ext4_falloc_update_inode() restore it again.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index d0e3f333d3f0..8686eb756b38 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -3432,14 +3432,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, | |||
3432 | 3432 | ||
3433 | /* buffered write, writepage time, convert*/ | 3433 | /* buffered write, writepage time, convert*/ |
3434 | ret = ext4_ext_convert_to_initialized(handle, inode, map, path); | 3434 | ret = ext4_ext_convert_to_initialized(handle, inode, map, path); |
3435 | if (ret >= 0) { | 3435 | if (ret >= 0) |
3436 | ext4_update_inode_fsync_trans(handle, inode, 1); | 3436 | ext4_update_inode_fsync_trans(handle, inode, 1); |
3437 | err = check_eofblocks_fl(handle, inode, map->m_lblk, path, | ||
3438 | map->m_len); | ||
3439 | if (err < 0) | ||
3440 | goto out2; | ||
3441 | } | ||
3442 | |||
3443 | out: | 3437 | out: |
3444 | if (ret <= 0) { | 3438 | if (ret <= 0) { |
3445 | err = ret; | 3439 | err = ret; |
@@ -3480,6 +3474,12 @@ out: | |||
3480 | 3474 | ||
3481 | map_out: | 3475 | map_out: |
3482 | map->m_flags |= EXT4_MAP_MAPPED; | 3476 | map->m_flags |= EXT4_MAP_MAPPED; |
3477 | if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0) { | ||
3478 | err = check_eofblocks_fl(handle, inode, map->m_lblk, path, | ||
3479 | map->m_len); | ||
3480 | if (err < 0) | ||
3481 | goto out2; | ||
3482 | } | ||
3483 | out1: | 3483 | out1: |
3484 | if (allocated > map->m_len) | 3484 | if (allocated > map->m_len) |
3485 | allocated = map->m_len; | 3485 | allocated = map->m_len; |
@@ -3955,7 +3955,10 @@ got_allocated_blocks: | |||
3955 | map->m_flags |= EXT4_MAP_UNINIT; | 3955 | map->m_flags |= EXT4_MAP_UNINIT; |
3956 | } | 3956 | } |
3957 | 3957 | ||
3958 | err = check_eofblocks_fl(handle, inode, map->m_lblk, path, ar.len); | 3958 | err = 0; |
3959 | if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0) | ||
3960 | err = check_eofblocks_fl(handle, inode, map->m_lblk, | ||
3961 | path, ar.len); | ||
3959 | if (!err) | 3962 | if (!err) |
3960 | err = ext4_ext_insert_extent(handle, inode, path, | 3963 | err = ext4_ext_insert_extent(handle, inode, path, |
3961 | &newex, flags); | 3964 | &newex, flags); |
@@ -4214,6 +4217,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
4214 | int ret = 0; | 4217 | int ret = 0; |
4215 | int ret2 = 0; | 4218 | int ret2 = 0; |
4216 | int retries = 0; | 4219 | int retries = 0; |
4220 | int flags; | ||
4217 | struct ext4_map_blocks map; | 4221 | struct ext4_map_blocks map; |
4218 | unsigned int credits, blkbits = inode->i_blkbits; | 4222 | unsigned int credits, blkbits = inode->i_blkbits; |
4219 | 4223 | ||
@@ -4250,6 +4254,10 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
4250 | trace_ext4_fallocate_exit(inode, offset, max_blocks, ret); | 4254 | trace_ext4_fallocate_exit(inode, offset, max_blocks, ret); |
4251 | return ret; | 4255 | return ret; |
4252 | } | 4256 | } |
4257 | flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT | | ||
4258 | EXT4_GET_BLOCKS_NO_NORMALIZE; | ||
4259 | if (mode & FALLOC_FL_KEEP_SIZE) | ||
4260 | flags |= EXT4_GET_BLOCKS_KEEP_SIZE; | ||
4253 | retry: | 4261 | retry: |
4254 | while (ret >= 0 && ret < max_blocks) { | 4262 | while (ret >= 0 && ret < max_blocks) { |
4255 | map.m_lblk = map.m_lblk + ret; | 4263 | map.m_lblk = map.m_lblk + ret; |
@@ -4259,9 +4267,7 @@ retry: | |||
4259 | ret = PTR_ERR(handle); | 4267 | ret = PTR_ERR(handle); |
4260 | break; | 4268 | break; |
4261 | } | 4269 | } |
4262 | ret = ext4_map_blocks(handle, inode, &map, | 4270 | ret = ext4_map_blocks(handle, inode, &map, flags); |
4263 | EXT4_GET_BLOCKS_CREATE_UNINIT_EXT | | ||
4264 | EXT4_GET_BLOCKS_NO_NORMALIZE); | ||
4265 | if (ret <= 0) { | 4271 | if (ret <= 0) { |
4266 | #ifdef EXT4FS_DEBUG | 4272 | #ifdef EXT4FS_DEBUG |
4267 | WARN_ON(ret <= 0); | 4273 | WARN_ON(ret <= 0); |