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@xxxxxx> Index: linux-2.6/arch/mips/include/asm/statfs.h =================================================================== --- linux-2.6.orig/arch/mips/include/asm/statfs.h 2010-06-27 11:18:56.228261526 +0200 +++ linux-2.6/arch/mips/include/asm/statfs.h 2010-06-29 16:58:13.036004011 +0200 @@ -33,7 +33,8 @@ struct statfs { /* Linux specials */ __kernel_fsid_t f_fsid; long f_namelen; - long f_spare[6]; + long f_flags; + long f_spare[5]; }; #if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32) @@ -53,7 +54,8 @@ struct statfs64 { __u64 f_bavail; __kernel_fsid_t f_fsid; __u32 f_namelen; - __u32 f_spare[6]; + __u32 f_flags; + __u32 f_spare[5]; }; #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ @@ -73,7 +75,8 @@ struct statfs64 { /* Same as struct st /* Linux specials */ __kernel_fsid_t f_fsid; long f_namelen; - long f_spare[6]; + long f_flags; + long f_spare[5]; }; struct compat_statfs64 { @@ -88,7 +91,8 @@ struct compat_statfs64 { __u64 f_bavail; __kernel_fsid_t f_fsid; __u32 f_namelen; - __u32 f_spare[6]; + __u32 f_flags; + __u32 f_spare[5]; }; #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ Index: linux-2.6/arch/s390/include/asm/statfs.h =================================================================== --- linux-2.6.orig/arch/s390/include/asm/statfs.h 2010-06-27 11:18:56.241254542 +0200 +++ linux-2.6/arch/s390/include/asm/statfs.h 2010-06-29 16:58:13.037004081 +0200 @@ -33,7 +33,8 @@ struct statfs { __kernel_fsid_t f_fsid; int f_namelen; int f_frsize; - int f_spare[5]; + int f_flags; + int f_spare[4]; }; struct statfs64 { @@ -47,7 +48,8 @@ struct statfs64 { __kernel_fsid_t f_fsid; int f_namelen; int f_frsize; - int f_spare[5]; + int f_flags; + int f_spare[4]; }; struct compat_statfs64 { @@ -61,7 +63,8 @@ struct compat_statfs64 { __kernel_fsid_t f_fsid; __u32 f_namelen; __u32 f_frsize; - __u32 f_spare[5]; + __u32 f_flags; + __u32 f_spare[4]; }; #endif /* __s390x__ */ Index: linux-2.6/include/asm-generic/statfs.h =================================================================== --- linux-2.6.orig/include/asm-generic/statfs.h 2010-06-27 11:18:56.257254961 +0200 +++ linux-2.6/include/asm-generic/statfs.h 2010-06-29 16:58:13.045157664 +0200 @@ -33,7 +33,8 @@ struct statfs { __kernel_fsid_t f_fsid; __statfs_word f_namelen; __statfs_word f_frsize; - __statfs_word f_spare[5]; + __statfs_word f_flags; + __statfs_word f_spare[4]; }; /* @@ -55,7 +56,8 @@ struct statfs64 { __kernel_fsid_t f_fsid; __statfs_word f_namelen; __statfs_word f_frsize; - __statfs_word f_spare[5]; + __statfs_word f_flags; + __statfs_word f_spare[4]; } ARCH_PACK_STATFS64; /* @@ -77,7 +79,8 @@ struct compat_statfs64 { __kernel_fsid_t f_fsid; __u32 f_namelen; __u32 f_frsize; - __u32 f_spare[5]; + __u32 f_flags; + __u32 f_spare[4]; } ARCH_PACK_COMPAT_STATFS64; #endif Index: linux-2.6/include/linux/statfs.h =================================================================== --- linux-2.6.orig/include/linux/statfs.h 2010-06-27 11:18:56.269254612 +0200 +++ linux-2.6/include/linux/statfs.h 2010-06-29 16:58:13.054173308 +0200 @@ -2,7 +2,6 @@ #define _LINUX_STATFS_H #include <linux/types.h> - #include <asm/statfs.h> struct kstatfs { @@ -16,7 +15,29 @@ struct kstatfs { __kernel_fsid_t f_fsid; long f_namelen; long f_frsize; - long f_spare[5]; + long f_flags; + long f_spare[4]; }; +/* + * Definitions for the flag in f_flag. + * + * Generally these flags are equivalent to the MS_ flags used in the mount + * ABI. The exception is ST_VALID which has the same value as MS_REMOUNT + * which doesn't make any sense for statfs. + */ +#define ST_RDONLY 0x0001 /* mount read-only */ +#define ST_NOSUID 0x0002 /* ignore suid and sgid bits */ +#define ST_NODEV 0x0004 /* disallow access to device special files */ +#define ST_NOEXEC 0x0008 /* disallow program execution */ +#define ST_SYNCHRONOUS 0x0010 /* writes are synced at once */ +#define ST_VALID 0x0020 /* f_flags support is implemented */ +#define ST_MANDLOCK 0x0040 /* allow mandatory locks on an FS */ +/* 0x0080 used for ST_WRITE in glibc */ +/* 0x0100 used for ST_APPEND in glibc */ +/* 0x0200 used for ST_IMMUTABLE in glibc */ +#define ST_NOATIME 0x0400 /* do not update access times */ +#define ST_NODIRATIME 0x0800 /* do not update directory access times */ +#define ST_RELATIME 0x1000 /* update atime relative to mtime/ctime */ + #endif Index: linux-2.6/fs/statfs.c =================================================================== --- linux-2.6.orig/fs/statfs.c 2010-06-29 16:58:12.548255583 +0200 +++ linux-2.6/fs/statfs.c 2010-06-29 16:58:13.059033694 +0200 @@ -2,11 +2,40 @@ #include <linux/module.h> #include <linux/fs.h> #include <linux/file.h> +#include <linux/mount.h> #include <linux/namei.h> #include <linux/statfs.h> #include <linux/security.h> #include <linux/uaccess.h> +static int calculate_f_flags(struct vfsmount *mnt) +{ + struct super_block *sb = mnt->mnt_sb; + long flags = ST_VALID; + + if (mnt->mnt_flags & MNT_READONLY) + flags |= ST_RDONLY; + if (mnt->mnt_flags & MNT_NOSUID) + flags |= ST_NOSUID; + if (mnt->mnt_flags & MNT_NODEV) + flags |= ST_NODEV; + if (mnt->mnt_flags & MNT_NOEXEC) + flags |= ST_NOEXEC; + if (mnt->mnt_flags & MNT_NOATIME) + flags |= ST_NOATIME; + if (mnt->mnt_flags & MNT_NODIRATIME) + flags |= ST_NODIRATIME; + if (mnt->mnt_flags & MNT_RELATIME) + flags |= ST_RELATIME; + + if (sb->s_flags & MS_SYNCHRONOUS) + flags |= ST_SYNCHRONOUS; + if (sb->s_flags & MS_MANDLOCK) + flags |= ST_MANDLOCK; + + return flags; +} + int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) { int retval; @@ -26,7 +55,12 @@ int statfs_by_dentry(struct dentry *dent int vfs_statfs(struct path *path, struct kstatfs *buf) { - return statfs_by_dentry(path->dentry, buf); + int error; + + error = statfs_by_dentry(path->dentry, buf); + if (!error) + buf->f_flags = calculate_f_flags(path->mnt); + return error; } EXPORT_SYMBOL(vfs_statfs); @@ -69,6 +103,7 @@ static int do_statfs_native(struct path buf->f_fsid = st.f_fsid; buf->f_namelen = st.f_namelen; buf->f_frsize = st.f_frsize; + buf->f_flags = st.f_flags; memset(buf->f_spare, 0, sizeof(buf->f_spare)); } return 0; @@ -96,6 +131,7 @@ static int do_statfs64(struct path *path buf->f_fsid = st.f_fsid; buf->f_namelen = st.f_namelen; buf->f_frsize = st.f_frsize; + buf->f_flags = st.f_flags; memset(buf->f_spare, 0, sizeof(buf->f_spare)); } return 0; -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html