]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
non-consuming variant of do_renameat2()
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 7 Jan 2026 04:19:10 +0000 (23:19 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 16 Jan 2026 17:46:57 +0000 (12:46 -0500)
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
fs/internal.h
fs/namei.c
io_uring/fs.c

index 3397937ed838e5e7dfacc6379a9d71481cc30914..459ec2f57794d85cc3133012060e930b9576a6ec 100644 (file)
@@ -1334,3 +1334,12 @@ 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**
+
+fs/namei.c primitives that consume filesystem references (do_renameat2(),
+do_linkat(), do_symlinkat(), do_mkdirat(), do_mknodat(), do_unlinkat()
+and do_rmdir()) are getting replaced with non-consuming analogues
+(filename_renameat2(), etc.)  Replaced so far: do_renameat2().
index 4c4d2733c47a2c901836812d627019fae1a6e7ec..5047cfbb8c93c531ac3d0fa01abd4ceeade86195 100644 (file)
@@ -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);
index 65a06fb312af692ed2cde16c55a5b37775083eba..5354f240b86a9a241db10ed85deaa62c5e2c41e8 100644 (file)
@@ -6028,8 +6028,8 @@ out:
 }
 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)
 {
        struct renamedata rd;
        struct path old_path, new_path;
@@ -6038,20 +6038,20 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
        struct delegated_inode delegated_inode = { };
        unsigned int lookup_flags = 0;
        bool should_retry = false;
-       int error = -EINVAL;
+       int error;
 
        if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
-               goto put_names;
+               return -EINVAL;
 
        if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT)) &&
            (flags & RENAME_EXCHANGE))
-               goto put_names;
+               return -EINVAL;
 
 retry:
        error = filename_parentat(olddfd, from, lookup_flags, &old_path,
                                  &old_last, &old_type);
        if (error)
-               goto put_names;
+               return error;
 
        error = filename_parentat(newdfd, to, lookup_flags, &new_path, &new_last,
                                  &new_type);
@@ -6128,30 +6128,30 @@ exit1:
                lookup_flags |= LOOKUP_REVAL;
                goto retry;
        }
-put_names:
-       putname(from);
-       putname(to);
        return error;
 }
 
 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)
index c04c6282210abbd805885c154891b78dde67c1dc..e5829d112c9e9f3350cb01308d287fcfeb176ac7 100644 (file)
@@ -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);