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

ext4: add two helper functions extent_logical_end() and pa_logical_end()

When we use lstart + len to calculate the end of free extent or prealloc
space, it may exceed the maximum value of 4294967295(0xffffffff) supported
by ext4_lblk_t and cause overflow, which may lead to various problems.

Therefore, we add two helper functions, extent_logical_end() and
pa_logical_end(), to limit the type of end to loff_t, and also convert
lstart to loff_t for calculation to avoid overflow.

Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Link: https://lore.kernel.org/r/20230724121059.11834-2-libaokun1@huawei.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>

authored by

Baokun Li and committed by
Theodore Ts'o
43bbddc0 6eaae198

+17 -6
+3 -6
fs/ext4/mballoc.c
··· 4432 4432 4433 4433 /* first, let's learn actual file size 4434 4434 * given current request is allocated */ 4435 - size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len); 4435 + size = extent_logical_end(sbi, &ac->ac_o_ex); 4436 4436 size = size << bsbits; 4437 4437 if (size < i_size_read(ac->ac_inode)) 4438 4438 size = i_size_read(ac->ac_inode); ··· 4766 4766 struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); 4767 4767 struct ext4_locality_group *lg; 4768 4768 struct ext4_prealloc_space *tmp_pa = NULL, *cpa = NULL; 4769 - loff_t tmp_pa_end; 4770 4769 struct rb_node *iter; 4771 4770 ext4_fsblk_t goal_block; 4772 4771 ··· 4861 4862 * pa can possibly satisfy the request hence check if it overlaps 4862 4863 * original logical start and stop searching if it doesn't. 4863 4864 */ 4864 - tmp_pa_end = (loff_t)tmp_pa->pa_lstart + EXT4_C2B(sbi, tmp_pa->pa_len); 4865 - 4866 - if (ac->ac_o_ex.fe_logical >= tmp_pa_end) { 4865 + if (ac->ac_o_ex.fe_logical >= pa_logical_end(sbi, tmp_pa)) { 4867 4866 spin_unlock(&tmp_pa->pa_lock); 4868 4867 goto try_group_pa; 4869 4868 } ··· 5766 5769 5767 5770 group_pa_eligible = sbi->s_mb_group_prealloc > 0; 5768 5771 inode_pa_eligible = true; 5769 - size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len); 5772 + size = extent_logical_end(sbi, &ac->ac_o_ex); 5770 5773 isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1) 5771 5774 >> bsbits; 5772 5775
+14
fs/ext4/mballoc.h
··· 233 233 (fex->fe_start << EXT4_SB(sb)->s_cluster_bits); 234 234 } 235 235 236 + static inline loff_t extent_logical_end(struct ext4_sb_info *sbi, 237 + struct ext4_free_extent *fex) 238 + { 239 + /* Use loff_t to avoid end exceeding ext4_lblk_t max. */ 240 + return (loff_t)fex->fe_logical + EXT4_C2B(sbi, fex->fe_len); 241 + } 242 + 243 + static inline loff_t pa_logical_end(struct ext4_sb_info *sbi, 244 + struct ext4_prealloc_space *pa) 245 + { 246 + /* Use loff_t to avoid end exceeding ext4_lblk_t max. */ 247 + return (loff_t)pa->pa_lstart + EXT4_C2B(sbi, pa->pa_len); 248 + } 249 + 236 250 typedef int (*ext4_mballoc_query_range_fn)( 237 251 struct super_block *sb, 238 252 ext4_group_t agno,