aboutsummaryrefslogtreecommitdiffstats
path: root/fs/statfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/statfs.c')
-rw-r--r--fs/statfs.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/fs/statfs.c b/fs/statfs.c
index 4ef021f3b612..30ea8c8a996b 100644
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -2,38 +2,83 @@
2#include <linux/module.h> 2#include <linux/module.h>
3#include <linux/fs.h> 3#include <linux/fs.h>
4#include <linux/file.h> 4#include <linux/file.h>
5#include <linux/mount.h>
5#include <linux/namei.h> 6#include <linux/namei.h>
6#include <linux/statfs.h> 7#include <linux/statfs.h>
7#include <linux/security.h> 8#include <linux/security.h>
8#include <linux/uaccess.h> 9#include <linux/uaccess.h>
9 10
10int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) 11static int flags_by_mnt(int mnt_flags)
11{ 12{
12 int retval = -ENODEV; 13 int flags = 0;
13 14
14 if (dentry) { 15 if (mnt_flags & MNT_READONLY)
15 retval = -ENOSYS; 16 flags |= ST_RDONLY;
16 if (dentry->d_sb->s_op->statfs) { 17 if (mnt_flags & MNT_NOSUID)
17 memset(buf, 0, sizeof(*buf)); 18 flags |= ST_NOSUID;
18 retval = security_sb_statfs(dentry); 19 if (mnt_flags & MNT_NODEV)
19 if (retval) 20 flags |= ST_NODEV;
20 return retval; 21 if (mnt_flags & MNT_NOEXEC)
21 retval = dentry->d_sb->s_op->statfs(dentry, buf); 22 flags |= ST_NOEXEC;
22 if (retval == 0 && buf->f_frsize == 0) 23 if (mnt_flags & MNT_NOATIME)
23 buf->f_frsize = buf->f_bsize; 24 flags |= ST_NOATIME;
24 } 25 if (mnt_flags & MNT_NODIRATIME)
25 } 26 flags |= ST_NODIRATIME;
27 if (mnt_flags & MNT_RELATIME)
28 flags |= ST_RELATIME;
29 return flags;
30}
31
32static int flags_by_sb(int s_flags)
33{
34 int flags = 0;
35 if (s_flags & MS_SYNCHRONOUS)
36 flags |= ST_SYNCHRONOUS;
37 if (s_flags & MS_MANDLOCK)
38 flags |= ST_MANDLOCK;
39 return flags;
40}
41
42static int calculate_f_flags(struct vfsmount *mnt)
43{
44 return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
45 flags_by_sb(mnt->mnt_sb->s_flags);
46}
47
48int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
49{
50 int retval;
51
52 if (!dentry->d_sb->s_op->statfs)
53 return -ENOSYS;
54
55 memset(buf, 0, sizeof(*buf));
56 retval = security_sb_statfs(dentry);
57 if (retval)
58 return retval;
59 retval = dentry->d_sb->s_op->statfs(dentry, buf);
60 if (retval == 0 && buf->f_frsize == 0)
61 buf->f_frsize = buf->f_bsize;
26 return retval; 62 return retval;
27} 63}
28 64
65int vfs_statfs(struct path *path, struct kstatfs *buf)
66{
67 int error;
68
69 error = statfs_by_dentry(path->dentry, buf);
70 if (!error)
71 buf->f_flags = calculate_f_flags(path->mnt);
72 return error;
73}
29EXPORT_SYMBOL(vfs_statfs); 74EXPORT_SYMBOL(vfs_statfs);
30 75
31static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf) 76static int do_statfs_native(struct path *path, struct statfs *buf)
32{ 77{
33 struct kstatfs st; 78 struct kstatfs st;
34 int retval; 79 int retval;
35 80
36 retval = vfs_statfs(dentry, &st); 81 retval = vfs_statfs(path, &st);
37 if (retval) 82 if (retval)
38 return retval; 83 return retval;
39 84
@@ -67,17 +112,18 @@ static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
67 buf->f_fsid = st.f_fsid; 112 buf->f_fsid = st.f_fsid;
68 buf->f_namelen = st.f_namelen; 113 buf->f_namelen = st.f_namelen;
69 buf->f_frsize = st.f_frsize; 114 buf->f_frsize = st.f_frsize;
115 buf->f_flags = st.f_flags;
70 memset(buf->f_spare, 0, sizeof(buf->f_spare)); 116 memset(buf->f_spare, 0, sizeof(buf->f_spare));
71 } 117 }
72 return 0; 118 return 0;
73} 119}
74 120
75static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf) 121static int do_statfs64(struct path *path, struct statfs64 *buf)
76{ 122{
77 struct kstatfs st; 123 struct kstatfs st;
78 int retval; 124 int retval;
79 125
80 retval = vfs_statfs(dentry, &st); 126 retval = vfs_statfs(path, &st);
81 if (retval) 127 if (retval)
82 return retval; 128 return retval;
83 129
@@ -94,6 +140,7 @@ static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
94 buf->f_fsid = st.f_fsid; 140 buf->f_fsid = st.f_fsid;
95 buf->f_namelen = st.f_namelen; 141 buf->f_namelen = st.f_namelen;
96 buf->f_frsize = st.f_frsize; 142 buf->f_frsize = st.f_frsize;
143 buf->f_flags = st.f_flags;
97 memset(buf->f_spare, 0, sizeof(buf->f_spare)); 144 memset(buf->f_spare, 0, sizeof(buf->f_spare));
98 } 145 }
99 return 0; 146 return 0;
@@ -107,7 +154,7 @@ SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, b
107 error = user_path(pathname, &path); 154 error = user_path(pathname, &path);
108 if (!error) { 155 if (!error) {
109 struct statfs tmp; 156 struct statfs tmp;
110 error = vfs_statfs_native(path.dentry, &tmp); 157 error = do_statfs_native(&path, &tmp);
111 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 158 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
112 error = -EFAULT; 159 error = -EFAULT;
113 path_put(&path); 160 path_put(&path);
@@ -125,7 +172,7 @@ SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct stat
125 error = user_path(pathname, &path); 172 error = user_path(pathname, &path);
126 if (!error) { 173 if (!error) {
127 struct statfs64 tmp; 174 struct statfs64 tmp;
128 error = vfs_statfs64(path.dentry, &tmp); 175 error = do_statfs64(&path, &tmp);
129 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 176 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
130 error = -EFAULT; 177 error = -EFAULT;
131 path_put(&path); 178 path_put(&path);
@@ -143,7 +190,7 @@ SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
143 file = fget(fd); 190 file = fget(fd);
144 if (!file) 191 if (!file)
145 goto out; 192 goto out;
146 error = vfs_statfs_native(file->f_path.dentry, &tmp); 193 error = do_statfs_native(&file->f_path, &tmp);
147 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 194 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
148 error = -EFAULT; 195 error = -EFAULT;
149 fput(file); 196 fput(file);
@@ -164,7 +211,7 @@ SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user
164 file = fget(fd); 211 file = fget(fd);
165 if (!file) 212 if (!file)
166 goto out; 213 goto out;
167 error = vfs_statfs64(file->f_path.dentry, &tmp); 214 error = do_statfs64(&file->f_path, &tmp);
168 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 215 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
169 error = -EFAULT; 216 error = -EFAULT;
170 fput(file); 217 fput(file);
@@ -183,7 +230,7 @@ SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
183 if (!s) 230 if (!s)
184 return -EINVAL; 231 return -EINVAL;
185 232
186 err = vfs_statfs(s->s_root, &sbuf); 233 err = statfs_by_dentry(s->s_root, &sbuf);
187 drop_super(s); 234 drop_super(s);
188 if (err) 235 if (err)
189 return err; 236 return err;