mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-18 18:43:59 +08:00
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>
This commit is contained in:
parent
750c9c47a5
commit
a4e5d88b1b
@ -539,6 +539,8 @@ struct ext4_new_group_data {
|
||||
#define EXT4_GET_BLOCKS_PUNCH_OUT_EXT 0x0020
|
||||
/* Don't normalize allocation size (used for fallocate) */
|
||||
#define EXT4_GET_BLOCKS_NO_NORMALIZE 0x0040
|
||||
/* Request will not result in inode size update (user for fallocate) */
|
||||
#define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080
|
||||
|
||||
/*
|
||||
* Flags used by ext4_free_blocks
|
||||
|
@ -3432,14 +3432,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
|
||||
|
||||
/* buffered write, writepage time, convert*/
|
||||
ret = ext4_ext_convert_to_initialized(handle, inode, map, path);
|
||||
if (ret >= 0) {
|
||||
if (ret >= 0)
|
||||
ext4_update_inode_fsync_trans(handle, inode, 1);
|
||||
err = check_eofblocks_fl(handle, inode, map->m_lblk, path,
|
||||
map->m_len);
|
||||
if (err < 0)
|
||||
goto out2;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret <= 0) {
|
||||
err = ret;
|
||||
@ -3480,6 +3474,12 @@ out:
|
||||
|
||||
map_out:
|
||||
map->m_flags |= EXT4_MAP_MAPPED;
|
||||
if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0) {
|
||||
err = check_eofblocks_fl(handle, inode, map->m_lblk, path,
|
||||
map->m_len);
|
||||
if (err < 0)
|
||||
goto out2;
|
||||
}
|
||||
out1:
|
||||
if (allocated > map->m_len)
|
||||
allocated = map->m_len;
|
||||
@ -3955,7 +3955,10 @@ got_allocated_blocks:
|
||||
map->m_flags |= EXT4_MAP_UNINIT;
|
||||
}
|
||||
|
||||
err = check_eofblocks_fl(handle, inode, map->m_lblk, path, ar.len);
|
||||
err = 0;
|
||||
if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0)
|
||||
err = check_eofblocks_fl(handle, inode, map->m_lblk,
|
||||
path, ar.len);
|
||||
if (!err)
|
||||
err = ext4_ext_insert_extent(handle, inode, path,
|
||||
&newex, flags);
|
||||
@ -4214,6 +4217,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
||||
int ret = 0;
|
||||
int ret2 = 0;
|
||||
int retries = 0;
|
||||
int flags;
|
||||
struct ext4_map_blocks map;
|
||||
unsigned int credits, blkbits = inode->i_blkbits;
|
||||
|
||||
@ -4250,6 +4254,10 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
||||
trace_ext4_fallocate_exit(inode, offset, max_blocks, ret);
|
||||
return ret;
|
||||
}
|
||||
flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT |
|
||||
EXT4_GET_BLOCKS_NO_NORMALIZE;
|
||||
if (mode & FALLOC_FL_KEEP_SIZE)
|
||||
flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
|
||||
retry:
|
||||
while (ret >= 0 && ret < max_blocks) {
|
||||
map.m_lblk = map.m_lblk + ret;
|
||||
@ -4259,9 +4267,7 @@ retry:
|
||||
ret = PTR_ERR(handle);
|
||||
break;
|
||||
}
|
||||
ret = ext4_map_blocks(handle, inode, &map,
|
||||
EXT4_GET_BLOCKS_CREATE_UNINIT_EXT |
|
||||
EXT4_GET_BLOCKS_NO_NORMALIZE);
|
||||
ret = ext4_map_blocks(handle, inode, &map, flags);
|
||||
if (ret <= 0) {
|
||||
#ifdef EXT4FS_DEBUG
|
||||
WARN_ON(ret <= 0);
|
||||
|
@ -477,9 +477,11 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
|
||||
*/
|
||||
down_read((&EXT4_I(inode)->i_data_sem));
|
||||
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
|
||||
retval = ext4_ext_map_blocks(handle, inode, map, 0);
|
||||
retval = ext4_ext_map_blocks(handle, inode, map, flags &
|
||||
EXT4_GET_BLOCKS_KEEP_SIZE);
|
||||
} else {
|
||||
retval = ext4_ind_map_blocks(handle, inode, map, 0);
|
||||
retval = ext4_ind_map_blocks(handle, inode, map, flags &
|
||||
EXT4_GET_BLOCKS_KEEP_SIZE);
|
||||
}
|
||||
up_read((&EXT4_I(inode)->i_data_sem));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user