From: Méven Car Copy utilities that preserve timestamps, like cp -p or a file manager, set the times of every copy after its last write. To do that through io_uring, the request needs the utimensat() lookup on a name that was imported at submission time. io_uring takes the path of a request when it is submitted and looks it up later, from a worker thread. The path ops it already has call the filename_*() helpers of fs/namei.c with a struct filename. utimensat(2) had no such helper: do_utimes_path() took the user pointer and imported the name itself. Split the lookup and the vfs_utimes() call out of do_utimes_path() into filename_utimensat(), declared in fs/internal.h next to the other filename_*() helpers. do_utimes_path() now only imports the name. Signed-off-by: Méven Car --- fs/internal.h | 2 ++ fs/utimes.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/internal.h b/fs/internal.h index c658c8a5ebd5..985b2bc5895e 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -63,6 +63,8 @@ int filename_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int 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 filename_utimensat(int dfd, struct filename *name, + struct timespec64 *times, int flags); int vfs_tmpfile(struct mnt_idmap *idmap, const struct path *parentpath, struct file *file, umode_t mode); diff --git a/fs/utimes.c b/fs/utimes.c index e22664e4115f..8072f05ac8dc 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -79,8 +79,8 @@ int vfs_utimes(const struct path *path, struct timespec64 *times) } EXPORT_SYMBOL_GPL(vfs_utimes); -static int do_utimes_path(int dfd, const char __user *filename, - struct timespec64 *times, int flags) +int filename_utimensat(int dfd, struct filename *name, + struct timespec64 *times, int flags) { struct path path; int lookup_flags = 0, error; @@ -91,7 +91,6 @@ static int do_utimes_path(int dfd, const char __user *filename, if (!(flags & AT_SYMLINK_NOFOLLOW)) lookup_flags |= LOOKUP_FOLLOW; - CLASS(filename_uflags, name)(filename, flags); retry: error = filename_lookup(dfd, name, lookup_flags, &path, NULL); if (error) @@ -105,6 +104,13 @@ static int do_utimes_path(int dfd, const char __user *filename, return error; } +static int do_utimes_path(int dfd, const char __user *filename, + struct timespec64 *times, int flags) +{ + CLASS(filename_uflags, name)(filename, flags); + return filename_utimensat(dfd, name, times, flags); +} + static int do_utimes_fd(int fd, struct timespec64 *times, int flags) { if (flags) -- 2.56.0