Re: [PATCH v5 14/14] VFS: introduce end_creating_keep()

Jeff Layton <[email protected]>
Newsgroups org.kernel.vger.ecryptfs,dev.linux.lists.netfs,org.kernel.vger.linux-cifs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-nfs,org.kernel.vger.linux-security-module,org.kernel.vger.linux-unionfs,org.kernel.vger.linux-xfs,org.kernel.vger.selinux
Message-ID <[email protected]>
On Thu, 2025-11-06 at 11:50 +1100, NeilBrown wrote:
> From: NeilBrown <[email protected]>
> 
> Occasionally the caller of end_creating() wants to keep using the dentry.
> Rather then requiring them to dget() the dentry (when not an error)
> before calling end_creating(), provide end_creating_keep() which does
> this.
> 
> cachefiles and overlayfs make use of this.
> 
> Reviewed-by: Amir Goldstein <[email protected]>
> Signed-off-by: NeilBrown <[email protected]>
> ---
>  fs/cachefiles/namei.c |  3 +--
>  fs/overlayfs/dir.c    |  8 ++------
>  fs/overlayfs/super.c  | 11 +++--------
>  include/linux/namei.h | 22 ++++++++++++++++++++++
>  4 files changed, 28 insertions(+), 16 deletions(-)
> 
> diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
> index 59327618ac42..ef22ac19545b 100644
> --- a/fs/cachefiles/namei.c
> +++ b/fs/cachefiles/namei.c
> @@ -155,8 +155,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
>  
>  	/* Tell rmdir() it's not allowed to delete the subdir */
>  	inode_lock(d_inode(subdir));
> -	dget(subdir);
> -	end_creating(subdir);
> +	end_creating_keep(subdir);
>  
>  	if (!__cachefiles_mark_inode_in_use(NULL, d_inode(subdir))) {
>  		pr_notice("cachefiles: Inode already in use: %pd (B=%lx)\n",
> diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
> index a4a0dc261310..50717ff8cac7 100644
> --- a/fs/overlayfs/dir.c
> +++ b/fs/overlayfs/dir.c
> @@ -252,10 +252,7 @@ struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir,
>  	if (IS_ERR(ret))
>  		return ret;
>  	ret = ovl_create_real(ofs, workdir, ret, attr);
> -	if (!IS_ERR(ret))
> -		dget(ret);
> -	end_creating(ret);
> -	return ret;
> +	return end_creating_keep(ret);
>  }
>  
>  static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper,
> @@ -365,8 +362,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
>  	if (IS_ERR(newdentry))
>  		return PTR_ERR(newdentry);
>  
> -	dget(newdentry);
> -	end_creating(newdentry);
> +	end_creating_keep(newdentry);
>  
>  	if (ovl_type_merge(dentry->d_parent) && d_is_dir(newdentry) &&
>  	    !ovl_allow_offline_changes(ofs)) {
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index 3acda985c8a3..7b8fc1cab6eb 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -319,8 +319,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
>  		};
>  
>  		if (work->d_inode) {
> -			dget(work);
> -			end_creating(work);
> +			end_creating_keep(work);
>  			if (persist)
>  				return work;
>  			err = -EEXIST;
> @@ -336,9 +335,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
>  		}
>  
>  		work = ovl_do_mkdir(ofs, dir, work, attr.ia_mode);
> -		if (!IS_ERR(work))
> -			dget(work);
> -		end_creating(work);
> +		end_creating_keep(work);
>  		err = PTR_ERR(work);
>  		if (IS_ERR(work))
>  			goto out_err;
> @@ -630,9 +627,7 @@ static struct dentry *ovl_lookup_or_create(struct ovl_fs *ofs,
>  		if (!child->d_inode)
>  			child = ovl_create_real(ofs, parent, child,
>  						OVL_CATTR(mode));
> -		if (!IS_ERR(child))
> -			dget(child);
> -		end_creating(child);
> +		end_creating_keep(child);
>  	}
>  	dput(parent);
>  
> diff --git a/include/linux/namei.h b/include/linux/namei.h
> index b4d95b79b5a8..58600cf234bc 100644
> --- a/include/linux/namei.h
> +++ b/include/linux/namei.h
> @@ -126,6 +126,28 @@ static inline void end_creating(struct dentry *child)
>  	end_dirop(child);
>  }
>  
> +/* end_creating_keep - finish action started with start_creating() and return result
> + * @child: dentry returned by start_creating() or vfs_mkdir()
> + *
> + * Unlock and return the child. This can be called after
> + * start_creating() whether that function succeeded or not,
> + * but it is not needed on failure.
> + *
> + * If vfs_mkdir() was called then the value returned from that function
> + * should be given for @child rather than the original dentry, as vfs_mkdir()
> + * may have provided a new dentry.
> + *
> + * Returns: @child, which may be a dentry or an error.
> + *
> + */
> +static inline struct dentry *end_creating_keep(struct dentry *child)
> +{
> +	if (!IS_ERR(child))
> +		dget(child);
> +	end_dirop(child);
> +	return child;
> +}
> +
>  /**
>   * end_removing - finish action started with start_removing
>   * @child:  dentry returned by start_removing()

Reviewed-by: Jeff Layton <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.