From: Zhang Yi <yi.zhang@huawei.com> hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/8477 -------------------------------- Change ext4_alloc_file_blocks() to accept offset and len in byte granularity instead of block granularity. This allows callers to pass byte offsets and lengths directly, and this prepares for moving the ext4_zero_partial_blocks() call from the while(len) loop for unaligned append writes, where it only needs to be invoked once before doing block allocation. Fixes: 5721968224e0 ("ext4: implement zero_range iomap path") Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Signed-off-by: Yongjian Sun <sunyongjian1@huawei.com> --- fs/ext4/extents.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 43899a3728fe..b9dbe6072392 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4489,43 +4489,44 @@ int ext4_ext_truncate(handle_t *handle, struct inode *inode) return err; } -static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset, - ext4_lblk_t len, loff_t new_size, - int flags) +static int ext4_alloc_file_blocks(struct file *file, loff_t offset, loff_t len, + loff_t new_size, int flags) { struct inode *inode = file_inode(file); handle_t *handle; int ret = 0, ret2 = 0, ret3 = 0; int retries = 0; int depth = 0; + ext4_lblk_t len_lblk; struct ext4_map_blocks map; unsigned int credits; loff_t epos, old_size = i_size_read(inode); + unsigned int blkbits = inode->i_blkbits; BUG_ON(!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)); - map.m_lblk = offset; - map.m_len = len; + map.m_lblk = offset >> blkbits; + map.m_len = len_lblk = EXT4_MAX_BLOCKS(len, offset, blkbits); /* * Don't normalize the request if it can fit in one extent so * that it doesn't get unnecessarily split into multiple * extents. */ - if (len <= EXT_UNWRITTEN_MAX_LEN) + if (len_lblk <= EXT_UNWRITTEN_MAX_LEN) flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; /* * credits to insert 1 extent into extent tree */ - credits = ext4_chunk_trans_blocks(inode, len); + credits = ext4_chunk_trans_blocks(inode, len_lblk); depth = ext_depth(inode); retry: - while (len) { + while (len_lblk) { /* * Recalculate credits when extent tree depth changes. */ if (depth != ext_depth(inode)) { - credits = ext4_chunk_trans_blocks(inode, len); + credits = ext4_chunk_trans_blocks(inode, len_lblk); depth = ext_depth(inode); } @@ -4550,7 +4551,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset, */ retries = 0; map.m_lblk += ret; - map.m_len = len = len - ret; + map.m_len = len_lblk = len_lblk - ret; epos = (loff_t)map.m_lblk << inode->i_blkbits; inode_set_ctime_current(inode); if (new_size) { @@ -4651,11 +4652,8 @@ static long ext4_zero_range(struct file *file, loff_t offset, /* Preallocate the range including the unaligned edges */ if (partial_begin || partial_end) { - ret = ext4_alloc_file_blocks(file, - round_down(offset, 1 << blkbits) >> blkbits, - (round_up((offset + len), 1 << blkbits) - - round_down(offset, 1 << blkbits)) >> blkbits, - new_size, flags); + ret = ext4_alloc_file_blocks(file, offset, len, new_size, + flags); if (ret) goto out_mutex; @@ -4702,7 +4700,7 @@ static long ext4_zero_range(struct file *file, loff_t offset, inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); - ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, + ret = ext4_alloc_file_blocks(file, start, end - start, new_size, flags); filemap_invalidate_unlock(mapping); if (ret) @@ -4757,11 +4755,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file_inode(file); loff_t new_size = 0; - unsigned int max_blocks; int ret = 0; int flags; - ext4_lblk_t lblk; - unsigned int blkbits = inode->i_blkbits; /* * Encrypted inodes can't handle collapse range or insert @@ -4805,9 +4800,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) goto exit; } trace_ext4_fallocate_enter(inode, offset, len, mode); - lblk = offset >> blkbits; - max_blocks = EXT4_MAX_BLOCKS(len, offset, blkbits); flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT; inode_lock(inode); @@ -4836,7 +4829,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (ret) goto out; - ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags); + ret = ext4_alloc_file_blocks(file, offset, len, new_size, flags); if (ret) goto out; @@ -4846,7 +4839,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) } out: inode_unlock(inode); - trace_ext4_fallocate_exit(inode, offset, max_blocks, ret); + trace_ext4_fallocate_exit(inode, offset, + EXT4_MAX_BLOCKS(len, offset, inode->i_blkbits), ret); exit: return ret; } -- 2.39.2