summaryrefslogtreecommitdiffstats
path: root/fs/statfs.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2010-07-07 18:53:25 +0200
committerAl Viro <viro@zeniv.linux.org.uk>2010-08-09 16:48:44 -0400
commit365b18189789bfa1acd9939e6312b8a4b4577b28 (patch)
treeffb71da8e11c7751002d018d0b44c41776bc92a3 /fs/statfs.c
parentebabe9a9001af0af56c0c2780ca1576246e7a74b (diff)
downloadlinux-0-day-365b18189789bfa1acd9939e6312b8a4b4577b28.tar.gz
linux-0-day-365b18189789bfa1acd9939e6312b8a4b4577b28.tar.xz
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>
Diffstat (limited to 'fs/statfs.c')
-rw-r--r--fs/statfs.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/fs/statfs.c b/fs/statfs.c
index 6a305709a4da9..30ea8c8a996b1 100644
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -2,11 +2,49 @@
#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 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 retval;
@@ -26,7 +64,12 @@ int statfs_by_dentry(struct dentry *dentry, 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);
@@ -69,6 +112,7 @@ static int do_statfs_native(struct path *path, struct statfs *buf)
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 +140,7 @@ static int do_statfs64(struct path *path, struct statfs64 *buf)
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;