Commit 365b18189789bfa1acd9939e6312b8a4b4577b28
Committed by
Al Viro
1 parent
ebabe9a900
Exists in
master
and in
20 other branches
add f_flags to struct statfs(64)
Add a flags field to help glibc implementing statvfs(3) efficiently. We copy the flag values from glibc, and add a new ST_VALID flag to denote that f_flags is implemented. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 5 changed files with 89 additions and 13 deletions Side-by-side Diff
arch/mips/include/asm/statfs.h
... | ... | @@ -33,7 +33,8 @@ |
33 | 33 | /* Linux specials */ |
34 | 34 | __kernel_fsid_t f_fsid; |
35 | 35 | long f_namelen; |
36 | - long f_spare[6]; | |
36 | + long f_flags; | |
37 | + long f_spare[5]; | |
37 | 38 | }; |
38 | 39 | |
39 | 40 | #if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32) |
... | ... | @@ -53,7 +54,8 @@ |
53 | 54 | __u64 f_bavail; |
54 | 55 | __kernel_fsid_t f_fsid; |
55 | 56 | __u32 f_namelen; |
56 | - __u32 f_spare[6]; | |
57 | + __u32 f_flags; | |
58 | + __u32 f_spare[5]; | |
57 | 59 | }; |
58 | 60 | |
59 | 61 | #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ |
... | ... | @@ -73,7 +75,8 @@ |
73 | 75 | /* Linux specials */ |
74 | 76 | __kernel_fsid_t f_fsid; |
75 | 77 | long f_namelen; |
76 | - long f_spare[6]; | |
78 | + long f_flags; | |
79 | + long f_spare[5]; | |
77 | 80 | }; |
78 | 81 | |
79 | 82 | struct compat_statfs64 { |
... | ... | @@ -88,7 +91,8 @@ |
88 | 91 | __u64 f_bavail; |
89 | 92 | __kernel_fsid_t f_fsid; |
90 | 93 | __u32 f_namelen; |
91 | - __u32 f_spare[6]; | |
94 | + __u32 f_flags; | |
95 | + __u32 f_spare[5]; | |
92 | 96 | }; |
93 | 97 | |
94 | 98 | #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ |
arch/s390/include/asm/statfs.h
... | ... | @@ -33,7 +33,8 @@ |
33 | 33 | __kernel_fsid_t f_fsid; |
34 | 34 | int f_namelen; |
35 | 35 | int f_frsize; |
36 | - int f_spare[5]; | |
36 | + int f_flags; | |
37 | + int f_spare[4]; | |
37 | 38 | }; |
38 | 39 | |
39 | 40 | struct statfs64 { |
... | ... | @@ -47,7 +48,8 @@ |
47 | 48 | __kernel_fsid_t f_fsid; |
48 | 49 | int f_namelen; |
49 | 50 | int f_frsize; |
50 | - int f_spare[5]; | |
51 | + int f_flags; | |
52 | + int f_spare[4]; | |
51 | 53 | }; |
52 | 54 | |
53 | 55 | struct compat_statfs64 { |
... | ... | @@ -61,7 +63,8 @@ |
61 | 63 | __kernel_fsid_t f_fsid; |
62 | 64 | __u32 f_namelen; |
63 | 65 | __u32 f_frsize; |
64 | - __u32 f_spare[5]; | |
66 | + __u32 f_flags; | |
67 | + __u32 f_spare[4]; | |
65 | 68 | }; |
66 | 69 | |
67 | 70 | #endif /* __s390x__ */ |
fs/statfs.c
... | ... | @@ -2,11 +2,49 @@ |
2 | 2 | #include <linux/module.h> |
3 | 3 | #include <linux/fs.h> |
4 | 4 | #include <linux/file.h> |
5 | +#include <linux/mount.h> | |
5 | 6 | #include <linux/namei.h> |
6 | 7 | #include <linux/statfs.h> |
7 | 8 | #include <linux/security.h> |
8 | 9 | #include <linux/uaccess.h> |
9 | 10 | |
11 | +static int flags_by_mnt(int mnt_flags) | |
12 | +{ | |
13 | + int flags = 0; | |
14 | + | |
15 | + if (mnt_flags & MNT_READONLY) | |
16 | + flags |= ST_RDONLY; | |
17 | + if (mnt_flags & MNT_NOSUID) | |
18 | + flags |= ST_NOSUID; | |
19 | + if (mnt_flags & MNT_NODEV) | |
20 | + flags |= ST_NODEV; | |
21 | + if (mnt_flags & MNT_NOEXEC) | |
22 | + flags |= ST_NOEXEC; | |
23 | + if (mnt_flags & MNT_NOATIME) | |
24 | + flags |= ST_NOATIME; | |
25 | + if (mnt_flags & MNT_NODIRATIME) | |
26 | + flags |= ST_NODIRATIME; | |
27 | + if (mnt_flags & MNT_RELATIME) | |
28 | + flags |= ST_RELATIME; | |
29 | + return flags; | |
30 | +} | |
31 | + | |
32 | +static 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 | + | |
42 | +static 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 | + | |
10 | 48 | int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) |
11 | 49 | { |
12 | 50 | int retval; |
... | ... | @@ -26,7 +64,12 @@ |
26 | 64 | |
27 | 65 | int vfs_statfs(struct path *path, struct kstatfs *buf) |
28 | 66 | { |
29 | - return statfs_by_dentry(path->dentry, buf); | |
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; | |
30 | 73 | } |
31 | 74 | EXPORT_SYMBOL(vfs_statfs); |
32 | 75 | |
... | ... | @@ -69,6 +112,7 @@ |
69 | 112 | buf->f_fsid = st.f_fsid; |
70 | 113 | buf->f_namelen = st.f_namelen; |
71 | 114 | buf->f_frsize = st.f_frsize; |
115 | + buf->f_flags = st.f_flags; | |
72 | 116 | memset(buf->f_spare, 0, sizeof(buf->f_spare)); |
73 | 117 | } |
74 | 118 | return 0; |
... | ... | @@ -96,6 +140,7 @@ |
96 | 140 | buf->f_fsid = st.f_fsid; |
97 | 141 | buf->f_namelen = st.f_namelen; |
98 | 142 | buf->f_frsize = st.f_frsize; |
143 | + buf->f_flags = st.f_flags; | |
99 | 144 | memset(buf->f_spare, 0, sizeof(buf->f_spare)); |
100 | 145 | } |
101 | 146 | return 0; |
include/asm-generic/statfs.h
... | ... | @@ -33,7 +33,8 @@ |
33 | 33 | __kernel_fsid_t f_fsid; |
34 | 34 | __statfs_word f_namelen; |
35 | 35 | __statfs_word f_frsize; |
36 | - __statfs_word f_spare[5]; | |
36 | + __statfs_word f_flags; | |
37 | + __statfs_word f_spare[4]; | |
37 | 38 | }; |
38 | 39 | |
39 | 40 | /* |
... | ... | @@ -55,7 +56,8 @@ |
55 | 56 | __kernel_fsid_t f_fsid; |
56 | 57 | __statfs_word f_namelen; |
57 | 58 | __statfs_word f_frsize; |
58 | - __statfs_word f_spare[5]; | |
59 | + __statfs_word f_flags; | |
60 | + __statfs_word f_spare[4]; | |
59 | 61 | } ARCH_PACK_STATFS64; |
60 | 62 | |
61 | 63 | /* |
... | ... | @@ -77,7 +79,8 @@ |
77 | 79 | __kernel_fsid_t f_fsid; |
78 | 80 | __u32 f_namelen; |
79 | 81 | __u32 f_frsize; |
80 | - __u32 f_spare[5]; | |
82 | + __u32 f_flags; | |
83 | + __u32 f_spare[4]; | |
81 | 84 | } ARCH_PACK_COMPAT_STATFS64; |
82 | 85 | |
83 | 86 | #endif |
include/linux/statfs.h
... | ... | @@ -2,7 +2,6 @@ |
2 | 2 | #define _LINUX_STATFS_H |
3 | 3 | |
4 | 4 | #include <linux/types.h> |
5 | - | |
6 | 5 | #include <asm/statfs.h> |
7 | 6 | |
8 | 7 | struct kstatfs { |
9 | 8 | |
... | ... | @@ -16,8 +15,30 @@ |
16 | 15 | __kernel_fsid_t f_fsid; |
17 | 16 | long f_namelen; |
18 | 17 | long f_frsize; |
19 | - long f_spare[5]; | |
18 | + long f_flags; | |
19 | + long f_spare[4]; | |
20 | 20 | }; |
21 | + | |
22 | +/* | |
23 | + * Definitions for the flag in f_flag. | |
24 | + * | |
25 | + * Generally these flags are equivalent to the MS_ flags used in the mount | |
26 | + * ABI. The exception is ST_VALID which has the same value as MS_REMOUNT | |
27 | + * which doesn't make any sense for statfs. | |
28 | + */ | |
29 | +#define ST_RDONLY 0x0001 /* mount read-only */ | |
30 | +#define ST_NOSUID 0x0002 /* ignore suid and sgid bits */ | |
31 | +#define ST_NODEV 0x0004 /* disallow access to device special files */ | |
32 | +#define ST_NOEXEC 0x0008 /* disallow program execution */ | |
33 | +#define ST_SYNCHRONOUS 0x0010 /* writes are synced at once */ | |
34 | +#define ST_VALID 0x0020 /* f_flags support is implemented */ | |
35 | +#define ST_MANDLOCK 0x0040 /* allow mandatory locks on an FS */ | |
36 | +/* 0x0080 used for ST_WRITE in glibc */ | |
37 | +/* 0x0100 used for ST_APPEND in glibc */ | |
38 | +/* 0x0200 used for ST_IMMUTABLE in glibc */ | |
39 | +#define ST_NOATIME 0x0400 /* do not update access times */ | |
40 | +#define ST_NODIRATIME 0x0800 /* do not update directory access times */ | |
41 | +#define ST_RELATIME 0x1000 /* update atime relative to mtime/ctime */ | |
21 | 42 | |
22 | 43 | #endif |