public inbox for io-uring@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/8] experimental struct filename followups
@ 2026-01-08  7:41 Al Viro
  2026-01-08  7:41 ` [RFC PATCH 1/8] non-consuming variant of do_renameat2() Al Viro
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:41 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

This series switches the filename-consuming primitives to variants
that leave dropping the reference(s) to caller.  These days it's
fairly painless, and results look simpler wrt lifetime rules:
	* with 3 exceptions, all instances have constructors and destructors
happen in the same scope (via CLASS(filename...), at that)
	* CLASS(filename_consume) has no users left, could be dropped.
	* exceptions are:
		* audit dropping the references it stashed in audit_names
		* fsconfig(2) creating and dropping references in two subcommands
		* fs_lookup_param() playing silly buggers.
	  That's it.
If we go that way, this will certainly get reordered back into the main series
and have several commits in there ripped apart and folded into these ones.
E.g. no sense to convert do_renameat2() et.al. to filename_consume, only to
have that followed by the first 6 commits here, etc.

For now I've put those into #experimental.filename, on top of #work.filename.
Comments would be very welcome...

Al Viro (8):
  non-consuming variant of do_renameat2()
  non-consuming variant of do_linkat()
  non-consuming variant of do_symlinkat()
  non-consuming variant of do_mkdirat()
  non-consuming variant of do_mknodat()
  non-consuming variants of do_{unlinkat,rmdir}()
  execve: fold {compat_,}do_execve{,at}() into their sole callers
  do_execveat_common(): don't consume filename reference

 Documentation/filesystems/porting.rst |  8 +++
 fs/coredump.c                         |  3 +-
 fs/exec.c                             | 87 ++++++++-------------------
 fs/init.c                             | 22 ++++---
 fs/internal.h                         | 14 ++---
 fs/namei.c                            | 87 +++++++++++++++------------
 io_uring/fs.c                         | 25 +++++---
 7 files changed, 117 insertions(+), 129 deletions(-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC PATCH 1/8] non-consuming variant of do_renameat2()
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
@ 2026-01-08  7:41 ` Al Viro
  2026-01-08  7:41 ` [RFC PATCH 2/8] non-consuming variant of do_linkat() Al Viro
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:41 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

filename_renameat2() replaces do_renameat2(); unlike the latter,
it does not drop filename references - these days it can be just
as easily arranged in the caller.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 Documentation/filesystems/porting.rst |  8 ++++++++
 fs/internal.h                         |  2 +-
 fs/namei.c                            | 21 +++++++++++----------
 io_uring/fs.c                         |  7 ++++---
 4 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 3397937ed838..577f7f952a51 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1334,3 +1334,11 @@ end_creating() and the parent will be unlocked precisely when necessary.
 
 kill_litter_super() is gone; convert to DCACHE_PERSISTENT use (as all
 in-tree filesystems have done).
+
+---
+
+**mandatory**
+
+do_renameat2() is gone; filename_renameat2() replaces it.  The difference
+is that the former used to consume filename references; the latter does
+not.
diff --git a/fs/internal.h b/fs/internal.h
index 4c4d2733c47a..5047cfbb8c93 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -57,7 +57,7 @@ extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
 int do_rmdir(int dfd, struct filename *name);
 int do_unlinkat(int dfd, struct filename *name);
 int may_linkat(struct mnt_idmap *idmap, const struct path *link);
-int do_renameat2(int olddfd, struct filename *oldname, int newdfd,
+int filename_renameat2(int olddfd, struct filename *oldname, int newdfd,
 		 struct filename *newname, unsigned int flags);
 int do_mkdirat(int dfd, struct filename *name, umode_t mode);
 int do_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int dev);
diff --git a/fs/namei.c b/fs/namei.c
index 7418a4e725da..c54beaf193e0 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5980,11 +5980,9 @@ int vfs_rename(struct renamedata *rd)
 }
 EXPORT_SYMBOL(vfs_rename);
 
-int do_renameat2(int olddfd, struct filename *__from, int newdfd,
-		 struct filename *__to, unsigned int flags)
+int filename_renameat2(int olddfd, struct filename *from,
+		       int newdfd, struct filename *to, unsigned int flags)
 {
-	CLASS(filename_consume, from)(__from);
-	CLASS(filename_consume, to)(__to);
 	struct renamedata rd;
 	struct path old_path, new_path;
 	struct qstr old_last, new_last;
@@ -6088,21 +6086,24 @@ int do_renameat2(int olddfd, struct filename *__from, int newdfd,
 SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
 		int, newdfd, const char __user *, newname, unsigned int, flags)
 {
-	return do_renameat2(olddfd, getname(oldname), newdfd, getname(newname),
-				flags);
+	CLASS(filename, old)(oldname);
+	CLASS(filename, new)(newname);
+	return filename_renameat2(olddfd, old, newdfd, new, flags);
 }
 
 SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
 		int, newdfd, const char __user *, newname)
 {
-	return do_renameat2(olddfd, getname(oldname), newdfd, getname(newname),
-				0);
+	CLASS(filename, old)(oldname);
+	CLASS(filename, new)(newname);
+	return filename_renameat2(olddfd, old, newdfd, new, 0);
 }
 
 SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname)
 {
-	return do_renameat2(AT_FDCWD, getname(oldname), AT_FDCWD,
-				getname(newname), 0);
+	CLASS(filename, old)(oldname);
+	CLASS(filename, new)(newname);
+	return filename_renameat2(AT_FDCWD, old, AT_FDCWD, new, 0);
 }
 
 int readlink_copy(char __user *buffer, int buflen, const char *link, int linklen)
diff --git a/io_uring/fs.c b/io_uring/fs.c
index c04c6282210a..e5829d112c9e 100644
--- a/io_uring/fs.c
+++ b/io_uring/fs.c
@@ -82,13 +82,14 @@ int io_renameat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 int io_renameat(struct io_kiocb *req, unsigned int issue_flags)
 {
 	struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename);
+	CLASS(filename_complete_delayed, old)(&ren->oldpath);
+	CLASS(filename_complete_delayed, new)(&ren->newpath);
 	int ret;
 
 	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
-	ret = do_renameat2(ren->old_dfd, complete_getname(&ren->oldpath),
-			   ren->new_dfd, complete_getname(&ren->newpath),
-			   ren->flags);
+	ret = filename_renameat2(ren->old_dfd, old,
+				 ren->new_dfd, new, ren->flags);
 
 	req->flags &= ~REQ_F_NEED_CLEANUP;
 	io_req_set_res(req, ret, 0);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 2/8] non-consuming variant of do_linkat()
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
  2026-01-08  7:41 ` [RFC PATCH 1/8] non-consuming variant of do_renameat2() Al Viro
@ 2026-01-08  7:41 ` Al Viro
  2026-01-08  7:41 ` [RFC PATCH 3/8] non-consuming variant of do_symlinkat() Al Viro
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:41 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

similar to previous commit; replacement is filename_linkat()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 Documentation/filesystems/porting.rst |  6 +++---
 fs/init.c                             |  5 +++--
 fs/internal.h                         |  2 +-
 fs/namei.c                            | 17 +++++++++--------
 io_uring/fs.c                         |  5 +++--
 5 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 577f7f952a51..8ecbc41d6d82 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1339,6 +1339,6 @@ in-tree filesystems have done).
 
 **mandatory**
 
-do_renameat2() is gone; filename_renameat2() replaces it.  The difference
-is that the former used to consume filename references; the latter does
-not.
+do_{link,renameat2}() are gone; filename_{link,renameat2}() replaces those.
+The difference is that the former used to consume filename references;
+the latter do not.
diff --git a/fs/init.c b/fs/init.c
index da6500d2ee98..f46e54552931 100644
--- a/fs/init.c
+++ b/fs/init.c
@@ -145,8 +145,9 @@ int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
 
 int __init init_link(const char *oldname, const char *newname)
 {
-	return do_linkat(AT_FDCWD, getname_kernel(oldname),
-			 AT_FDCWD, getname_kernel(newname), 0);
+	CLASS(filename_kernel, old)(oldname);
+	CLASS(filename_kernel, new)(newname);
+	return filename_linkat(AT_FDCWD, old, AT_FDCWD, new, 0);
 }
 
 int __init init_symlink(const char *oldname, const char *newname)
diff --git a/fs/internal.h b/fs/internal.h
index 5047cfbb8c93..c9b70c2716d1 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -62,7 +62,7 @@ int filename_renameat2(int olddfd, struct filename *oldname, int newdfd,
 int do_mkdirat(int dfd, struct filename *name, umode_t mode);
 int do_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int dev);
 int do_symlinkat(struct filename *from, int newdfd, struct filename *to);
-int do_linkat(int olddfd, struct filename *old, int newdfd,
+int filename_linkat(int olddfd, struct filename *old, int newdfd,
 			struct filename *new, int flags);
 int vfs_tmpfile(struct mnt_idmap *idmap,
 		const struct path *parentpath,
diff --git a/fs/namei.c b/fs/namei.c
index c54beaf193e0..1f003ac9470e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5685,12 +5685,10 @@ EXPORT_SYMBOL(vfs_link);
  * We don't follow them on the oldname either to be compatible
  * with linux 2.0, and to avoid hard-linking to directories
  * and other special files.  --ADM
- */
-int do_linkat(int olddfd, struct filename *__old, int newdfd,
-	      struct filename *__new, int flags)
+*/
+int filename_linkat(int olddfd, struct filename *old,
+		    int newdfd, struct filename *new, int flags)
 {
-	CLASS(filename_consume, old)(__old);
-	CLASS(filename_consume, new)(__new);
 	struct mnt_idmap *idmap;
 	struct dentry *new_dentry;
 	struct path old_path, new_path;
@@ -5756,13 +5754,16 @@ int do_linkat(int olddfd, struct filename *__old, int newdfd,
 SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
 		int, newdfd, const char __user *, newname, int, flags)
 {
-	return do_linkat(olddfd, getname_uflags(oldname, flags),
-		newdfd, getname(newname), flags);
+	CLASS(filename_uflags, old)(oldname, flags);
+	CLASS(filename, new)(newname);
+	return filename_linkat(olddfd, old, newdfd, new, flags);
 }
 
 SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname)
 {
-	return do_linkat(AT_FDCWD, getname(oldname), AT_FDCWD, getname(newname), 0);
+	CLASS(filename, old)(oldname);
+	CLASS(filename, new)(newname);
+	return filename_linkat(AT_FDCWD, old, AT_FDCWD, new, 0);
 }
 
 /**
diff --git a/io_uring/fs.c b/io_uring/fs.c
index e5829d112c9e..e39cd1ca1942 100644
--- a/io_uring/fs.c
+++ b/io_uring/fs.c
@@ -280,12 +280,13 @@ int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 int io_linkat(struct io_kiocb *req, unsigned int issue_flags)
 {
 	struct io_link *lnk = io_kiocb_to_cmd(req, struct io_link);
+	CLASS(filename_complete_delayed, old)(&lnk->oldpath);
+	CLASS(filename_complete_delayed, new)(&lnk->newpath);
 	int ret;
 
 	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
-	ret = do_linkat(lnk->old_dfd, complete_getname(&lnk->oldpath),
-			lnk->new_dfd, complete_getname(&lnk->newpath), lnk->flags);
+	ret = filename_linkat(lnk->old_dfd, old, lnk->new_dfd, new, lnk->flags);
 
 	req->flags &= ~REQ_F_NEED_CLEANUP;
 	io_req_set_res(req, ret, 0);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 3/8] non-consuming variant of do_symlinkat()
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
  2026-01-08  7:41 ` [RFC PATCH 1/8] non-consuming variant of do_renameat2() Al Viro
  2026-01-08  7:41 ` [RFC PATCH 2/8] non-consuming variant of do_linkat() Al Viro
@ 2026-01-08  7:41 ` Al Viro
  2026-01-08  7:41 ` [RFC PATCH 4/8] non-consuming variant of do_mkdirat() Al Viro
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:41 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

similar to previous commit; replacement is filename_symlinkat()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 Documentation/filesystems/porting.rst |  6 +++---
 fs/init.c                             |  5 +++--
 fs/internal.h                         |  2 +-
 fs/namei.c                            | 12 +++++++-----
 io_uring/fs.c                         |  5 +++--
 5 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 8ecbc41d6d82..c44c351bc297 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1339,6 +1339,6 @@ in-tree filesystems have done).
 
 **mandatory**
 
-do_{link,renameat2}() are gone; filename_{link,renameat2}() replaces those.
-The difference is that the former used to consume filename references;
-the latter do not.
+do_{link,symlink,renameat2}() are gone; filename_...() counterparts
+replace those.  The difference is that the former used to consume
+filename references; the latter do not.
diff --git a/fs/init.c b/fs/init.c
index f46e54552931..a54ef750ffe3 100644
--- a/fs/init.c
+++ b/fs/init.c
@@ -152,8 +152,9 @@ int __init init_link(const char *oldname, const char *newname)
 
 int __init init_symlink(const char *oldname, const char *newname)
 {
-	return do_symlinkat(getname_kernel(oldname), AT_FDCWD,
-			    getname_kernel(newname));
+	CLASS(filename_kernel, old)(oldname);
+	CLASS(filename_kernel, new)(newname);
+	return filename_symlinkat(old, AT_FDCWD, new);
 }
 
 int __init init_unlink(const char *pathname)
diff --git a/fs/internal.h b/fs/internal.h
index c9b70c2716d1..4a63b89c02d7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -61,7 +61,7 @@ int filename_renameat2(int olddfd, struct filename *oldname, int newdfd,
 		 struct filename *newname, unsigned int flags);
 int do_mkdirat(int dfd, struct filename *name, umode_t mode);
 int do_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int dev);
-int do_symlinkat(struct filename *from, int newdfd, struct filename *to);
+int filename_symlinkat(struct filename *from, int newdfd, struct filename *to);
 int filename_linkat(int olddfd, struct filename *old, int newdfd,
 			struct filename *new, int flags);
 int vfs_tmpfile(struct mnt_idmap *idmap,
diff --git a/fs/namei.c b/fs/namei.c
index 1f003ac9470e..338e2934c520 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5541,10 +5541,8 @@ int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
 }
 EXPORT_SYMBOL(vfs_symlink);
 
-int do_symlinkat(struct filename *__from, int newdfd, struct filename *__to)
+int filename_symlinkat(struct filename *from, int newdfd, struct filename *to)
 {
-	CLASS(filename_consume, from)(__from);
-	CLASS(filename_consume, to)(__to);
 	int error;
 	struct dentry *dentry;
 	struct path path;
@@ -5578,12 +5576,16 @@ int do_symlinkat(struct filename *__from, int newdfd, struct filename *__to)
 SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
 		int, newdfd, const char __user *, newname)
 {
-	return do_symlinkat(getname(oldname), newdfd, getname(newname));
+	CLASS(filename, old)(oldname);
+	CLASS(filename, new)(newname);
+	return filename_symlinkat(old, newdfd, new);
 }
 
 SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newname)
 {
-	return do_symlinkat(getname(oldname), AT_FDCWD, getname(newname));
+	CLASS(filename, old)(oldname);
+	CLASS(filename, new)(newname);
+	return filename_symlinkat(old, AT_FDCWD, new);
 }
 
 /**
diff --git a/io_uring/fs.c b/io_uring/fs.c
index e39cd1ca1942..cd4d88d37795 100644
--- a/io_uring/fs.c
+++ b/io_uring/fs.c
@@ -233,12 +233,13 @@ int io_symlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 int io_symlinkat(struct io_kiocb *req, unsigned int issue_flags)
 {
 	struct io_link *sl = io_kiocb_to_cmd(req, struct io_link);
+	CLASS(filename_complete_delayed, old)(&sl->oldpath);
+	CLASS(filename_complete_delayed, new)(&sl->newpath);
 	int ret;
 
 	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
-	ret = do_symlinkat(complete_getname(&sl->oldpath), sl->new_dfd,
-			   complete_getname(&sl->newpath));
+	ret = filename_symlinkat(old, sl->new_dfd, new);
 
 	req->flags &= ~REQ_F_NEED_CLEANUP;
 	io_req_set_res(req, ret, 0);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 4/8] non-consuming variant of do_mkdirat()
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
                   ` (2 preceding siblings ...)
  2026-01-08  7:41 ` [RFC PATCH 3/8] non-consuming variant of do_symlinkat() Al Viro
@ 2026-01-08  7:41 ` Al Viro
  2026-01-08  7:41 ` [RFC PATCH 5/8] non-consuming variant of do_mknodat() Al Viro
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:41 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

similar to previous commit; replacement is filename_mkdirat()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 Documentation/filesystems/porting.rst | 2 +-
 fs/init.c                             | 3 ++-
 fs/internal.h                         | 2 +-
 fs/namei.c                            | 9 +++++----
 io_uring/fs.c                         | 3 ++-
 5 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index c44c351bc297..ace0607fe39c 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1339,6 +1339,6 @@ in-tree filesystems have done).
 
 **mandatory**
 
-do_{link,symlink,renameat2}() are gone; filename_...() counterparts
+do_{mkdir,link,symlink,renameat2}() are gone; filename_...() counterparts
 replace those.  The difference is that the former used to consume
 filename references; the latter do not.
diff --git a/fs/init.c b/fs/init.c
index a54ef750ffe3..9a550ba4802f 100644
--- a/fs/init.c
+++ b/fs/init.c
@@ -164,7 +164,8 @@ int __init init_unlink(const char *pathname)
 
 int __init init_mkdir(const char *pathname, umode_t mode)
 {
-	return do_mkdirat(AT_FDCWD, getname_kernel(pathname), mode);
+	CLASS(filename_kernel, name)(pathname);
+	return filename_mkdirat(AT_FDCWD, name, mode);
 }
 
 int __init init_rmdir(const char *pathname)
diff --git a/fs/internal.h b/fs/internal.h
index 4a63b89c02d7..03638008d84a 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -59,7 +59,7 @@ int do_unlinkat(int dfd, struct filename *name);
 int may_linkat(struct mnt_idmap *idmap, const struct path *link);
 int filename_renameat2(int olddfd, struct filename *oldname, int newdfd,
 		 struct filename *newname, unsigned int flags);
-int do_mkdirat(int dfd, struct filename *name, umode_t mode);
+int filename_mkdirat(int dfd, struct filename *name, umode_t mode);
 int do_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int dev);
 int filename_symlinkat(struct filename *from, int newdfd, struct filename *to);
 int filename_linkat(int olddfd, struct filename *old, int newdfd,
diff --git a/fs/namei.c b/fs/namei.c
index 338e2934c520..e3252d4abce4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5171,9 +5171,8 @@ struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
 }
 EXPORT_SYMBOL(vfs_mkdir);
 
-int do_mkdirat(int dfd, struct filename *__name, umode_t mode)
+int filename_mkdirat(int dfd, struct filename *name, umode_t mode)
 {
-	CLASS(filename_consume, name)(__name);
 	struct dentry *dentry;
 	struct path path;
 	int error;
@@ -5208,12 +5207,14 @@ int do_mkdirat(int dfd, struct filename *__name, umode_t mode)
 
 SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
 {
-	return do_mkdirat(dfd, getname(pathname), mode);
+	CLASS(filename, name)(pathname);
+	return filename_mkdirat(dfd, name, mode);
 }
 
 SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
 {
-	return do_mkdirat(AT_FDCWD, getname(pathname), mode);
+	CLASS(filename, name)(pathname);
+	return filename_mkdirat(AT_FDCWD, name, mode);
 }
 
 /**
diff --git a/io_uring/fs.c b/io_uring/fs.c
index cd4d88d37795..40541b539e0d 100644
--- a/io_uring/fs.c
+++ b/io_uring/fs.c
@@ -182,11 +182,12 @@ int io_mkdirat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 int io_mkdirat(struct io_kiocb *req, unsigned int issue_flags)
 {
 	struct io_mkdir *mkd = io_kiocb_to_cmd(req, struct io_mkdir);
+	CLASS(filename_complete_delayed, name)(&mkd->filename);
 	int ret;
 
 	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
-	ret = do_mkdirat(mkd->dfd, complete_getname(&mkd->filename), mkd->mode);
+	ret = filename_mkdirat(mkd->dfd, name, mkd->mode);
 
 	req->flags &= ~REQ_F_NEED_CLEANUP;
 	io_req_set_res(req, ret, 0);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 5/8] non-consuming variant of do_mknodat()
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
                   ` (3 preceding siblings ...)
  2026-01-08  7:41 ` [RFC PATCH 4/8] non-consuming variant of do_mkdirat() Al Viro
@ 2026-01-08  7:41 ` Al Viro
  2026-01-08  7:41 ` [RFC PATCH 6/8] non-consuming variants of do_{unlinkat,rmdir}() Al Viro
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:41 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

similar to previous commit; replacement is filename_mknodat()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 Documentation/filesystems/porting.rst |  6 +++---
 fs/init.c                             |  3 ++-
 fs/internal.h                         |  2 +-
 fs/namei.c                            | 11 ++++++-----
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index ace0607fe39c..7e68a148dd1e 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1339,6 +1339,6 @@ in-tree filesystems have done).
 
 **mandatory**
 
-do_{mkdir,link,symlink,renameat2}() are gone; filename_...() counterparts
-replace those.  The difference is that the former used to consume
-filename references; the latter do not.
+do_{mkdir,mknod,link,symlink,renameat2}() are gone; filename_...()
+counterparts replace those.  The difference is that the former used
+to consume filename references; the latter do not.
diff --git a/fs/init.c b/fs/init.c
index 9a550ba4802f..543444c1d79e 100644
--- a/fs/init.c
+++ b/fs/init.c
@@ -140,7 +140,8 @@ int __init init_stat(const char *filename, struct kstat *stat, int flags)
 
 int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
 {
-	return do_mknodat(AT_FDCWD, getname_kernel(filename), mode, dev);
+	CLASS(filename_kernel, name)(filename);
+	return filename_mknodat(AT_FDCWD, name, mode, dev);
 }
 
 int __init init_link(const char *oldname, const char *newname)
diff --git a/fs/internal.h b/fs/internal.h
index 03638008d84a..02b5dec13ff3 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -60,7 +60,7 @@ int may_linkat(struct mnt_idmap *idmap, const struct path *link);
 int filename_renameat2(int olddfd, struct filename *oldname, int newdfd,
 		 struct filename *newname, unsigned int flags);
 int filename_mkdirat(int dfd, struct filename *name, umode_t mode);
-int do_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int dev);
+int filename_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int dev);
 int filename_symlinkat(struct filename *from, int newdfd, struct filename *to);
 int filename_linkat(int olddfd, struct filename *old, int newdfd,
 			struct filename *new, int flags);
diff --git a/fs/namei.c b/fs/namei.c
index e3252d4abce4..1aa19dde50e4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5038,10 +5038,9 @@ static int may_mknod(umode_t mode)
 	}
 }
 
-int do_mknodat(int dfd, struct filename *__name, umode_t mode,
-		unsigned int dev)
+int filename_mknodat(int dfd, struct filename *name, umode_t mode,
+		     unsigned int dev)
 {
-	CLASS(filename_consume, name)(__name);
 	struct delegated_inode di = { };
 	struct mnt_idmap *idmap;
 	struct dentry *dentry;
@@ -5095,12 +5094,14 @@ int do_mknodat(int dfd, struct filename *__name, umode_t mode,
 SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
 		unsigned int, dev)
 {
-	return do_mknodat(dfd, getname(filename), mode, dev);
+	CLASS(filename, name)(filename);
+	return filename_mknodat(dfd, name, mode, dev);
 }
 
 SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev)
 {
-	return do_mknodat(AT_FDCWD, getname(filename), mode, dev);
+	CLASS(filename, name)(filename);
+	return filename_mknodat(AT_FDCWD, name, mode, dev);
 }
 
 /**
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 6/8] non-consuming variants of do_{unlinkat,rmdir}()
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
                   ` (4 preceding siblings ...)
  2026-01-08  7:41 ` [RFC PATCH 5/8] non-consuming variant of do_mknodat() Al Viro
@ 2026-01-08  7:41 ` Al Viro
  2026-01-08  7:42 ` [RFC PATCH 7/8] execve: fold {compat_,}do_execve{,at}() into their sole callers Al Viro
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:41 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

similar to previous commit; replacements are filename_{unlinkat,rmdir}()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 Documentation/filesystems/porting.rst |  6 +++---
 fs/coredump.c                         |  3 ++-
 fs/init.c                             |  6 ++++--
 fs/internal.h                         |  4 ++--
 fs/namei.c                            | 17 +++++++++--------
 io_uring/fs.c                         |  5 +++--
 6 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 7e68a148dd1e..2b4dddfe6c66 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1339,6 +1339,6 @@ in-tree filesystems have done).
 
 **mandatory**
 
-do_{mkdir,mknod,link,symlink,renameat2}() are gone; filename_...()
-counterparts replace those.  The difference is that the former used
-to consume filename references; the latter do not.
+do_{mkdir,mknod,link,symlink,renameat2,rmdir,unlink}() are gone; filename_...()
+counterparts replace those.  The difference is that the former used to consume
+filename references; the latter do not.
diff --git a/fs/coredump.c b/fs/coredump.c
index 8feb9c1cf83d..d9597610a6ca 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -895,11 +895,12 @@ static bool coredump_file(struct core_name *cn, struct coredump_params *cprm,
 	 * privs and don't want to unlink another user's coredump.
 	 */
 	if (!coredump_force_suid_safe(cprm)) {
+		CLASS(filename_kernel, name)(cn->corename);
 		/*
 		 * If it doesn't exist, that's fine. If there's some
 		 * other problem, we'll catch it at the filp_open().
 		 */
-		do_unlinkat(AT_FDCWD, getname_kernel(cn->corename));
+		filename_unlinkat(AT_FDCWD, name);
 	}
 
 	/*
diff --git a/fs/init.c b/fs/init.c
index 543444c1d79e..ea528b020cd1 100644
--- a/fs/init.c
+++ b/fs/init.c
@@ -160,7 +160,8 @@ int __init init_symlink(const char *oldname, const char *newname)
 
 int __init init_unlink(const char *pathname)
 {
-	return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
+	CLASS(filename_kernel, name)(pathname);
+	return filename_unlinkat(AT_FDCWD, name);
 }
 
 int __init init_mkdir(const char *pathname, umode_t mode)
@@ -171,7 +172,8 @@ int __init init_mkdir(const char *pathname, umode_t mode)
 
 int __init init_rmdir(const char *pathname)
 {
-	return do_rmdir(AT_FDCWD, getname_kernel(pathname));
+	CLASS(filename_kernel, name)(pathname);
+	return filename_rmdir(AT_FDCWD, name);
 }
 
 int __init init_utimes(char *filename, struct timespec64 *ts)
diff --git a/fs/internal.h b/fs/internal.h
index 02b5dec13ff3..4821f8b8fdda 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -54,8 +54,8 @@ extern int finish_clean_context(struct fs_context *fc);
  */
 extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
 			   struct path *path, const struct path *root);
-int do_rmdir(int dfd, struct filename *name);
-int do_unlinkat(int dfd, struct filename *name);
+int filename_rmdir(int dfd, struct filename *name);
+int filename_unlinkat(int dfd, struct filename *name);
 int may_linkat(struct mnt_idmap *idmap, const struct path *link);
 int filename_renameat2(int olddfd, struct filename *oldname, int newdfd,
 		 struct filename *newname, unsigned int flags);
diff --git a/fs/namei.c b/fs/namei.c
index 1aa19dde50e4..42b33bb0f892 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5278,9 +5278,8 @@ int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir,
 }
 EXPORT_SYMBOL(vfs_rmdir);
 
-int do_rmdir(int dfd, struct filename *__name)
+int filename_rmdir(int dfd, struct filename *name)
 {
-	CLASS(filename_consume, name)(__name);
 	int error;
 	struct dentry *dentry;
 	struct path path;
@@ -5338,7 +5337,8 @@ int do_rmdir(int dfd, struct filename *__name)
 
 SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
 {
-	return do_rmdir(AT_FDCWD, getname(pathname));
+	CLASS(filename, name)(pathname);
+	return filename_rmdir(AT_FDCWD, name);
 }
 
 /**
@@ -5420,9 +5420,8 @@ EXPORT_SYMBOL(vfs_unlink);
  * writeout happening, and we don't want to prevent access to the directory
  * while waiting on the I/O.
  */
-int do_unlinkat(int dfd, struct filename *__name)
+int filename_unlinkat(int dfd, struct filename *name)
 {
-	CLASS(filename_consume, name)(__name);
 	int error;
 	struct dentry *dentry;
 	struct path path;
@@ -5489,14 +5488,16 @@ SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag)
 	if ((flag & ~AT_REMOVEDIR) != 0)
 		return -EINVAL;
 
+	CLASS(filename, name)(pathname);
 	if (flag & AT_REMOVEDIR)
-		return do_rmdir(dfd, getname(pathname));
-	return do_unlinkat(dfd, getname(pathname));
+		return filename_rmdir(dfd, name);
+	return filename_unlinkat(dfd, name);
 }
 
 SYSCALL_DEFINE1(unlink, const char __user *, pathname)
 {
-	return do_unlinkat(AT_FDCWD, getname(pathname));
+	CLASS(filename, name)(pathname);
+	return filename_unlinkat(AT_FDCWD, name);
 }
 
 /**
diff --git a/io_uring/fs.c b/io_uring/fs.c
index 40541b539e0d..d0580c754bf8 100644
--- a/io_uring/fs.c
+++ b/io_uring/fs.c
@@ -134,14 +134,15 @@ int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags)
 {
 	struct io_unlink *un = io_kiocb_to_cmd(req, struct io_unlink);
+	CLASS(filename_complete_delayed, name)(&un->filename);
 	int ret;
 
 	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
 	if (un->flags & AT_REMOVEDIR)
-		ret = do_rmdir(un->dfd, complete_getname(&un->filename));
+		ret = filename_rmdir(un->dfd, name);
 	else
-		ret = do_unlinkat(un->dfd, complete_getname(&un->filename));
+		ret = filename_unlinkat(un->dfd, name);
 
 	req->flags &= ~REQ_F_NEED_CLEANUP;
 	io_req_set_res(req, ret, 0);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 7/8] execve: fold {compat_,}do_execve{,at}() into their sole callers
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
                   ` (5 preceding siblings ...)
  2026-01-08  7:41 ` [RFC PATCH 6/8] non-consuming variants of do_{unlinkat,rmdir}() Al Viro
@ 2026-01-08  7:42 ` Al Viro
  2026-01-08  7:42 ` [RFC PATCH 8/8] do_execveat_common(): don't consume filename reference Al Viro
  2026-01-12 10:00 ` [RFC PATCH 0/8] experimental struct filename followups Christian Brauner
  8 siblings, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:42 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

All of them are wrappers for do_execveat_common() and each has
exactly one caller.  The only difference is in the way they are
constructing argv/envp arguments for do_execveat_common() and
that's easy to do with less boilerplate.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/exec.c | 80 +++++++++++++------------------------------------------
 1 file changed, 19 insertions(+), 61 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 902561a878ff..4e192d7b7e71 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1893,59 +1893,6 @@ int kernel_execve(const char *kernel_filename,
 	return bprm_execve(bprm);
 }
 
-static int do_execve(struct filename *filename,
-	const char __user *const __user *__argv,
-	const char __user *const __user *__envp)
-{
-	struct user_arg_ptr argv = { .ptr.native = __argv };
-	struct user_arg_ptr envp = { .ptr.native = __envp };
-	return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
-}
-
-static int do_execveat(int fd, struct filename *filename,
-		const char __user *const __user *__argv,
-		const char __user *const __user *__envp,
-		int flags)
-{
-	struct user_arg_ptr argv = { .ptr.native = __argv };
-	struct user_arg_ptr envp = { .ptr.native = __envp };
-
-	return do_execveat_common(fd, filename, argv, envp, flags);
-}
-
-#ifdef CONFIG_COMPAT
-static int compat_do_execve(struct filename *filename,
-	const compat_uptr_t __user *__argv,
-	const compat_uptr_t __user *__envp)
-{
-	struct user_arg_ptr argv = {
-		.is_compat = true,
-		.ptr.compat = __argv,
-	};
-	struct user_arg_ptr envp = {
-		.is_compat = true,
-		.ptr.compat = __envp,
-	};
-	return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
-}
-
-static int compat_do_execveat(int fd, struct filename *filename,
-			      const compat_uptr_t __user *__argv,
-			      const compat_uptr_t __user *__envp,
-			      int flags)
-{
-	struct user_arg_ptr argv = {
-		.is_compat = true,
-		.ptr.compat = __argv,
-	};
-	struct user_arg_ptr envp = {
-		.is_compat = true,
-		.ptr.compat = __envp,
-	};
-	return do_execveat_common(fd, filename, argv, envp, flags);
-}
-#endif
-
 void set_binfmt(struct linux_binfmt *new)
 {
 	struct mm_struct *mm = current->mm;
@@ -1970,12 +1917,18 @@ void set_dumpable(struct mm_struct *mm, int value)
 	__mm_flags_set_mask_dumpable(mm, value);
 }
 
+static inline struct user_arg_ptr native_arg(const char __user *const __user *p)
+{
+	return (struct user_arg_ptr){.ptr.native = p};
+}
+
 SYSCALL_DEFINE3(execve,
 		const char __user *, filename,
 		const char __user *const __user *, argv,
 		const char __user *const __user *, envp)
 {
-	return do_execve(getname(filename), argv, envp);
+	return do_execveat_common(AT_FDCWD, getname(filename),
+				  native_arg(argv), native_arg(envp), 0);
 }
 
 SYSCALL_DEFINE5(execveat,
@@ -1984,17 +1937,23 @@ SYSCALL_DEFINE5(execveat,
 		const char __user *const __user *, envp,
 		int, flags)
 {
-	return do_execveat(fd,
-			   getname_uflags(filename, flags),
-			   argv, envp, flags);
+	return do_execveat_common(fd, getname_uflags(filename, flags),
+				  native_arg(argv), native_arg(envp), flags);
 }
 
 #ifdef CONFIG_COMPAT
+
+static inline struct user_arg_ptr compat_arg(const compat_uptr_t __user *p)
+{
+	return (struct user_arg_ptr){.is_compat = true, .ptr.compat = p};
+}
+
 COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename,
 	const compat_uptr_t __user *, argv,
 	const compat_uptr_t __user *, envp)
 {
-	return compat_do_execve(getname(filename), argv, envp);
+	return do_execveat_common(AT_FDCWD, getname(filename),
+				  compat_arg(argv), compat_arg(envp), 0);
 }
 
 COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
@@ -2003,9 +1962,8 @@ COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
 		       const compat_uptr_t __user *, envp,
 		       int,  flags)
 {
-	return compat_do_execveat(fd,
-				  getname_uflags(filename, flags),
-				  argv, envp, flags);
+	return do_execveat_common(fd, getname_uflags(filename, flags),
+				  compat_arg(argv), compat_arg(envp), flags);
 }
 #endif
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 8/8] do_execveat_common(): don't consume filename reference
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
                   ` (6 preceding siblings ...)
  2026-01-08  7:42 ` [RFC PATCH 7/8] execve: fold {compat_,}do_execve{,at}() into their sole callers Al Viro
@ 2026-01-08  7:42 ` Al Viro
  2026-01-12 10:00 ` [RFC PATCH 0/8] experimental struct filename followups Christian Brauner
  8 siblings, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-08  7:42 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: torvalds, brauner, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel

... and convert its callers to CLASS(filename...)

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/exec.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 4e192d7b7e71..3405c754da80 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1775,12 +1775,11 @@ static int bprm_execve(struct linux_binprm *bprm)
 	return retval;
 }
 
-static int do_execveat_common(int fd, struct filename *__filename,
+static int do_execveat_common(int fd, struct filename *filename,
 			      struct user_arg_ptr argv,
 			      struct user_arg_ptr envp,
 			      int flags)
 {
-	CLASS(filename_consume, filename)(__filename);
 	int retval;
 
 	/*
@@ -1927,7 +1926,8 @@ SYSCALL_DEFINE3(execve,
 		const char __user *const __user *, argv,
 		const char __user *const __user *, envp)
 {
-	return do_execveat_common(AT_FDCWD, getname(filename),
+	CLASS(filename, name)(filename);
+	return do_execveat_common(AT_FDCWD, name,
 				  native_arg(argv), native_arg(envp), 0);
 }
 
@@ -1937,7 +1937,8 @@ SYSCALL_DEFINE5(execveat,
 		const char __user *const __user *, envp,
 		int, flags)
 {
-	return do_execveat_common(fd, getname_uflags(filename, flags),
+	CLASS(filename_uflags, name)(filename, flags);
+	return do_execveat_common(fd, name,
 				  native_arg(argv), native_arg(envp), flags);
 }
 
@@ -1952,7 +1953,8 @@ COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename,
 	const compat_uptr_t __user *, argv,
 	const compat_uptr_t __user *, envp)
 {
-	return do_execveat_common(AT_FDCWD, getname(filename),
+	CLASS(filename, name)(filename);
+	return do_execveat_common(AT_FDCWD, name,
 				  compat_arg(argv), compat_arg(envp), 0);
 }
 
@@ -1962,7 +1964,8 @@ COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
 		       const compat_uptr_t __user *, envp,
 		       int,  flags)
 {
-	return do_execveat_common(fd, getname_uflags(filename, flags),
+	CLASS(filename_uflags, name)(filename, flags);
+	return do_execveat_common(fd, name,
 				  compat_arg(argv), compat_arg(envp), flags);
 }
 #endif
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/8] experimental struct filename followups
  2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
                   ` (7 preceding siblings ...)
  2026-01-08  7:42 ` [RFC PATCH 8/8] do_execveat_common(): don't consume filename reference Al Viro
@ 2026-01-12 10:00 ` Christian Brauner
  2026-01-14  2:15   ` Al Viro
  8 siblings, 1 reply; 13+ messages in thread
From: Christian Brauner @ 2026-01-12 10:00 UTC (permalink / raw)
  To: Al Viro
  Cc: linux-fsdevel, torvalds, jack, mjguzik, paul, axboe, audit,
	io-uring, linux-kernel

On Thu, Jan 08, 2026 at 07:41:53AM +0000, Al Viro wrote:
> This series switches the filename-consuming primitives to variants
> that leave dropping the reference(s) to caller.  These days it's
> fairly painless, and results look simpler wrt lifetime rules:
> 	* with 3 exceptions, all instances have constructors and destructors
> happen in the same scope (via CLASS(filename...), at that)
> 	* CLASS(filename_consume) has no users left, could be dropped.
> 	* exceptions are:
> 		* audit dropping the references it stashed in audit_names
> 		* fsconfig(2) creating and dropping references in two subcommands
> 		* fs_lookup_param() playing silly buggers.
> 	  That's it.
> If we go that way, this will certainly get reordered back into the main series
> and have several commits in there ripped apart and folded into these ones.
> E.g. no sense to convert do_renameat2() et.al. to filename_consume, only to
> have that followed by the first 6 commits here, etc.
> 
> For now I've put those into #experimental.filename, on top of #work.filename.
> Comments would be very welcome...

Yeah, that looks nice. I like this a lot more than having calleee
consume it.
Reviewed-by: Christian Brauner <brauner@kernel.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/8] experimental struct filename followups
  2026-01-12 10:00 ` [RFC PATCH 0/8] experimental struct filename followups Christian Brauner
@ 2026-01-14  2:15   ` Al Viro
  2026-01-14  2:28     ` Al Viro
  2026-01-14 16:00     ` Christian Brauner
  0 siblings, 2 replies; 13+ messages in thread
From: Al Viro @ 2026-01-14  2:15 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: linux-fsdevel, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel, Christian Brauner

On Mon, Jan 12, 2026 at 11:00:10AM +0100, Christian Brauner wrote:
> On Thu, Jan 08, 2026 at 07:41:53AM +0000, Al Viro wrote:
> > This series switches the filename-consuming primitives to variants
> > that leave dropping the reference(s) to caller.  These days it's
> > fairly painless, and results look simpler wrt lifetime rules:
> > 	* with 3 exceptions, all instances have constructors and destructors
> > happen in the same scope (via CLASS(filename...), at that)
> > 	* CLASS(filename_consume) has no users left, could be dropped.
> > 	* exceptions are:
> > 		* audit dropping the references it stashed in audit_names
> > 		* fsconfig(2) creating and dropping references in two subcommands
> > 		* fs_lookup_param() playing silly buggers.
> > 	  That's it.
> > If we go that way, this will certainly get reordered back into the main series
> > and have several commits in there ripped apart and folded into these ones.
> > E.g. no sense to convert do_renameat2() et.al. to filename_consume, only to
> > have that followed by the first 6 commits here, etc.
> > 
> > For now I've put those into #experimental.filename, on top of #work.filename.
> > Comments would be very welcome...
> 
> Yeah, that looks nice. I like this a lot more than having calleee
> consume it.
> Reviewed-by: Christian Brauner <brauner@kernel.org>

FWIW, I've folded that into #work.filename and reordered the things to a somewhat
saner shape.  Will post the updated series shortly.

Open questions:

	* Exports.  Currently we have getname_kernel() and putname()
exported, while the rest of importers is not.  There is exactly one
module using those - ksmbd, and both users in it are doing only one
thing to resulting filename: passing it to vfs_path_parent_lookup().
No other callers of vfs_path_parent_lookup() exist.

	Options:
A) replace vfs_path_parent_lookup() with
int path_parent_root(const char *filename, unsigned int flags,
                     struct path *parent, struct qstr *last, int *type,
		     const struct path *root)
{
	CLASS(filename_kernel, name)(filename);
	return  __filename_parentat(AT_FDCWD, name, flags, parent, last,
					    type, root);
}
have that exported and used in fs/smb/server/vfs.c instead of
vfs_path_parent_lookup(); unexport getname_kernel() and putname().

B) make the rest of importers (well, CLASS(filename...), really) usable
for modules as well.  Then we probably want to publish filename_lookup()
as well.  Unattractive, IMO...

	* LOOKUP_EMPTY.  IMO putting it into LOOKUP_... space had been
a mistake.  We are actually pretty close to being able to extract it
from there; I'd love to make getname_flags() take boolean instead of this
"unsigned int, but we only care about one bit in it" thing.
	There's only one obstacle - modular callers of user_path_at() that
would possibly pass LOOKUP_EMPTY in flags.  Right now there's none (in-tree,
that is)- we have only 3 modular callers in the first place and they pass
only 0 or LOOKUP_FOLLOW in flags.
	I would rather provide user_path_maybe_null() if/when such beasts
appear; it's saner for any new API anyway.  I really wish we'd done it that
way for fspick(2), but it's too late to change now...
	Note that existing non-modular callers are better off with
CLASS(filename_...) + filename_lookup().  Modular ones can't do that,
due to the lack of exports; TBH, I'd rather keep that machinery internal
to the core kernel...

	Comments?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/8] experimental struct filename followups
  2026-01-14  2:15   ` Al Viro
@ 2026-01-14  2:28     ` Al Viro
  2026-01-14 16:00     ` Christian Brauner
  1 sibling, 0 replies; 13+ messages in thread
From: Al Viro @ 2026-01-14  2:28 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: linux-fsdevel, jack, mjguzik, paul, axboe, audit, io-uring,
	linux-kernel, Christian Brauner

On Wed, Jan 14, 2026 at 02:15:47AM +0000, Al Viro wrote:
> 	* Exports.  Currently we have getname_kernel() and putname()
> exported, while the rest of importers is not.  There is exactly one
> module using those - ksmbd, and both users in it are doing only one
> thing to resulting filename: passing it to vfs_path_parent_lookup().
> No other callers of vfs_path_parent_lookup() exist.
> 
> 	Options:
> A) replace vfs_path_parent_lookup() with
> int path_parent_root(const char *filename, unsigned int flags,
>                      struct path *parent, struct qstr *last, int *type,
> 		     const struct path *root)
> {
> 	CLASS(filename_kernel, name)(filename);
> 	return  __filename_parentat(AT_FDCWD, name, flags, parent, last,
> 					    type, root);
> }
> have that exported and used in fs/smb/server/vfs.c instead of
> vfs_path_parent_lookup(); unexport getname_kernel() and putname().

Sorry, can't do - one of those is inside a retry loop.  Pity, that...

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 0/8] experimental struct filename followups
  2026-01-14  2:15   ` Al Viro
  2026-01-14  2:28     ` Al Viro
@ 2026-01-14 16:00     ` Christian Brauner
  1 sibling, 0 replies; 13+ messages in thread
From: Christian Brauner @ 2026-01-14 16:00 UTC (permalink / raw)
  To: Al Viro
  Cc: Linus Torvalds, linux-fsdevel, jack, mjguzik, paul, axboe, audit,
	io-uring, linux-kernel

On Wed, Jan 14, 2026 at 02:15:47AM +0000, Al Viro wrote:
> On Mon, Jan 12, 2026 at 11:00:10AM +0100, Christian Brauner wrote:
> > On Thu, Jan 08, 2026 at 07:41:53AM +0000, Al Viro wrote:
> > > This series switches the filename-consuming primitives to variants
> > > that leave dropping the reference(s) to caller.  These days it's
> > > fairly painless, and results look simpler wrt lifetime rules:
> > > 	* with 3 exceptions, all instances have constructors and destructors
> > > happen in the same scope (via CLASS(filename...), at that)
> > > 	* CLASS(filename_consume) has no users left, could be dropped.
> > > 	* exceptions are:
> > > 		* audit dropping the references it stashed in audit_names
> > > 		* fsconfig(2) creating and dropping references in two subcommands
> > > 		* fs_lookup_param() playing silly buggers.
> > > 	  That's it.
> > > If we go that way, this will certainly get reordered back into the main series
> > > and have several commits in there ripped apart and folded into these ones.
> > > E.g. no sense to convert do_renameat2() et.al. to filename_consume, only to
> > > have that followed by the first 6 commits here, etc.
> > > 
> > > For now I've put those into #experimental.filename, on top of #work.filename.
> > > Comments would be very welcome...
> > 
> > Yeah, that looks nice. I like this a lot more than having calleee
> > consume it.
> > Reviewed-by: Christian Brauner <brauner@kernel.org>
> 
> FWIW, I've folded that into #work.filename and reordered the things to a somewhat
> saner shape.  Will post the updated series shortly.
> 
> Open questions:
> 
> 	* Exports.  Currently we have getname_kernel() and putname()
> exported, while the rest of importers is not.  There is exactly one

Tbh, I don't find that too bad. It would be elegant if we could wipe
that completely but I don't think that this is a big deal...

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-01-14 16:00 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-08  7:41 [RFC PATCH 0/8] experimental struct filename followups Al Viro
2026-01-08  7:41 ` [RFC PATCH 1/8] non-consuming variant of do_renameat2() Al Viro
2026-01-08  7:41 ` [RFC PATCH 2/8] non-consuming variant of do_linkat() Al Viro
2026-01-08  7:41 ` [RFC PATCH 3/8] non-consuming variant of do_symlinkat() Al Viro
2026-01-08  7:41 ` [RFC PATCH 4/8] non-consuming variant of do_mkdirat() Al Viro
2026-01-08  7:41 ` [RFC PATCH 5/8] non-consuming variant of do_mknodat() Al Viro
2026-01-08  7:41 ` [RFC PATCH 6/8] non-consuming variants of do_{unlinkat,rmdir}() Al Viro
2026-01-08  7:42 ` [RFC PATCH 7/8] execve: fold {compat_,}do_execve{,at}() into their sole callers Al Viro
2026-01-08  7:42 ` [RFC PATCH 8/8] do_execveat_common(): don't consume filename reference Al Viro
2026-01-12 10:00 ` [RFC PATCH 0/8] experimental struct filename followups Christian Brauner
2026-01-14  2:15   ` Al Viro
2026-01-14  2:28     ` Al Viro
2026-01-14 16:00     ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox