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: factor out journalled block zeroing range

Refactor __ext4_block_zero_page_range() by separating the block zeroing
operations for ordered data mode and journal data mode into two distinct
functions:

- ext4_block_do_zero_range(): handles non-journal data mode with
ordered data support
- ext4_block_journalled_zero_range(): handles journal data mode

Also extract a common helper, ext4_load_tail_bh(), to handle buffer head
and folio retrieval, along with the associated error handling. This
prepares for converting the partial block zero range to the iomap
infrastructure.

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

authored by

Zhang Yi and committed by
Theodore Ts'o
3b312a6f bd099a05

+69 -29
+69 -29
fs/ext4/inode.c
··· 4032 4032 * ext4_punch_hole, etc) which needs to be properly zeroed out. Otherwise a 4033 4033 * racing writeback can come later and flush the stale pagecache to disk. 4034 4034 */ 4035 - static int __ext4_block_zero_page_range(handle_t *handle, 4036 - struct address_space *mapping, loff_t from, loff_t length, 4037 - bool *did_zero) 4035 + static struct buffer_head *ext4_load_tail_bh(struct inode *inode, loff_t from) 4038 4036 { 4039 4037 unsigned int offset, blocksize, pos; 4040 4038 ext4_lblk_t iblock; 4041 - struct inode *inode = mapping->host; 4039 + struct address_space *mapping = inode->i_mapping; 4042 4040 struct buffer_head *bh; 4043 4041 struct folio *folio; 4044 4042 int err = 0; ··· 4045 4047 FGP_LOCK | FGP_ACCESSED | FGP_CREAT, 4046 4048 mapping_gfp_constraint(mapping, ~__GFP_FS)); 4047 4049 if (IS_ERR(folio)) 4048 - return PTR_ERR(folio); 4050 + return ERR_CAST(folio); 4049 4051 4050 4052 blocksize = inode->i_sb->s_blocksize; 4051 4053 ··· 4097 4099 } 4098 4100 } 4099 4101 } 4100 - if (ext4_should_journal_data(inode)) { 4101 - BUFFER_TRACE(bh, "get write access"); 4102 - err = ext4_journal_get_write_access(handle, inode->i_sb, bh, 4103 - EXT4_JTR_NONE); 4104 - if (err) 4105 - goto unlock; 4106 - } 4107 - folio_zero_range(folio, offset, length); 4102 + return bh; 4103 + 4104 + unlock: 4105 + folio_unlock(folio); 4106 + folio_put(folio); 4107 + return err ? ERR_PTR(err) : NULL; 4108 + } 4109 + 4110 + static int ext4_block_do_zero_range(handle_t *handle, struct inode *inode, 4111 + loff_t from, loff_t length, bool *did_zero) 4112 + { 4113 + struct buffer_head *bh; 4114 + struct folio *folio; 4115 + int err = 0; 4116 + 4117 + bh = ext4_load_tail_bh(inode, from); 4118 + if (IS_ERR_OR_NULL(bh)) 4119 + return PTR_ERR_OR_ZERO(bh); 4120 + 4121 + folio = bh->b_folio; 4122 + folio_zero_range(folio, offset_in_folio(folio, from), length); 4108 4123 BUFFER_TRACE(bh, "zeroed end of block"); 4109 4124 4110 - if (ext4_should_journal_data(inode)) { 4111 - err = ext4_dirty_journalled_data(handle, bh); 4112 - } else { 4113 - mark_buffer_dirty(bh); 4114 - /* 4115 - * Only the written block requires ordered data to prevent 4116 - * exposing stale data. 4117 - */ 4118 - if (!buffer_unwritten(bh) && !buffer_delay(bh) && 4119 - ext4_should_order_data(inode)) 4120 - err = ext4_jbd2_inode_add_write(handle, inode, from, 4121 - length); 4122 - } 4125 + mark_buffer_dirty(bh); 4126 + /* 4127 + * Only the written block requires ordered data to prevent exposing 4128 + * stale data. 4129 + */ 4130 + if (ext4_should_order_data(inode) && 4131 + !buffer_unwritten(bh) && !buffer_delay(bh)) 4132 + err = ext4_jbd2_inode_add_write(handle, inode, from, length); 4123 4133 if (!err && did_zero) 4124 4134 *did_zero = true; 4125 4135 4126 - unlock: 4136 + folio_unlock(folio); 4137 + folio_put(folio); 4138 + return err; 4139 + } 4140 + 4141 + static int ext4_block_journalled_zero_range(handle_t *handle, 4142 + struct inode *inode, loff_t from, loff_t length, bool *did_zero) 4143 + { 4144 + struct buffer_head *bh; 4145 + struct folio *folio; 4146 + int err; 4147 + 4148 + bh = ext4_load_tail_bh(inode, from); 4149 + if (IS_ERR_OR_NULL(bh)) 4150 + return PTR_ERR_OR_ZERO(bh); 4151 + folio = bh->b_folio; 4152 + 4153 + BUFFER_TRACE(bh, "get write access"); 4154 + err = ext4_journal_get_write_access(handle, inode->i_sb, bh, 4155 + EXT4_JTR_NONE); 4156 + if (err) 4157 + goto out; 4158 + 4159 + folio_zero_range(folio, offset_in_folio(folio, from), length); 4160 + BUFFER_TRACE(bh, "zeroed end of block"); 4161 + 4162 + err = ext4_dirty_journalled_data(handle, bh); 4163 + if (err) 4164 + goto out; 4165 + 4166 + if (did_zero) 4167 + *did_zero = true; 4168 + out: 4127 4169 folio_unlock(folio); 4128 4170 folio_put(folio); 4129 4171 return err; ··· 4194 4156 if (IS_DAX(inode)) { 4195 4157 return dax_zero_range(inode, from, length, did_zero, 4196 4158 &ext4_iomap_ops); 4159 + } else if (ext4_should_journal_data(inode)) { 4160 + return ext4_block_journalled_zero_range(handle, inode, from, 4161 + length, did_zero); 4197 4162 } 4198 - return __ext4_block_zero_page_range(handle, mapping, from, length, 4199 - did_zero); 4163 + return ext4_block_do_zero_range(handle, inode, from, length, did_zero); 4200 4164 } 4201 4165 4202 4166 /*