Re: [PATCH v3 02/22] ext4: factor out ext4_truncate_[up|down]()
From: Jan Kara
Date: Thu Apr 30 2026 - 08:55:57 EST
On Wed 22-04-26 10:10:22, Zhang Yi wrote:
> From: Zhang Yi <yi.zhang@xxxxxxxxxx>
>
> Refactor ext4_setattr() by introducing two helper functions,
> ext4_truncate_up() and ext4_truncate_down(), to handle size changes. The
> current ATTR_SIZE processing consolidates checks for both shrinking and
> non-shrinking cases, leading to cluttered code. Separating the
> truncation paths improves readability.
>
> Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx>
Looks good. Just a few nits below.
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 94283a991e5c..9e4353432325 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -3501,6 +3501,23 @@ static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize)
> return changed;
> }
>
> +/*
> + * Set i_size and i_disksize to 'newsize'.
> + *
> + * Both i_rwsem and i_data_sem are required here to avoid races between
> + * generic append writeback and concurrent truncate that also modify
> + * i_size and i_disksize.
> + */
> +static inline void ext4_set_inode_size(struct inode *inode, loff_t newsize)
> +{
> + WARN_ON_ONCE(S_ISREG(inode->i_mode) && !inode_is_locked(inode));
> +
> + down_write(&EXT4_I(inode)->i_data_sem);
> + i_size_write(inode, newsize);
> + EXT4_I(inode)->i_disksize = newsize;
> + up_write(&EXT4_I(inode)->i_data_sem);
> +}
> +
Do we need this in the header later or can we keep it local to inode.c?
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 0751dc55e94f..5e913aca6499 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5855,6 +5855,83 @@ static void ext4_wait_for_tail_page_commit(struct inode *inode)
> }
> }
>
> +static int ext4_truncate_up(struct inode *inode, loff_t oldsize, loff_t newsize)
> +{
> + ext4_lblk_t old_lblk, new_lblk;
> + handle_t *handle;
> + int ret;
> +
> + if (!IS_ALIGNED(oldsize | newsize, i_blocksize(inode))) {
> + ret = ext4_inode_attach_jinode(inode);
> + if (ret)
> + return ret;
> + }
> +
> + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
> + if (oldsize & (i_blocksize(inode) - 1)) {
When you transitioned to IS_ALIGNED above, use it here as well?
> + ret = ext4_block_zero_eof(inode, oldsize, LLONG_MAX);
> + if (ret)
> + return ret;
> + }
...
> + if (attr->ia_size > oldsize)
> + error = ext4_truncate_up(inode, oldsize, attr->ia_size);
> + else if (shrink)
> + error = ext4_truncate_down(inode, oldsize,
> + attr->ia_size, &orphan);
> + if (error)
> + goto out_mmap_sem;
>
> /*
> * Truncate pagecache after we've waited for commit
Hum, why not move the truncate_pagecache() call and ext4_truncate() call
into ext4_truncate_down()? They are not needed in the truncate up case...
Honza
--
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR