[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251103-dir-deleg-ro-v4-10-961b67adee89@kernel.org>
Date: Mon, 03 Nov 2025 07:52:38 -0500
From: Jeff Layton <jlayton@...nel.org>
To: 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>
Cc: 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,
Jeff Layton <jlayton@...nel.org>
Subject: [PATCH v4 10/17] vfs: make vfs_create break delegations on parent
directory
In order to add directory delegation support, we need to break
delegations on the parent whenever there is going to be a change in the
directory.
Add a delegated_inode parameter to struct createdata. Most callers just
leave that as a NULL pointer, but do_mknodat() is changed to wait for a
delegation break if there is one.
Signed-off-by: Jeff Layton <jlayton@...nel.org>
---
fs/namei.c | 26 +++++++++++++++++---------
include/linux/fs.h | 2 +-
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index fdf4e78cd041de8c564b7d1d89a46ba2aaf79d53..e8973000a312fb05ebb63a0d9bd83b9a5f8f805d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3487,6 +3487,9 @@ int vfs_create(struct createdata *args)
mode = vfs_prepare_mode(idmap, dir, mode, S_IALLUGO, S_IFREG);
error = security_inode_create(dir, dentry, mode);
+ if (error)
+ return error;
+ error = try_break_deleg(dir, args->delegated_inode);
if (error)
return error;
error = dir->i_op->create(idmap, dir, dentry, mode, args->excl);
@@ -4359,6 +4362,8 @@ static int may_mknod(umode_t mode)
static int do_mknodat(int dfd, struct filename *name, umode_t mode,
unsigned int dev)
{
+ struct delegated_inode delegated_inode = { };
+ struct createdata cargs = { };
struct mnt_idmap *idmap;
struct dentry *dentry;
struct path path;
@@ -4383,18 +4388,16 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
switch (mode & S_IFMT) {
case 0:
case S_IFREG:
- {
- struct createdata args = { .idmap = idmap,
- .dir = path.dentry->d_inode,
- .dentry = dentry,
- .mode = mode,
- .excl = true };
-
- error = vfs_create(&args);
+ cargs.idmap = idmap,
+ cargs.dir = path.dentry->d_inode,
+ cargs.dentry = dentry,
+ cargs.delegated_inode = &delegated_inode;
+ cargs.mode = mode,
+ cargs.excl = true,
+ error = vfs_create(&cargs);
if (!error)
security_path_post_mknod(idmap, dentry);
break;
- }
case S_IFCHR: case S_IFBLK:
error = vfs_mknod(idmap, path.dentry->d_inode,
dentry, mode, new_decode_dev(dev));
@@ -4406,6 +4409,11 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
}
out2:
end_creating_path(&path, dentry);
+ if (is_delegated(&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/include/linux/fs.h b/include/linux/fs.h
index b61873767b37591aecadd147623d7dfc866bef82..cfcb20a7c4ce4b6dcec98b3eccbdb5ec8bab6fa9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2116,12 +2116,12 @@ struct createdata {
struct mnt_idmap *idmap; // idmap of the mount the inode was found from
struct inode *dir; // inode of parent directory
struct dentry *dentry; // dentry of the child file
+ struct delegated_inode *delegated_inode; // returns parent inode, if delegated
umode_t mode; // mode of the child file
bool excl; // whether the file must not yet exist
};
int vfs_create(struct createdata *);
-
struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *,
struct dentry *, umode_t, struct delegated_inode *);
int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
--
2.51.1
Powered by blists - more mailing lists