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(-)
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(-)
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>
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?
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...
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...
© 2016 - 2026 Red Hat, Inc.