* [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