mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 07:03:28 -04:00
ext4: track partial-zero outcome per edge in ext4_zero_partial_blocks()
Replace the single bool did_zero output of ext4_zero_partial_blocks() with a bitmask that records which edge (start, end, or both in the single-block case) was actually partial-zeroed. This allows callers to distinguish which edges have been zeroed, preparing for unaligned FALLOC_FL_WRITE_ZEROES handling in later patches. Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260714080044.4038124-7-yi.zhang@huaweicloud.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
@@ -3198,8 +3198,11 @@ extern int ext4_chunk_trans_extent(struct inode *inode, int nrblocks);
|
||||
extern int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
|
||||
int pextents);
|
||||
extern int ext4_block_zero_eof(struct inode *inode, loff_t from, loff_t end);
|
||||
|
||||
#define EXT4_PARTIAL_ZERO_START 0x1
|
||||
#define EXT4_PARTIAL_ZERO_END 0x2
|
||||
extern int ext4_zero_partial_blocks(struct inode *inode, loff_t lstart,
|
||||
loff_t length, bool *did_zero);
|
||||
loff_t length, unsigned int *partial_zeroed);
|
||||
extern vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf);
|
||||
extern qsize_t *ext4_get_reserved_space(struct inode *inode);
|
||||
extern int ext4_get_projid(struct inode *inode, kprojid_t *projid);
|
||||
|
||||
@@ -4715,7 +4715,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
|
||||
loff_t align_start, align_end, new_size = 0;
|
||||
loff_t end = offset + len;
|
||||
unsigned int blocksize = i_blocksize(inode);
|
||||
bool partial_zeroed = false;
|
||||
unsigned int partial_zeroed = 0;
|
||||
int ret, flags;
|
||||
|
||||
trace_ext4_zero_range(inode, offset, len, mode);
|
||||
|
||||
@@ -4287,13 +4287,26 @@ int ext4_block_zero_eof(struct inode *inode, loff_t from, loff_t end)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero out the unaligned head and tail of the [lstart, lstart+length)
|
||||
* range.
|
||||
*
|
||||
* On return, @partial_zeroed records which edges actually got
|
||||
* partial-zeroed. Set EXT4_PARTIAL_ZERO_START/EXT4_PARTIAL_ZERO_END if
|
||||
* the head/tail block got actually partially zeroed (in written, dirty
|
||||
* unwritten or delalloc state). Cleared if the head/tail block is a
|
||||
* hole or a clean unwritten block, in which case there is nothing that
|
||||
* needs zeroing. When the head and tail land in the same block, both
|
||||
* bits are set together on a successful zeroing.
|
||||
*/
|
||||
int ext4_zero_partial_blocks(struct inode *inode, loff_t lstart, loff_t length,
|
||||
bool *did_zero)
|
||||
unsigned int *partial_zeroed)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
unsigned partial_start, partial_end;
|
||||
ext4_fsblk_t start, end;
|
||||
loff_t byte_end = (lstart + length - 1);
|
||||
bool did_zero = false;
|
||||
int err = 0;
|
||||
|
||||
partial_start = lstart & (sb->s_blocksize - 1);
|
||||
@@ -4305,21 +4318,32 @@ int ext4_zero_partial_blocks(struct inode *inode, loff_t lstart, loff_t length,
|
||||
/* Handle partial zero within the single block */
|
||||
if (start == end &&
|
||||
(partial_start || (partial_end != sb->s_blocksize - 1))) {
|
||||
err = ext4_block_zero_range(inode, lstart, length, did_zero,
|
||||
err = ext4_block_zero_range(inode, lstart, length, &did_zero,
|
||||
NULL);
|
||||
if (did_zero)
|
||||
*partial_zeroed |= (EXT4_PARTIAL_ZERO_START |
|
||||
EXT4_PARTIAL_ZERO_END);
|
||||
return err;
|
||||
}
|
||||
/* Handle partial zero out on the start of the range */
|
||||
if (partial_start) {
|
||||
err = ext4_block_zero_range(inode, lstart, sb->s_blocksize,
|
||||
did_zero, NULL);
|
||||
&did_zero, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
if (did_zero)
|
||||
*partial_zeroed |= EXT4_PARTIAL_ZERO_START;
|
||||
}
|
||||
/* Handle partial zero out on the end of the range */
|
||||
if (partial_end != sb->s_blocksize - 1)
|
||||
if (partial_end != sb->s_blocksize - 1) {
|
||||
did_zero = false;
|
||||
err = ext4_block_zero_range(inode, byte_end - partial_end,
|
||||
partial_end + 1, did_zero, NULL);
|
||||
partial_end + 1, &did_zero, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
if (did_zero)
|
||||
*partial_zeroed |= EXT4_PARTIAL_ZERO_END;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -4468,7 +4492,7 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
|
||||
loff_t end = offset + length;
|
||||
handle_t *handle;
|
||||
unsigned int credits;
|
||||
bool partial_zeroed = false;
|
||||
unsigned int partial_zeroed = 0;
|
||||
int ret;
|
||||
|
||||
trace_ext4_punch_hole(inode, offset, length, 0);
|
||||
|
||||
Reference in New Issue
Block a user