1 #include <linux/syscalls.h>
2 #include <linux/export.h>
4 #include <linux/file.h>
5 #include <linux/mount.h>
6 #include <linux/namei.h>
7 #include <linux/statfs.h>
8 #include <linux/security.h>
9 #include <linux/uaccess.h>
12 static int flags_by_mnt(int mnt_flags
)
16 if (mnt_flags
& MNT_READONLY
)
18 if (mnt_flags
& MNT_NOSUID
)
20 if (mnt_flags
& MNT_NODEV
)
22 if (mnt_flags
& MNT_NOEXEC
)
24 if (mnt_flags
& MNT_NOATIME
)
26 if (mnt_flags
& MNT_NODIRATIME
)
27 flags
|= ST_NODIRATIME
;
28 if (mnt_flags
& MNT_RELATIME
)
33 static int flags_by_sb(int s_flags
)
36 if (s_flags
& MS_SYNCHRONOUS
)
37 flags
|= ST_SYNCHRONOUS
;
38 if (s_flags
& MS_MANDLOCK
)
43 static int calculate_f_flags(struct vfsmount
*mnt
)
45 return ST_VALID
| flags_by_mnt(mnt
->mnt_flags
) |
46 flags_by_sb(mnt
->mnt_sb
->s_flags
);
49 static int statfs_by_dentry(struct dentry
*dentry
, struct kstatfs
*buf
)
53 if (!dentry
->d_sb
->s_op
->statfs
)
56 memset(buf
, 0, sizeof(*buf
));
57 retval
= security_sb_statfs(dentry
);
60 retval
= dentry
->d_sb
->s_op
->statfs(dentry
, buf
);
61 if (retval
== 0 && buf
->f_frsize
== 0)
62 buf
->f_frsize
= buf
->f_bsize
;
66 int vfs_statfs(const struct path
*path
, struct kstatfs
*buf
)
70 error
= statfs_by_dentry(path
->dentry
, buf
);
72 buf
->f_flags
= calculate_f_flags(path
->mnt
);
75 EXPORT_SYMBOL(vfs_statfs
);
77 int user_statfs(const char __user
*pathname
, struct kstatfs
*st
)
81 unsigned int lookup_flags
= LOOKUP_FOLLOW
|LOOKUP_AUTOMOUNT
;
83 error
= user_path_at(AT_FDCWD
, pathname
, lookup_flags
, &path
);
85 error
= vfs_statfs(&path
, st
);
87 if (retry_estale(error
, lookup_flags
)) {
88 lookup_flags
|= LOOKUP_REVAL
;
95 int fd_statfs(int fd
, struct kstatfs
*st
)
97 struct fd f
= fdget_raw(fd
);
100 error
= vfs_statfs(&f
.file
->f_path
, st
);
106 static int do_statfs_native(struct kstatfs
*st
, struct statfs __user
*p
)
110 if (sizeof(buf
) == sizeof(*st
))
111 memcpy(&buf
, st
, sizeof(*st
));
113 if (sizeof buf
.f_blocks
== 4) {
114 if ((st
->f_blocks
| st
->f_bfree
| st
->f_bavail
|
115 st
->f_bsize
| st
->f_frsize
) &
116 0xffffffff00000000ULL
)
119 * f_files and f_ffree may be -1; it's okay to stuff
122 if (st
->f_files
!= -1 &&
123 (st
->f_files
& 0xffffffff00000000ULL
))
125 if (st
->f_ffree
!= -1 &&
126 (st
->f_ffree
& 0xffffffff00000000ULL
))
130 buf
.f_type
= st
->f_type
;
131 buf
.f_bsize
= st
->f_bsize
;
132 buf
.f_blocks
= st
->f_blocks
;
133 buf
.f_bfree
= st
->f_bfree
;
134 buf
.f_bavail
= st
->f_bavail
;
135 buf
.f_files
= st
->f_files
;
136 buf
.f_ffree
= st
->f_ffree
;
137 buf
.f_fsid
= st
->f_fsid
;
138 buf
.f_namelen
= st
->f_namelen
;
139 buf
.f_frsize
= st
->f_frsize
;
140 buf
.f_flags
= st
->f_flags
;
141 memset(buf
.f_spare
, 0, sizeof(buf
.f_spare
));
143 if (copy_to_user(p
, &buf
, sizeof(buf
)))
148 static int do_statfs64(struct kstatfs
*st
, struct statfs64 __user
*p
)
151 if (sizeof(buf
) == sizeof(*st
))
152 memcpy(&buf
, st
, sizeof(*st
));
154 buf
.f_type
= st
->f_type
;
155 buf
.f_bsize
= st
->f_bsize
;
156 buf
.f_blocks
= st
->f_blocks
;
157 buf
.f_bfree
= st
->f_bfree
;
158 buf
.f_bavail
= st
->f_bavail
;
159 buf
.f_files
= st
->f_files
;
160 buf
.f_ffree
= st
->f_ffree
;
161 buf
.f_fsid
= st
->f_fsid
;
162 buf
.f_namelen
= st
->f_namelen
;
163 buf
.f_frsize
= st
->f_frsize
;
164 buf
.f_flags
= st
->f_flags
;
165 memset(buf
.f_spare
, 0, sizeof(buf
.f_spare
));
167 if (copy_to_user(p
, &buf
, sizeof(buf
)))
172 SYSCALL_DEFINE2(statfs
, const char __user
*, pathname
, struct statfs __user
*, buf
)
175 int error
= user_statfs(pathname
, &st
);
177 error
= do_statfs_native(&st
, buf
);
181 SYSCALL_DEFINE3(statfs64
, const char __user
*, pathname
, size_t, sz
, struct statfs64 __user
*, buf
)
185 if (sz
!= sizeof(*buf
))
187 error
= user_statfs(pathname
, &st
);
189 error
= do_statfs64(&st
, buf
);
193 SYSCALL_DEFINE2(fstatfs
, unsigned int, fd
, struct statfs __user
*, buf
)
196 int error
= fd_statfs(fd
, &st
);
198 error
= do_statfs_native(&st
, buf
);
202 SYSCALL_DEFINE3(fstatfs64
, unsigned int, fd
, size_t, sz
, struct statfs64 __user
*, buf
)
207 if (sz
!= sizeof(*buf
))
210 error
= fd_statfs(fd
, &st
);
212 error
= do_statfs64(&st
, buf
);
216 int vfs_ustat(dev_t dev
, struct kstatfs
*sbuf
)
218 struct super_block
*s
= user_get_super(dev
);
223 err
= statfs_by_dentry(s
->s_root
, sbuf
);
228 SYSCALL_DEFINE2(ustat
, unsigned, dev
, struct ustat __user
*, ubuf
)
232 int err
= vfs_ustat(new_decode_dev(dev
), &sbuf
);
236 memset(&tmp
,0,sizeof(struct ustat
));
237 tmp
.f_tfree
= sbuf
.f_bfree
;
238 tmp
.f_tinode
= sbuf
.f_ffree
;
240 return copy_to_user(ubuf
, &tmp
, sizeof(struct ustat
)) ? -EFAULT
: 0;