--- fs/compat.c | 13 +++++----- fs/ecryptfs/super.c | 5 +++- fs/nfsd/nfs4xdr.c | 2 - fs/nfsd/vfs.c | 2 - fs/open.c | 53 ++++++++++++++++++++++++++++++++++--------- fs/super.c | 2 - include/asm-generic/statfs.h | 9 ++++--- include/asm-x86_64/compat.h | 3 +- include/asm-x86_64/statfs.h | 9 ++++--- include/linux/fs.h | 2 - include/linux/statfs.h | 13 +++++++++- kernel/acct.c | 2 - 12 files changed, 84 insertions(+), 31 deletions(-) --- a/fs/compat.c +++ b/fs/compat.c @@ -194,7 +194,7 @@ static int put_compat_statfs(struct comp __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || __put_user(kbuf->f_frsize, &ubuf->f_frsize) || - __put_user(0, &ubuf->f_spare[0]) || + __put_user(kbuf->f_flag, &ubuf->f_flag) || __put_user(0, &ubuf->f_spare[1]) || __put_user(0, &ubuf->f_spare[2]) || __put_user(0, &ubuf->f_spare[3]) || @@ -215,7 +215,7 @@ asmlinkage long compat_sys_statfs(const error = user_path_walk(path, &nd); if (!error) { struct kstatfs tmp; - error = vfs_statfs(nd.dentry, &tmp); + error = vfs_statfs(nd.dentry, nd.mnt, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); path_release(&nd); @@ -233,7 +233,7 @@ asmlinkage long compat_sys_fstatfs(unsig file = fget(fd); if (!file) goto out; - error = vfs_statfs(file->f_path.dentry, &tmp); + error = vfs_statfs(file->f_path.dentry, file->f_path.mnt, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); fput(file); @@ -267,7 +267,8 @@ static int put_compat_statfs64(struct co __put_user(kbuf->f_namelen, &ubuf->f_namelen) || __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || - __put_user(kbuf->f_frsize, &ubuf->f_frsize)) + __put_user(kbuf->f_frsize, &ubuf->f_frsize) || + __put_user(kbuf->f_flag, &ubuf->f_flag)) return -EFAULT; return 0; } @@ -283,7 +284,7 @@ asmlinkage long compat_sys_statfs64(cons error = user_path_walk(path, &nd); if (!error) { struct kstatfs tmp; - error = vfs_statfs(nd.dentry, &tmp); + error = vfs_statfs(nd.dentry, nd.mnt, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); path_release(&nd); @@ -304,7 +305,7 @@ asmlinkage long compat_sys_fstatfs64(uns file = fget(fd); if (!file) goto out; - error = vfs_statfs(file->f_path.dentry, &tmp); + error = vfs_statfs(file->f_path.dentry, file->f_path.mnt, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); fput(file); --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -119,7 +119,10 @@ static void ecryptfs_put_super(struct su */ static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) { - return vfs_statfs(ecryptfs_dentry_to_lower(dentry), buf); + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); + struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); + + return vfs_statfs(lower_dentry, lower_mnt, buf); } /** --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1457,7 +1457,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL))) { - err = vfs_statfs(dentry, &statfs); + err = vfs_statfs(dentry, exp->ex_mnt, &statfs); if (err) goto out_nfserr; } --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1767,7 +1767,7 @@ __be32 nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) { __be32 err = fh_verify(rqstp, fhp, 0, MAY_NOP); - if (!err && vfs_statfs(fhp->fh_dentry,stat)) + if (!err && vfs_statfs(fhp->fh_dentry, fhp->fh_export->ex_mnt, stat)) err = nfserr_io; return err; } --- a/fs/open.c +++ b/fs/open.c @@ -28,7 +28,7 @@ #include #include -int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) +int vfs_statfs(struct dentry *dentry, struct vfsmount *mnt, struct kstatfs *buf) { int retval = -ENODEV; @@ -40,8 +40,35 @@ int vfs_statfs(struct dentry *dentry, st if (retval) return retval; retval = dentry->d_sb->s_op->statfs(dentry, buf); - if (retval == 0 && buf->f_frsize == 0) - buf->f_frsize = buf->f_bsize; + if (retval == 0) { + unsigned long f_flag = ST_IN_USE; + unsigned long x; + + if (buf->f_frsize == 0) + buf->f_frsize = buf->f_bsize; + + x = dentry->d_inode->i_sb->s_flags; + if (x & MS_RDONLY) + f_flag |= ST_RDONLY; + if (x & MS_SYNCHRONOUS) + f_flag |= ST_SYNCHRONOUS; + if (x & MS_MANDLOCK) + f_flag |= ST_MANDLOCK; + + if (mnt) { + int x = mnt->mnt_flags; + + if (x & MNT_NOSUID) + f_flag |= ST_NOSUID; + if (x & MNT_NODEV) + f_flag |= ST_NODEV; + if (x & MNT_NOATIME) + f_flag |= ST_NOATIME; + if (x & MNT_NODIRATIME) + f_flag |= ST_NODIRATIME; + } + buf->f_flag = f_flag; + } } } return retval; @@ -49,12 +76,13 @@ int vfs_statfs(struct dentry *dentry, st EXPORT_SYMBOL(vfs_statfs); -static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf) +static int vfs_statfs_native(struct dentry *dentry, struct vfsmount *mnt, + struct statfs *buf) { struct kstatfs st; int retval; - retval = vfs_statfs(dentry, &st); + retval = vfs_statfs(dentry, mnt, &st); if (retval) return retval; @@ -87,17 +115,19 @@ static int vfs_statfs_native(struct dent buf->f_fsid = st.f_fsid; buf->f_namelen = st.f_namelen; buf->f_frsize = st.f_frsize; + buf->f_flag = st.f_flag; memset(buf->f_spare, 0, sizeof(buf->f_spare)); } return 0; } -static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf) +static int vfs_statfs64(struct dentry *dentry, struct vfsmount *mnt, + struct statfs64 *buf) { struct kstatfs st; int retval; - retval = vfs_statfs(dentry, &st); + retval = vfs_statfs(dentry, mnt, &st); if (retval) return retval; @@ -114,6 +144,7 @@ static int vfs_statfs64(struct dentry *d buf->f_fsid = st.f_fsid; buf->f_namelen = st.f_namelen; buf->f_frsize = st.f_frsize; + buf->f_flag = st.f_flag; memset(buf->f_spare, 0, sizeof(buf->f_spare)); } return 0; @@ -127,7 +158,7 @@ asmlinkage long sys_statfs(const char __ error = user_path_walk(path, &nd); if (!error) { struct statfs tmp; - error = vfs_statfs_native(nd.dentry, &tmp); + error = vfs_statfs_native(nd.dentry, nd.mnt, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; path_release(&nd); @@ -146,7 +177,7 @@ asmlinkage long sys_statfs64(const char error = user_path_walk(path, &nd); if (!error) { struct statfs64 tmp; - error = vfs_statfs64(nd.dentry, &tmp); + error = vfs_statfs64(nd.dentry, nd.mnt, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; path_release(&nd); @@ -165,7 +196,7 @@ asmlinkage long sys_fstatfs(unsigned int file = fget(fd); if (!file) goto out; - error = vfs_statfs_native(file->f_path.dentry, &tmp); + error = vfs_statfs_native(file->f_path.dentry, file->f_path.mnt, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); @@ -186,7 +217,7 @@ asmlinkage long sys_fstatfs64(unsigned i file = fget(fd); if (!file) goto out; - error = vfs_statfs64(file->f_path.dentry, &tmp); + error = vfs_statfs64(file->f_path.dentry, file->f_path.mnt, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); --- a/fs/super.c +++ b/fs/super.c @@ -542,7 +542,7 @@ asmlinkage long sys_ustat(unsigned dev, s = user_get_super(new_decode_dev(dev)); if (s == NULL) goto out; - err = vfs_statfs(s->s_root, &sbuf); + err = vfs_statfs(s->s_root, NULL, &sbuf); drop_super(s); if (err) goto out; --- a/include/asm-generic/statfs.h +++ b/include/asm-generic/statfs.h @@ -17,7 +17,8 @@ struct statfs { __kernel_fsid_t f_fsid; __u32 f_namelen; __u32 f_frsize; - __u32 f_spare[5]; + __u32 f_flag; + __u32 f_spare[4]; }; struct statfs64 { @@ -31,7 +32,8 @@ struct statfs64 { __kernel_fsid_t f_fsid; __u32 f_namelen; __u32 f_frsize; - __u32 f_spare[5]; + __u32 f_flag; + __u32 f_spare[4]; }; struct compat_statfs64 { @@ -45,7 +47,8 @@ struct compat_statfs64 { __kernel_fsid_t f_fsid; __u32 f_namelen; __u32 f_frsize; - __u32 f_spare[5]; + __u32 f_flag; + __u32 f_spare[4]; }; #endif --- a/include/asm-x86_64/compat.h +++ b/include/asm-x86_64/compat.h @@ -104,7 +104,8 @@ struct compat_statfs { compat_fsid_t f_fsid; int f_namelen; /* SunOS ignores this field. */ int f_frsize; - int f_spare[5]; + int f_flag; + int f_spare[4]; }; #define COMPAT_RLIM_OLD_INFINITY 0x7fffffff --- a/include/asm-x86_64/statfs.h +++ b/include/asm-x86_64/statfs.h @@ -24,7 +24,8 @@ struct statfs { __kernel_fsid_t f_fsid; long f_namelen; long f_frsize; - long f_spare[5]; + long f_flag; + long f_spare[4]; }; struct statfs64 { @@ -38,7 +39,8 @@ struct statfs64 { __kernel_fsid_t f_fsid; long f_namelen; long f_frsize; - long f_spare[5]; + long f_flag; + long f_spare[4]; }; struct compat_statfs64 { @@ -52,7 +54,8 @@ struct compat_statfs64 { __kernel_fsid_t f_fsid; __u32 f_namelen; __u32 f_frsize; - __u32 f_spare[5]; + __u32 f_flag; + __u32 f_spare[4]; } __attribute__((packed)); #endif --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1408,7 +1408,7 @@ extern struct vfsmount *copy_tree(struct extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, struct vfsmount *); -extern int vfs_statfs(struct dentry *, struct kstatfs *); +extern int vfs_statfs(struct dentry *, struct vfsmount *, struct kstatfs *); /* /sys/fs */ extern struct subsystem fs_subsys; --- a/include/linux/statfs.h +++ b/include/linux/statfs.h @@ -16,7 +16,18 @@ struct kstatfs { __kernel_fsid_t f_fsid; long f_namelen; long f_frsize; - long f_spare[5]; + unsigned long f_flag; + long f_spare[4]; }; +#define ST_RDONLY 1 +#define ST_NOSUID 2 +#define ST_NODEV 4 +#define ST_NOEXEC 8 +#define ST_SYNCHRONOUS 16 +#define ST_MANDLOCK 64 +#define ST_NOATIME 1024 +#define ST_NODIRATIME 2048 +#define ST_IN_USE (1 << 31) + #endif --- a/kernel/acct.c +++ b/kernel/acct.c @@ -118,7 +118,7 @@ static int check_free_space(struct file spin_unlock(&acct_globals.lock); /* May block */ - if (vfs_statfs(file->f_path.dentry, &sbuf)) + if (vfs_statfs(file->f_path.dentry, file->f_path.mnt, &sbuf)) return res; suspend = sbuf.f_blocks * SUSPEND; resume = sbuf.f_blocks * RESUME;