Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ext4: pass allocate range as loff_t to ext4_alloc_file_blocks()

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.

Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260327102939.1095257-8-yi.zhang@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>

authored by

Zhang Yi and committed by
Theodore Ts'o
ad1876bc d3609a71

+22 -31
+22 -31
fs/ext4/extents.c
··· 4571 4571 return err; 4572 4572 } 4573 4573 4574 - static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset, 4575 - ext4_lblk_t len, loff_t new_size, 4576 - int flags) 4574 + static int ext4_alloc_file_blocks(struct file *file, loff_t offset, loff_t len, 4575 + loff_t new_size, int flags) 4577 4576 { 4578 4577 struct inode *inode = file_inode(file); 4579 4578 handle_t *handle; 4580 4579 int ret = 0, ret2 = 0, ret3 = 0; 4581 4580 int retries = 0; 4582 4581 int depth = 0; 4582 + ext4_lblk_t len_lblk; 4583 4583 struct ext4_map_blocks map; 4584 4584 unsigned int credits; 4585 4585 loff_t epos, old_size = i_size_read(inode); ··· 4587 4587 bool alloc_zero = false; 4588 4588 4589 4589 BUG_ON(!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)); 4590 - map.m_lblk = offset; 4591 - map.m_len = len; 4590 + map.m_lblk = offset >> blkbits; 4591 + map.m_len = len_lblk = EXT4_MAX_BLOCKS(len, offset, blkbits); 4592 4592 /* 4593 4593 * Don't normalize the request if it can fit in one extent so 4594 4594 * that it doesn't get unnecessarily split into multiple 4595 4595 * extents. 4596 4596 */ 4597 - if (len <= EXT_UNWRITTEN_MAX_LEN) 4597 + if (len_lblk <= EXT_UNWRITTEN_MAX_LEN) 4598 4598 flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; 4599 4599 4600 4600 /* ··· 4611 4611 /* 4612 4612 * credits to insert 1 extent into extent tree 4613 4613 */ 4614 - credits = ext4_chunk_trans_blocks(inode, len); 4614 + credits = ext4_chunk_trans_blocks(inode, len_lblk); 4615 4615 depth = ext_depth(inode); 4616 4616 4617 4617 retry: 4618 - while (len) { 4618 + while (len_lblk) { 4619 4619 /* 4620 4620 * Recalculate credits when extent tree depth changes. 4621 4621 */ 4622 4622 if (depth != ext_depth(inode)) { 4623 - credits = ext4_chunk_trans_blocks(inode, len); 4623 + credits = ext4_chunk_trans_blocks(inode, len_lblk); 4624 4624 depth = ext_depth(inode); 4625 4625 } 4626 4626 ··· 4677 4677 } 4678 4678 4679 4679 map.m_lblk += ret; 4680 - map.m_len = len = len - ret; 4680 + map.m_len = len_lblk = len_lblk - ret; 4681 4681 } 4682 4682 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 4683 4683 goto retry; ··· 4694 4694 { 4695 4695 struct inode *inode = file_inode(file); 4696 4696 handle_t *handle = NULL; 4697 - loff_t new_size = 0; 4697 + loff_t align_start, align_end, new_size = 0; 4698 4698 loff_t end = offset + len; 4699 - ext4_lblk_t start_lblk, end_lblk; 4700 4699 unsigned int blocksize = i_blocksize(inode); 4701 - unsigned int blkbits = inode->i_blkbits; 4702 4700 int ret, flags, credits; 4703 4701 4704 4702 trace_ext4_zero_range(inode, offset, len, mode); ··· 4717 4719 flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT; 4718 4720 /* Preallocate the range including the unaligned edges */ 4719 4721 if (!IS_ALIGNED(offset | end, blocksize)) { 4720 - ext4_lblk_t alloc_lblk = offset >> blkbits; 4721 - ext4_lblk_t len_lblk = EXT4_MAX_BLOCKS(len, offset, blkbits); 4722 - 4723 - ret = ext4_alloc_file_blocks(file, alloc_lblk, len_lblk, 4724 - new_size, flags); 4722 + ret = ext4_alloc_file_blocks(file, offset, len, new_size, 4723 + flags); 4725 4724 if (ret) 4726 4725 return ret; 4727 4726 } ··· 4733 4738 return ret; 4734 4739 4735 4740 /* Zero range excluding the unaligned edges */ 4736 - start_lblk = EXT4_B_TO_LBLK(inode, offset); 4737 - end_lblk = end >> blkbits; 4738 - if (end_lblk > start_lblk) { 4739 - ext4_lblk_t zero_blks = end_lblk - start_lblk; 4740 - 4741 + align_start = round_up(offset, blocksize); 4742 + align_end = round_down(end, blocksize); 4743 + if (align_end > align_start) { 4741 4744 if (mode & FALLOC_FL_WRITE_ZEROES) 4742 4745 flags = EXT4_GET_BLOCKS_CREATE_ZERO | EXT4_EX_NOCACHE; 4743 4746 else 4744 4747 flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | 4745 4748 EXT4_EX_NOCACHE); 4746 - ret = ext4_alloc_file_blocks(file, start_lblk, zero_blks, 4747 - new_size, flags); 4749 + ret = ext4_alloc_file_blocks(file, align_start, 4750 + align_end - align_start, new_size, 4751 + flags); 4748 4752 if (ret) 4749 4753 return ret; 4750 4754 } ··· 4791 4797 struct inode *inode = file_inode(file); 4792 4798 loff_t end = offset + len; 4793 4799 loff_t new_size = 0; 4794 - ext4_lblk_t start_lblk, len_lblk; 4795 4800 int ret; 4796 4801 4797 4802 trace_ext4_fallocate_enter(inode, offset, len, mode); 4798 4803 WARN_ON_ONCE(!inode_is_locked(inode)); 4799 - 4800 - start_lblk = offset >> inode->i_blkbits; 4801 - len_lblk = EXT4_MAX_BLOCKS(len, offset, inode->i_blkbits); 4802 4804 4803 4805 /* We only support preallocation for extent-based files only. */ 4804 4806 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { ··· 4810 4820 goto out; 4811 4821 } 4812 4822 4813 - ret = ext4_alloc_file_blocks(file, start_lblk, len_lblk, new_size, 4823 + ret = ext4_alloc_file_blocks(file, offset, len, new_size, 4814 4824 EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT); 4815 4825 if (ret) 4816 4826 goto out; ··· 4820 4830 EXT4_I(inode)->i_sync_tid); 4821 4831 } 4822 4832 out: 4823 - trace_ext4_fallocate_exit(inode, offset, len_lblk, ret); 4833 + trace_ext4_fallocate_exit(inode, offset, 4834 + EXT4_MAX_BLOCKS(len, offset, inode->i_blkbits), ret); 4824 4835 return ret; 4825 4836 } 4826 4837