return result;
 }
 
-struct filename *
-getname_uflags(const char __user *filename, int uflags)
+struct filename *getname_uflags(const char __user *filename, int uflags)
 {
        int flags = (uflags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : 0;
 
        return getname_flags(filename, flags);
 }
 
-struct filename *
-getname(const char __user * filename)
+struct filename *getname(const char __user * filename)
 {
        return getname_flags(filename, 0);
 }
 
-struct filename *
-getname_kernel(const char * filename)
+struct filename *__getname_maybe_null(const char __user *pathname)
+{
+       struct filename *name;
+       char c;
+
+       /* try to save on allocations; loss on um, though */
+       if (get_user(c, pathname))
+               return ERR_PTR(-EFAULT);
+       if (!c)
+               return NULL;
+
+       name = getname_flags(pathname, LOOKUP_EMPTY);
+       if (!IS_ERR(name) && !(name->name[0])) {
+               putname(name);
+               name = NULL;
+       }
+       return name;
+}
+
+struct filename *getname_kernel(const char * filename)
 {
        struct filename *result;
        int len = strlen(filename) + 1;
 
 void putname(struct filename *name)
 {
-       if (IS_ERR(name))
+       if (IS_ERR_OR_NULL(name))
                return;
 
        if (WARN_ON_ONCE(!atomic_read(&name->refcnt)))
 
 {
        int ret;
        int statx_flags = flags | AT_NO_AUTOMOUNT;
-       struct filename *name;
+       struct filename *name = getname_maybe_null(filename, flags);
 
-       /*
-        * Work around glibc turning fstat() into fstatat(AT_EMPTY_PATH)
-        *
-        * If AT_EMPTY_PATH is set, we expect the common case to be that
-        * empty path, and avoid doing all the extra pathname work.
-        */
-       if (flags == AT_EMPTY_PATH && vfs_empty_path(dfd, filename))
+       if (!name && dfd >= 0)
                return vfs_fstat(dfd, stat);
 
-       name = getname_flags(filename, getname_statx_lookup_flags(statx_flags));
        ret = vfs_statx(dfd, name, statx_flags, stat, STATX_BASIC_STATS);
        putname(name);
 
                struct statx __user *, buffer)
 {
        int ret;
-       unsigned lflags;
-       struct filename *name;
+       struct filename *name = getname_maybe_null(filename, flags);
 
-       /*
-        * Short-circuit handling of NULL and "" paths.
-        *
-        * For a NULL path we require and accept only the AT_EMPTY_PATH flag
-        * (possibly |'d with AT_STATX flags).
-        *
-        * However, glibc on 32-bit architectures implements fstatat as statx
-        * with the "" pathname and AT_NO_AUTOMOUNT | AT_EMPTY_PATH flags.
-        * Supporting this results in the uglification below.
-        */
-       lflags = flags & ~(AT_NO_AUTOMOUNT | AT_STATX_SYNC_TYPE);
-       if (lflags == AT_EMPTY_PATH && vfs_empty_path(dfd, filename))
+       if (!name && dfd >= 0)
                return do_statx_fd(dfd, flags & ~AT_NO_AUTOMOUNT, mask, buffer);
 
-       name = getname_flags(filename, getname_statx_lookup_flags(flags));
        ret = do_statx(dfd, name, flags, mask, buffer);
        putname(name);
 
 
 extern struct filename *getname_uflags(const char __user *, int);
 extern struct filename *getname(const char __user *);
 extern struct filename *getname_kernel(const char *);
+extern struct filename *__getname_maybe_null(const char __user *);
+static inline struct filename *getname_maybe_null(const char __user *name, int flags)
+{
+       if (!(flags & AT_EMPTY_PATH))
+               return getname(name);
+
+       if (!name)
+               return NULL;
+       return __getname_maybe_null(name);
+}
 extern void putname(struct filename *name);
 
 extern int finish_open(struct file *file, struct dentry *dentry,