Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Christoph Hellwig and committed by
Al Viro
365b1818 ebabe9a9

+89 -13
+8 -4
arch/mips/include/asm/statfs.h
··· 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) ··· 54 53 __u64 f_bavail; 55 54 __kernel_fsid_t f_fsid; 56 55 __u32 f_namelen; 57 - __u32 f_spare[6]; 56 + __u32 f_flags; 57 + __u32 f_spare[5]; 58 58 }; 59 59 60 60 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ ··· 75 73 /* Linux specials */ 76 74 __kernel_fsid_t f_fsid; 77 75 long f_namelen; 78 - long f_spare[6]; 76 + long f_flags; 77 + long f_spare[5]; 79 78 }; 80 79 81 80 struct compat_statfs64 { ··· 91 88 __u64 f_bavail; 92 89 __kernel_fsid_t f_fsid; 93 90 __u32 f_namelen; 94 - __u32 f_spare[6]; 91 + __u32 f_flags; 92 + __u32 f_spare[5]; 95 93 }; 96 94 97 95 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
+6 -3
arch/s390/include/asm/statfs.h
··· 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 { ··· 48 47 __kernel_fsid_t f_fsid; 49 48 int f_namelen; 50 49 int f_frsize; 51 - int f_spare[5]; 50 + int f_flags; 51 + int f_spare[4]; 52 52 }; 53 53 54 54 struct compat_statfs64 { ··· 63 61 __kernel_fsid_t f_fsid; 64 62 __u32 f_namelen; 65 63 __u32 f_frsize; 66 - __u32 f_spare[5]; 64 + __u32 f_flags; 65 + __u32 f_spare[4]; 67 66 }; 68 67 69 68 #endif /* __s390x__ */
+46 -1
fs/statfs.c
··· 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> 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 + } 9 47 10 48 int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) 11 49 { ··· 64 26 65 27 int vfs_statfs(struct path *path, struct kstatfs *buf) 66 28 { 67 - return statfs_by_dentry(path->dentry, buf); 29 + int error; 30 + 31 + error = statfs_by_dentry(path->dentry, buf); 32 + if (!error) 33 + buf->f_flags = calculate_f_flags(path->mnt); 34 + return error; 68 35 } 69 36 EXPORT_SYMBOL(vfs_statfs); 70 37 ··· 112 69 buf->f_fsid = st.f_fsid; 113 70 buf->f_namelen = st.f_namelen; 114 71 buf->f_frsize = st.f_frsize; 72 + buf->f_flags = st.f_flags; 115 73 memset(buf->f_spare, 0, sizeof(buf->f_spare)); 116 74 } 117 75 return 0; ··· 140 96 buf->f_fsid = st.f_fsid; 141 97 buf->f_namelen = st.f_namelen; 142 98 buf->f_frsize = st.f_frsize; 99 + buf->f_flags = st.f_flags; 143 100 memset(buf->f_spare, 0, sizeof(buf->f_spare)); 144 101 } 145 102 return 0;
+6 -3
include/asm-generic/statfs.h
··· 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 /* ··· 56 55 __kernel_fsid_t f_fsid; 57 56 __statfs_word f_namelen; 58 57 __statfs_word f_frsize; 59 - __statfs_word f_spare[5]; 58 + __statfs_word f_flags; 59 + __statfs_word f_spare[4]; 60 60 } ARCH_PACK_STATFS64; 61 61 62 62 /* ··· 79 77 __kernel_fsid_t f_fsid; 80 78 __u32 f_namelen; 81 79 __u32 f_frsize; 82 - __u32 f_spare[5]; 80 + __u32 f_flags; 81 + __u32 f_spare[4]; 83 82 } ARCH_PACK_COMPAT_STATFS64; 84 83 85 84 #endif
+23 -2
include/linux/statfs.h
··· 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 { ··· 15 16 __kernel_fsid_t f_fsid; 16 17 long f_namelen; 17 18 long f_frsize; 18 - long f_spare[5]; 19 + long f_flags; 20 + long f_spare[4]; 19 21 }; 22 + 23 + /* 24 + * Definitions for the flag in f_flag. 25 + * 26 + * Generally these flags are equivalent to the MS_ flags used in the mount 27 + * ABI. The exception is ST_VALID which has the same value as MS_REMOUNT 28 + * which doesn't make any sense for statfs. 29 + */ 30 + #define ST_RDONLY 0x0001 /* mount read-only */ 31 + #define ST_NOSUID 0x0002 /* ignore suid and sgid bits */ 32 + #define ST_NODEV 0x0004 /* disallow access to device special files */ 33 + #define ST_NOEXEC 0x0008 /* disallow program execution */ 34 + #define ST_SYNCHRONOUS 0x0010 /* writes are synced at once */ 35 + #define ST_VALID 0x0020 /* f_flags support is implemented */ 36 + #define ST_MANDLOCK 0x0040 /* allow mandatory locks on an FS */ 37 + /* 0x0080 used for ST_WRITE in glibc */ 38 + /* 0x0100 used for ST_APPEND in glibc */ 39 + /* 0x0200 used for ST_IMMUTABLE in glibc */ 40 + #define ST_NOATIME 0x0400 /* do not update access times */ 41 + #define ST_NODIRATIME 0x0800 /* do not update directory access times */ 42 + #define ST_RELATIME 0x1000 /* update atime relative to mtime/ctime */ 20 43 21 44 #endif