wifi: create a new patch 'drivers/net/wireless/rockchip_wlan' for porting drivers.
[firefly-linux-kernel-4.4.55.git] / fs / statfs.c
index 8244924dec55fd863bc7e0649e1686f78b336c8d..083dc0ac91408870254cac60ed4b06580deba610 100644 (file)
@@ -1,5 +1,5 @@
 #include <linux/syscalls.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/mount.h>
@@ -7,6 +7,7 @@
 #include <linux/statfs.h>
 #include <linux/security.h>
 #include <linux/uaccess.h>
+#include "internal.h"
 
 static int flags_by_mnt(int mnt_flags)
 {
@@ -45,7 +46,7 @@ static int calculate_f_flags(struct vfsmount *mnt)
                flags_by_sb(mnt->mnt_sb->s_flags);
 }
 
-int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
+static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
 {
        int retval;
 
@@ -76,21 +77,28 @@ EXPORT_SYMBOL(vfs_statfs);
 int user_statfs(const char __user *pathname, struct kstatfs *st)
 {
        struct path path;
-       int error = user_path(pathname, &path);
+       int error;
+       unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
+retry:
+       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
        if (!error) {
                error = vfs_statfs(&path, st);
                path_put(&path);
+               if (retry_estale(error, lookup_flags)) {
+                       lookup_flags |= LOOKUP_REVAL;
+                       goto retry;
+               }
        }
        return error;
 }
 
 int fd_statfs(int fd, struct kstatfs *st)
 {
-       struct file *file = fget(fd);
+       struct fd f = fdget_raw(fd);
        int error = -EBADF;
-       if (file) {
-               error = vfs_statfs(&file->f_path, st);
-               fput(file);
+       if (f.file) {
+               error = vfs_statfs(&f.file->f_path, st);
+               fdput(f);
        }
        return error;
 }
@@ -205,19 +213,23 @@ SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user
        return error;
 }
 
-SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
+int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
 {
-       struct super_block *s;
-       struct ustat tmp;
-       struct kstatfs sbuf;
+       struct super_block *s = user_get_super(dev);
        int err;
-
-       s = user_get_super(new_decode_dev(dev));
        if (!s)
                return -EINVAL;
 
-       err = statfs_by_dentry(s->s_root, &sbuf);
+       err = statfs_by_dentry(s->s_root, sbuf);
        drop_super(s);
+       return err;
+}
+
+SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
+{
+       struct ustat tmp;
+       struct kstatfs sbuf;
+       int err = vfs_ustat(new_decode_dev(dev), &sbuf);
        if (err)
                return err;