[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <od3ovbtjf3hc3htk6wxhb4t7wpq3he53dm3l23d456o4yjbe4t@tooasyi3jer4>
Date: Wed, 22 Oct 2025 11:01:22 +0200
From: Jan Kara <jack@...e.cz>
To: Jeff Layton <jlayton@...nel.org>
Cc: Miklos Szeredi <miklos@...redi.hu>,
Alexander Viro <viro@...iv.linux.org.uk>, Christian Brauner <brauner@...nel.org>, Jan Kara <jack@...e.cz>,
Chuck Lever <chuck.lever@...cle.com>, Alexander Aring <alex.aring@...il.com>,
Trond Myklebust <trondmy@...nel.org>, Anna Schumaker <anna@...nel.org>,
Steve French <sfrench@...ba.org>, Paulo Alcantara <pc@...guebit.org>,
Ronnie Sahlberg <ronniesahlberg@...il.com>, Shyam Prasad N <sprasad@...rosoft.com>,
Tom Talpey <tom@...pey.com>, Bharath SM <bharathsm@...rosoft.com>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>, "Rafael J. Wysocki" <rafael@...nel.org>,
Danilo Krummrich <dakr@...nel.org>, David Howells <dhowells@...hat.com>,
Tyler Hicks <code@...icks.com>, NeilBrown <neil@...wn.name>,
Olga Kornievskaia <okorniev@...hat.com>, Dai Ngo <Dai.Ngo@...cle.com>,
Amir Goldstein <amir73il@...il.com>, Namjae Jeon <linkinjeon@...nel.org>,
Steve French <smfrench@...il.com>, Sergey Senozhatsky <senozhatsky@...omium.org>,
Carlos Maiolino <cem@...nel.org>, Kuniyuki Iwashima <kuniyu@...gle.com>,
"David S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>, Simon Horman <horms@...nel.org>,
linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org, linux-nfs@...r.kernel.org,
linux-cifs@...r.kernel.org, samba-technical@...ts.samba.org, netfs@...ts.linux.dev,
ecryptfs@...r.kernel.org, linux-unionfs@...r.kernel.org, linux-xfs@...r.kernel.org,
netdev@...r.kernel.org
Subject: Re: [PATCH v3 08/13] vfs: make vfs_symlink break delegations on
parent dir
On Tue 21-10-25 11:25:43, Jeff Layton wrote:
> In order to add directory delegation support, we must break delegations
> on the parent on any change to the directory.
>
> Add a delegated_inode parameter to vfs_symlink() and have it break the
> delegation. do_symlinkat() can then wait on the delegation break before
> proceeding.
>
> Signed-off-by: Jeff Layton <jlayton@...nel.org>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@...e.cz>
Honza
> ---
> fs/ecryptfs/inode.c | 2 +-
> fs/init.c | 2 +-
> fs/namei.c | 16 ++++++++++++++--
> fs/nfsd/vfs.c | 2 +-
> fs/overlayfs/overlayfs.h | 2 +-
> include/linux/fs.h | 2 +-
> 6 files changed, 19 insertions(+), 7 deletions(-)
>
> diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
> index 639ae42bcd56890d04592f7269e4ffc099b44f09..d430ec5a63094ea4cd42828e7d44f0f8d918fcec 100644
> --- a/fs/ecryptfs/inode.c
> +++ b/fs/ecryptfs/inode.c
> @@ -480,7 +480,7 @@ static int ecryptfs_symlink(struct mnt_idmap *idmap,
> if (rc)
> goto out_lock;
> rc = vfs_symlink(&nop_mnt_idmap, lower_dir, lower_dentry,
> - encoded_symname);
> + encoded_symname, NULL);
> kfree(encoded_symname);
> if (rc || d_really_is_negative(lower_dentry))
> goto out_lock;
> diff --git a/fs/init.c b/fs/init.c
> index 4f02260dd65b0dfcbfbf5812d2ec6a33444a3b1f..e0f5429c0a49d046bd3f231a260954ed0f90ef44 100644
> --- a/fs/init.c
> +++ b/fs/init.c
> @@ -209,7 +209,7 @@ int __init init_symlink(const char *oldname, const char *newname)
> error = security_path_symlink(&path, dentry, oldname);
> if (!error)
> error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
> - dentry, oldname);
> + dentry, oldname, NULL);
> end_creating_path(&path, dentry);
> return error;
> }
> diff --git a/fs/namei.c b/fs/namei.c
> index 7e400cbdbc6af1c72eb684f051d0571e944a27d7..71af256cdd941e200389570538f64a3f795e6c83 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -4851,6 +4851,7 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname)
> * @dir: inode of the parent directory
> * @dentry: dentry of the child symlink file
> * @oldname: name of the file to link to
> + * @delegated_inode: returns victim inode, if the inode is delegated.
> *
> * Create a symlink.
> *
> @@ -4861,7 +4862,8 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname)
> * raw inode simply pass @nop_mnt_idmap.
> */
> int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
> - struct dentry *dentry, const char *oldname)
> + struct dentry *dentry, const char *oldname,
> + struct inode **delegated_inode)
> {
> int error;
>
> @@ -4876,6 +4878,10 @@ int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
> if (error)
> return error;
>
> + error = try_break_deleg(dir, delegated_inode);
> + if (error)
> + return error;
> +
> error = dir->i_op->symlink(idmap, dir, dentry, oldname);
> if (!error)
> fsnotify_create(dir, dentry);
> @@ -4889,6 +4895,7 @@ int do_symlinkat(struct filename *from, int newdfd, struct filename *to)
> struct dentry *dentry;
> struct path path;
> unsigned int lookup_flags = 0;
> + struct inode *delegated_inode = NULL;
>
> if (IS_ERR(from)) {
> error = PTR_ERR(from);
> @@ -4903,8 +4910,13 @@ int do_symlinkat(struct filename *from, int newdfd, struct filename *to)
> error = security_path_symlink(&path, dentry, from->name);
> if (!error)
> error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
> - dentry, from->name);
> + dentry, from->name, &delegated_inode);
> end_creating_path(&path, dentry);
> + if (delegated_inode) {
> + error = break_deleg_wait(&delegated_inode);
> + if (!error)
> + goto retry;
> + }
> if (retry_estale(error, lookup_flags)) {
> lookup_flags |= LOOKUP_REVAL;
> goto retry;
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index 44debf3d0be450ddc245e2fa4f57fe076e1454a2..386f454badce7ed448399ef93e9c8edafbcc4d79 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -1829,7 +1829,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
> err = fh_fill_pre_attrs(fhp);
> if (err != nfs_ok)
> goto out_unlock;
> - host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path);
> + host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path, NULL);
> err = nfserrno(host_err);
> cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
> if (!err)
> diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> index 87b82dada7ec1b8429299c68078cda24176c5607..94bb4540f7ae2e0571b3b88393c180bd73c3c09c 100644
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@ -267,7 +267,7 @@ static inline int ovl_do_symlink(struct ovl_fs *ofs,
> struct inode *dir, struct dentry *dentry,
> const char *oldname)
> {
> - int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname);
> + int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname, NULL);
>
> pr_debug("symlink(\"%s\", %pd2) = %i\n", oldname, dentry, err);
> return err;
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index a1e1afe39e01a46bf0a81e241b92690947402851..d8c7245da3bf3200b435c7ea6cafcf7903ebf293 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -2117,7 +2117,7 @@ struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *,
> int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
> umode_t, dev_t, struct inode **);
> int vfs_symlink(struct mnt_idmap *, struct inode *,
> - struct dentry *, const char *);
> + struct dentry *, const char *, struct inode **);
> int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *,
> struct dentry *, struct inode **);
> int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *,
>
> --
> 2.51.0
>
--
Jan Kara <jack@...e.com>
SUSE Labs, CR
Powered by blists - more mailing lists