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: move zero partial block range functions out of active handle

Move ext4_block_zero_eof() and ext4_zero_partial_blocks() calls out of
the active handle context, making them independent operations, and also
add return value checks. This is safe because it still ensures data is
updated before metadata for data=ordered mode and data=journal mode
because we still zero data and ordering data before modifying the
metadata.

This change is required for iomap infrastructure conversion because the
iomap buffered I/O path does not use the same journal infrastructure for
partial block zeroing. The lock ordering of folio lock and starting
transactions is "folio lock -> transaction start", which is opposite of
the current path. Therefore, zeroing partial blocks cannot be performed
under the active handle.

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

authored by

Zhang Yi and committed by
Theodore Ts'o
c4602a1d ad1876bc

+41 -38
+15 -17
fs/ext4/extents.c
··· 4614 4614 credits = ext4_chunk_trans_blocks(inode, len_lblk); 4615 4615 depth = ext_depth(inode); 4616 4616 4617 + /* Zero to the end of the block containing i_size */ 4618 + if (new_size > old_size) { 4619 + ret = ext4_block_zero_eof(inode, old_size, LLONG_MAX); 4620 + if (ret) 4621 + return ret; 4622 + } 4623 + 4617 4624 retry: 4618 4625 while (len_lblk) { 4619 4626 /* ··· 4659 4652 if (ext4_update_inode_size(inode, epos) & 0x1) 4660 4653 inode_set_mtime_to_ts(inode, 4661 4654 inode_get_ctime(inode)); 4662 - if (epos > old_size) { 4655 + if (epos > old_size) 4663 4656 pagecache_isize_extended(inode, old_size, epos); 4664 - ext4_block_zero_eof(inode, old_size, epos); 4665 - } 4666 4657 } 4667 4658 ret2 = ext4_mark_inode_dirty(handle, inode); 4668 4659 ext4_update_inode_fsync_trans(handle, inode, 1); ··· 4702 4697 loff_t align_start, align_end, new_size = 0; 4703 4698 loff_t end = offset + len; 4704 4699 unsigned int blocksize = i_blocksize(inode); 4705 - int ret, flags, credits; 4700 + int ret, flags; 4706 4701 4707 4702 trace_ext4_zero_range(inode, offset, len, mode); 4708 4703 WARN_ON_ONCE(!inode_is_locked(inode)); ··· 4756 4751 if (IS_ALIGNED(offset | end, blocksize)) 4757 4752 return ret; 4758 4753 4759 - /* 4760 - * In worst case we have to writeout two nonadjacent unwritten 4761 - * blocks and update the inode 4762 - */ 4763 - credits = (2 * ext4_ext_index_trans_blocks(inode, 2)) + 1; 4764 - if (ext4_should_journal_data(inode)) 4765 - credits += 2; 4766 - handle = ext4_journal_start(inode, EXT4_HT_MISC, credits); 4754 + /* Zero out partial block at the edges of the range */ 4755 + ret = ext4_zero_partial_blocks(inode, offset, len); 4756 + if (ret) 4757 + return ret; 4758 + 4759 + handle = ext4_journal_start(inode, EXT4_HT_MISC, 1); 4767 4760 if (IS_ERR(handle)) { 4768 4761 ret = PTR_ERR(handle); 4769 4762 ext4_std_error(inode->i_sb, ret); 4770 4763 return ret; 4771 4764 } 4772 - 4773 - /* Zero out partial block at the edges of the range */ 4774 - ret = ext4_zero_partial_blocks(inode, offset, len); 4775 - if (ret) 4776 - goto out_handle; 4777 4765 4778 4766 if (new_size) 4779 4767 ext4_update_inode_size(inode, new_size);
+26 -21
fs/ext4/inode.c
··· 4471 4471 if (ret) 4472 4472 return ret; 4473 4473 4474 + ret = ext4_zero_partial_blocks(inode, offset, length); 4475 + if (ret) 4476 + return ret; 4477 + 4474 4478 if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) 4475 - credits = ext4_chunk_trans_extent(inode, 2); 4479 + credits = ext4_chunk_trans_extent(inode, 0); 4476 4480 else 4477 4481 credits = ext4_blocks_for_truncate(inode); 4478 4482 handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); ··· 4485 4481 ext4_std_error(sb, ret); 4486 4482 return ret; 4487 4483 } 4488 - 4489 - ret = ext4_zero_partial_blocks(inode, offset, length); 4490 - if (ret) 4491 - goto out_handle; 4492 4484 4493 4485 /* If there are blocks to remove, do it */ 4494 4486 start_lblk = EXT4_B_TO_LBLK(inode, offset); ··· 4622 4622 err = ext4_inode_attach_jinode(inode); 4623 4623 if (err) 4624 4624 goto out_trace; 4625 + 4626 + /* Zero to the end of the block containing i_size */ 4627 + err = ext4_block_zero_eof(inode, inode->i_size, LLONG_MAX); 4628 + if (err) 4629 + goto out_trace; 4625 4630 } 4626 4631 4627 4632 if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) ··· 4639 4634 err = PTR_ERR(handle); 4640 4635 goto out_trace; 4641 4636 } 4642 - 4643 - /* Zero to the end of the block containing i_size */ 4644 - if (inode->i_size & (inode->i_sb->s_blocksize - 1)) 4645 - ext4_block_zero_eof(inode, inode->i_size, LLONG_MAX); 4646 4637 4647 4638 /* 4648 4639 * We add the inode to the orphan list, so that if this ··· 6009 6008 goto out_mmap_sem; 6010 6009 } 6011 6010 6012 - handle = ext4_journal_start(inode, EXT4_HT_INODE, 3); 6013 - if (IS_ERR(handle)) { 6014 - error = PTR_ERR(handle); 6015 - goto out_mmap_sem; 6016 - } 6017 - if (ext4_handle_valid(handle) && shrink) { 6018 - error = ext4_orphan_add(handle, inode); 6019 - orphan = 1; 6020 - } 6021 6011 /* 6022 6012 * Update c/mtime and tail zero the EOF folio on 6023 6013 * truncate up. ext4_truncate() handles the shrink case ··· 6017 6025 if (!shrink) { 6018 6026 inode_set_mtime_to_ts(inode, 6019 6027 inode_set_ctime_current(inode)); 6020 - if (oldsize & (inode->i_sb->s_blocksize - 1)) 6021 - ext4_block_zero_eof(inode, oldsize, 6022 - LLONG_MAX); 6028 + if (oldsize & (inode->i_sb->s_blocksize - 1)) { 6029 + error = ext4_block_zero_eof(inode, 6030 + oldsize, LLONG_MAX); 6031 + if (error) 6032 + goto out_mmap_sem; 6033 + } 6034 + } 6035 + 6036 + handle = ext4_journal_start(inode, EXT4_HT_INODE, 3); 6037 + if (IS_ERR(handle)) { 6038 + error = PTR_ERR(handle); 6039 + goto out_mmap_sem; 6040 + } 6041 + if (ext4_handle_valid(handle) && shrink) { 6042 + error = ext4_orphan_add(handle, inode); 6043 + orphan = 1; 6023 6044 } 6024 6045 6025 6046 if (shrink)