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>
This commit is contained in:
Christoph Hellwig 2010-07-07 18:53:25 +02:00 committed by Al Viro
parent ebabe9a900
commit 365b181897
5 changed files with 89 additions and 13 deletions

View file

@ -33,7 +33,8 @@ struct statfs {
/* Linux specials */ /* Linux specials */
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
long f_namelen; 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) #if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32)
@ -53,7 +54,8 @@ struct statfs64 {
__u64 f_bavail; __u64 f_bavail;
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
__u32 f_namelen; __u32 f_namelen;
__u32 f_spare[6]; __u32 f_flags;
__u32 f_spare[5];
}; };
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
@ -73,7 +75,8 @@ struct statfs64 { /* Same as struct statfs */
/* Linux specials */ /* Linux specials */
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
long f_namelen; long f_namelen;
long f_spare[6]; long f_flags;
long f_spare[5];
}; };
struct compat_statfs64 { struct compat_statfs64 {
@ -88,7 +91,8 @@ struct compat_statfs64 {
__u64 f_bavail; __u64 f_bavail;
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
__u32 f_namelen; __u32 f_namelen;
__u32 f_spare[6]; __u32 f_flags;
__u32 f_spare[5];
}; };
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */

View file

@ -33,7 +33,8 @@ struct statfs {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
int f_namelen; int f_namelen;
int f_frsize; int f_frsize;
int f_spare[5]; int f_flags;
int f_spare[4];
}; };
struct statfs64 { struct statfs64 {
@ -47,7 +48,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
int f_namelen; int f_namelen;
int f_frsize; int f_frsize;
int f_spare[5]; int f_flags;
int f_spare[4];
}; };
struct compat_statfs64 { struct compat_statfs64 {
@ -61,7 +63,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
__u32 f_namelen; __u32 f_namelen;
__u32 f_frsize; __u32 f_frsize;
__u32 f_spare[5]; __u32 f_flags;
__u32 f_spare[4];
}; };
#endif /* __s390x__ */ #endif /* __s390x__ */

View file

@ -2,11 +2,49 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/mount.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/statfs.h> #include <linux/statfs.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
static int flags_by_mnt(int mnt_flags)
{
int flags = 0;
if (mnt_flags & MNT_READONLY)
flags |= ST_RDONLY;
if (mnt_flags & MNT_NOSUID)
flags |= ST_NOSUID;
if (mnt_flags & MNT_NODEV)
flags |= ST_NODEV;
if (mnt_flags & MNT_NOEXEC)
flags |= ST_NOEXEC;
if (mnt_flags & MNT_NOATIME)
flags |= ST_NOATIME;
if (mnt_flags & MNT_NODIRATIME)
flags |= ST_NODIRATIME;
if (mnt_flags & MNT_RELATIME)
flags |= ST_RELATIME;
return flags;
}
static int flags_by_sb(int s_flags)
{
int flags = 0;
if (s_flags & MS_SYNCHRONOUS)
flags |= ST_SYNCHRONOUS;
if (s_flags & MS_MANDLOCK)
flags |= ST_MANDLOCK;
return flags;
}
static int calculate_f_flags(struct vfsmount *mnt)
{
return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
flags_by_sb(mnt->mnt_sb->s_flags);
}
int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
{ {
int retval; int retval;
@ -26,7 +64,12 @@ int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
int vfs_statfs(struct path *path, struct kstatfs *buf) 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); EXPORT_SYMBOL(vfs_statfs);
@ -69,6 +112,7 @@ static int do_statfs_native(struct path *path, struct statfs *buf)
buf->f_fsid = st.f_fsid; buf->f_fsid = st.f_fsid;
buf->f_namelen = st.f_namelen; buf->f_namelen = st.f_namelen;
buf->f_frsize = st.f_frsize; buf->f_frsize = st.f_frsize;
buf->f_flags = st.f_flags;
memset(buf->f_spare, 0, sizeof(buf->f_spare)); memset(buf->f_spare, 0, sizeof(buf->f_spare));
} }
return 0; return 0;
@ -96,6 +140,7 @@ static int do_statfs64(struct path *path, struct statfs64 *buf)
buf->f_fsid = st.f_fsid; buf->f_fsid = st.f_fsid;
buf->f_namelen = st.f_namelen; buf->f_namelen = st.f_namelen;
buf->f_frsize = st.f_frsize; buf->f_frsize = st.f_frsize;
buf->f_flags = st.f_flags;
memset(buf->f_spare, 0, sizeof(buf->f_spare)); memset(buf->f_spare, 0, sizeof(buf->f_spare));
} }
return 0; return 0;

View file

@ -33,7 +33,8 @@ struct statfs {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
__statfs_word f_namelen; __statfs_word f_namelen;
__statfs_word f_frsize; __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; __kernel_fsid_t f_fsid;
__statfs_word f_namelen; __statfs_word f_namelen;
__statfs_word f_frsize; __statfs_word f_frsize;
__statfs_word f_spare[5]; __statfs_word f_flags;
__statfs_word f_spare[4];
} ARCH_PACK_STATFS64; } ARCH_PACK_STATFS64;
/* /*
@ -77,7 +79,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
__u32 f_namelen; __u32 f_namelen;
__u32 f_frsize; __u32 f_frsize;
__u32 f_spare[5]; __u32 f_flags;
__u32 f_spare[4];
} ARCH_PACK_COMPAT_STATFS64; } ARCH_PACK_COMPAT_STATFS64;
#endif #endif

View file

@ -2,7 +2,6 @@
#define _LINUX_STATFS_H #define _LINUX_STATFS_H
#include <linux/types.h> #include <linux/types.h>
#include <asm/statfs.h> #include <asm/statfs.h>
struct kstatfs { struct kstatfs {
@ -16,7 +15,29 @@ struct kstatfs {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
long f_namelen; long f_namelen;
long f_frsize; 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 #endif