io-uring: Make statx API stable
[linux-2.6-block.git] / fs / stat.c
index 28d2020ba1f428eba0123954a8952be8272d9da3..7f734be0e57ec9f5d69927a672d7e4b20a4b006e 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -184,6 +184,20 @@ int vfs_fstat(int fd, struct kstat *stat)
        return error;
 }
 
+int getname_statx_lookup_flags(int flags)
+{
+       int lookup_flags = 0;
+
+       if (!(flags & AT_SYMLINK_NOFOLLOW))
+               lookup_flags |= LOOKUP_FOLLOW;
+       if (!(flags & AT_NO_AUTOMOUNT))
+               lookup_flags |= LOOKUP_AUTOMOUNT;
+       if (flags & AT_EMPTY_PATH)
+               lookup_flags |= LOOKUP_EMPTY;
+
+       return lookup_flags;
+}
+
 /**
  * vfs_statx - Get basic and extra attributes by filename
  * @dfd: A file descriptor representing the base dir for a relative filename
@@ -199,26 +213,19 @@ int vfs_fstat(int fd, struct kstat *stat)
  *
  * 0 will be returned on success, and a -ve error code if unsuccessful.
  */
-static int vfs_statx(int dfd, const char __user *filename, int flags,
+static int vfs_statx(int dfd, struct filename *filename, int flags,
              struct kstat *stat, u32 request_mask)
 {
        struct path path;
-       unsigned lookup_flags = 0;
+       unsigned int lookup_flags = getname_statx_lookup_flags(flags);
        int error;
 
        if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH |
                      AT_STATX_SYNC_TYPE))
                return -EINVAL;
 
-       if (!(flags & AT_SYMLINK_NOFOLLOW))
-               lookup_flags |= LOOKUP_FOLLOW;
-       if (!(flags & AT_NO_AUTOMOUNT))
-               lookup_flags |= LOOKUP_AUTOMOUNT;
-       if (flags & AT_EMPTY_PATH)
-               lookup_flags |= LOOKUP_EMPTY;
-
 retry:
-       error = user_path_at(dfd, filename, lookup_flags, &path);
+       error = filename_lookup(dfd, filename, lookup_flags, &path, NULL);
        if (error)
                goto out;
 
@@ -240,8 +247,15 @@ out:
 int vfs_fstatat(int dfd, const char __user *filename,
                              struct kstat *stat, int flags)
 {
-       return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT,
-                        stat, STATX_BASIC_STATS);
+       int ret;
+       int statx_flags = flags | AT_NO_AUTOMOUNT;
+       struct filename *name;
+
+       name = getname_flags(filename, getname_statx_lookup_flags(statx_flags), NULL);
+       ret = vfs_statx(dfd, name, statx_flags, stat, STATX_BASIC_STATS);
+       putname(name);
+
+       return ret;
 }
 
 #ifdef __ARCH_WANT_OLD_STAT
@@ -602,7 +616,7 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer)
        return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
-int do_statx(int dfd, const char __user *filename, unsigned flags,
+int do_statx(int dfd, struct filename *filename, unsigned int flags,
             unsigned int mask, struct statx __user *buffer)
 {
        struct kstat stat;
@@ -636,7 +650,14 @@ SYSCALL_DEFINE5(statx,
                unsigned int, mask,
                struct statx __user *, buffer)
 {
-       return do_statx(dfd, filename, flags, mask, buffer);
+       int ret;
+       struct filename *name;
+
+       name = getname_flags(filename, getname_statx_lookup_flags(flags), NULL);
+       ret = do_statx(dfd, name, flags, mask, buffer);
+       putname(name);
+
+       return ret;
 }
 
 #ifdef CONFIG_COMPAT