[lvc-project] [PATCH 5.10/5.15 1/1] fuse: don't increment nlink in link()
Fedor Pchelkin
pchelkin at ispras.ru
Fri Jun 20 12:49:41 MSK 2025
On Wed, 18. Jun 14:44, d.privalov wrote:
> From: Miklos Szeredi <mszeredi at redhat.com>
>
> commit 97f044f690bac2b094bfb7fb2d177ef946c85880 upstream.
>
> The fuse_iget() call in create_new_entry() already updated the inode with
> all the new attributes and incremented the attribute version.
>
> Incrementing the nlink will result in the wrong count. This wasn't noticed
> because the attributes were invalidated right after this.
>
> Updating ctime is still needed for the writeback case when the ctime is not
> refreshed.
>
> Signed-off-by: Miklos Szeredi <mszeredi at redhat.com>
Проведённую нетривиальную адаптацию стоит кратко описывать, чтобы у
читателей патча формировалось представление, по каким причинам были
выбраны те или иные решения.
> Signed-off-by: Dmitriy Privalov <d.privalov at omp.ru>
> ---
> fs/fuse/dir.c | 29 ++++++++++-------------------
> 1 file changed, 10 insertions(+), 19 deletions(-)
>
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index 4488a53a192d..7055fdc1b8ce 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -807,7 +807,7 @@ void fuse_flush_time_update(struct inode *inode)
> mapping_set_error(inode->i_mapping, err);
> }
>
> -void fuse_update_ctime(struct inode *inode)
> +static void fuse_update_ctime_in_cache(struct inode *inode)
> {
> if (!IS_NOCMTIME(inode)) {
> inode->i_ctime = current_time(inode);
> @@ -816,6 +816,12 @@ void fuse_update_ctime(struct inode *inode)
> }
> }
>
> +void fuse_update_ctime(struct inode *inode)
> +{
> + fuse_invalidate_attr(inode);
> + fuse_update_ctime_in_cache(inode);
> +}
В других местах вызова fuse_update_ctime() в контексте 5.10 будет дважды
вызываться fuse_invalidate_attr(), что как бы не то чтобы что-то
серьёзное, но указывает на не до конца продуманную адаптацию.
Стоит в целом проанализировать мёрдж
- cdd39b0539c4 ("Merge tag 'fuse-update-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse")
и возможно рассмотреть патчи для предварительного переноса
- 371e8fd02969 ("fuse: move fuse_invalidate_attr() into fuse_update_ctime()")
- cefd1b83275d ("fuse: decrement nlink on overwriting rename")
> +
> static int fuse_unlink(struct inode *dir, struct dentry *entry)
> {
> int err;
> @@ -986,25 +992,10 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
> args.in_args[1].size = newent->d_name.len + 1;
> args.in_args[1].value = newent->d_name.name;
> err = create_new_entry(fm, &args, newdir, newent, inode->i_mode);
> - /* Contrary to "normal" filesystems it can happen that link
> - makes two "logical" inodes point to the same "physical"
> - inode. We invalidate the attributes of the old one, so it
> - will reflect changes in the backing inode (link count,
> - etc.)
> - */
> - if (!err) {
> - struct fuse_inode *fi = get_fuse_inode(inode);
> -
> - spin_lock(&fi->lock);
> - fi->attr_version = atomic64_inc_return(&fm->fc->attr_version);
> - if (likely(inode->i_nlink < UINT_MAX))
> - inc_nlink(inode);
> - spin_unlock(&fi->lock);
> - fuse_invalidate_attr(inode);
> - fuse_update_ctime(inode);
> - } else if (err == -EINTR) {
> + if (!err)
> + fuse_update_ctime_in_cache(inode);
> + else if (err == -EINTR)
> fuse_invalidate_attr(inode);
> - }
> return err;
> }
>
> --
> 2.34.1
More information about the lvc-project
mailing list