xref: /openbmc/linux/fs/statfs.c (revision ae2a9762d6f54331f683464f07498cf66e7c125c)
17ed1ee61SAl Viro #include <linux/syscalls.h>
2630d9c47SPaul Gortmaker #include <linux/export.h>
37ed1ee61SAl Viro #include <linux/fs.h>
47ed1ee61SAl Viro #include <linux/file.h>
5365b1818SChristoph Hellwig #include <linux/mount.h>
67ed1ee61SAl Viro #include <linux/namei.h>
77ed1ee61SAl Viro #include <linux/statfs.h>
87ed1ee61SAl Viro #include <linux/security.h>
97ed1ee61SAl Viro #include <linux/uaccess.h>
104ada54eeSAl Viro #include <linux/compat.h>
11cf31e70dSAl Viro #include "internal.h"
127ed1ee61SAl Viro 
13365b1818SChristoph Hellwig static int flags_by_mnt(int mnt_flags)
14365b1818SChristoph Hellwig {
15365b1818SChristoph Hellwig 	int flags = 0;
16365b1818SChristoph Hellwig 
17365b1818SChristoph Hellwig 	if (mnt_flags & MNT_READONLY)
18365b1818SChristoph Hellwig 		flags |= ST_RDONLY;
19365b1818SChristoph Hellwig 	if (mnt_flags & MNT_NOSUID)
20365b1818SChristoph Hellwig 		flags |= ST_NOSUID;
21365b1818SChristoph Hellwig 	if (mnt_flags & MNT_NODEV)
22365b1818SChristoph Hellwig 		flags |= ST_NODEV;
23365b1818SChristoph Hellwig 	if (mnt_flags & MNT_NOEXEC)
24365b1818SChristoph Hellwig 		flags |= ST_NOEXEC;
25365b1818SChristoph Hellwig 	if (mnt_flags & MNT_NOATIME)
26365b1818SChristoph Hellwig 		flags |= ST_NOATIME;
27365b1818SChristoph Hellwig 	if (mnt_flags & MNT_NODIRATIME)
28365b1818SChristoph Hellwig 		flags |= ST_NODIRATIME;
29365b1818SChristoph Hellwig 	if (mnt_flags & MNT_RELATIME)
30365b1818SChristoph Hellwig 		flags |= ST_RELATIME;
31365b1818SChristoph Hellwig 	return flags;
32365b1818SChristoph Hellwig }
33365b1818SChristoph Hellwig 
34365b1818SChristoph Hellwig static int flags_by_sb(int s_flags)
35365b1818SChristoph Hellwig {
36365b1818SChristoph Hellwig 	int flags = 0;
37365b1818SChristoph Hellwig 	if (s_flags & MS_SYNCHRONOUS)
38365b1818SChristoph Hellwig 		flags |= ST_SYNCHRONOUS;
39365b1818SChristoph Hellwig 	if (s_flags & MS_MANDLOCK)
40365b1818SChristoph Hellwig 		flags |= ST_MANDLOCK;
41365b1818SChristoph Hellwig 	return flags;
42365b1818SChristoph Hellwig }
43365b1818SChristoph Hellwig 
44365b1818SChristoph Hellwig static int calculate_f_flags(struct vfsmount *mnt)
45365b1818SChristoph Hellwig {
46365b1818SChristoph Hellwig 	return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
47365b1818SChristoph Hellwig 		flags_by_sb(mnt->mnt_sb->s_flags);
48365b1818SChristoph Hellwig }
49365b1818SChristoph Hellwig 
50cf31e70dSAl Viro static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
517ed1ee61SAl Viro {
52ebabe9a9SChristoph Hellwig 	int retval;
537ed1ee61SAl Viro 
54ebabe9a9SChristoph Hellwig 	if (!dentry->d_sb->s_op->statfs)
55ebabe9a9SChristoph Hellwig 		return -ENOSYS;
56ebabe9a9SChristoph Hellwig 
577ed1ee61SAl Viro 	memset(buf, 0, sizeof(*buf));
587ed1ee61SAl Viro 	retval = security_sb_statfs(dentry);
597ed1ee61SAl Viro 	if (retval)
607ed1ee61SAl Viro 		return retval;
617ed1ee61SAl Viro 	retval = dentry->d_sb->s_op->statfs(dentry, buf);
627ed1ee61SAl Viro 	if (retval == 0 && buf->f_frsize == 0)
637ed1ee61SAl Viro 		buf->f_frsize = buf->f_bsize;
647ed1ee61SAl Viro 	return retval;
657ed1ee61SAl Viro }
667ed1ee61SAl Viro 
67f0bb5aafSAl Viro int vfs_statfs(const struct path *path, struct kstatfs *buf)
68ebabe9a9SChristoph Hellwig {
69365b1818SChristoph Hellwig 	int error;
70365b1818SChristoph Hellwig 
71365b1818SChristoph Hellwig 	error = statfs_by_dentry(path->dentry, buf);
72365b1818SChristoph Hellwig 	if (!error)
73365b1818SChristoph Hellwig 		buf->f_flags = calculate_f_flags(path->mnt);
74365b1818SChristoph Hellwig 	return error;
75ebabe9a9SChristoph Hellwig }
767ed1ee61SAl Viro EXPORT_SYMBOL(vfs_statfs);
777ed1ee61SAl Viro 
78c8b91accSAl Viro int user_statfs(const char __user *pathname, struct kstatfs *st)
797ed1ee61SAl Viro {
80c8b91accSAl Viro 	struct path path;
8196948fc6SJeff Layton 	int error;
8296948fc6SJeff Layton 	unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
8396948fc6SJeff Layton retry:
8496948fc6SJeff Layton 	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
85c8b91accSAl Viro 	if (!error) {
86c8b91accSAl Viro 		error = vfs_statfs(&path, st);
87c8b91accSAl Viro 		path_put(&path);
8896948fc6SJeff Layton 		if (retry_estale(error, lookup_flags)) {
8996948fc6SJeff Layton 			lookup_flags |= LOOKUP_REVAL;
9096948fc6SJeff Layton 			goto retry;
9196948fc6SJeff Layton 		}
92c8b91accSAl Viro 	}
93c8b91accSAl Viro 	return error;
94c8b91accSAl Viro }
957ed1ee61SAl Viro 
96c8b91accSAl Viro int fd_statfs(int fd, struct kstatfs *st)
97c8b91accSAl Viro {
989d05746eSLinus Torvalds 	struct fd f = fdget_raw(fd);
99c8b91accSAl Viro 	int error = -EBADF;
1002903ff01SAl Viro 	if (f.file) {
1012903ff01SAl Viro 		error = vfs_statfs(&f.file->f_path, st);
1022903ff01SAl Viro 		fdput(f);
103c8b91accSAl Viro 	}
104c8b91accSAl Viro 	return error;
105c8b91accSAl Viro }
1067ed1ee61SAl Viro 
107c8b91accSAl Viro static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
108c8b91accSAl Viro {
109c8b91accSAl Viro 	struct statfs buf;
110c8b91accSAl Viro 
111c8b91accSAl Viro 	if (sizeof(buf) == sizeof(*st))
112c8b91accSAl Viro 		memcpy(&buf, st, sizeof(*st));
1137ed1ee61SAl Viro 	else {
114c8b91accSAl Viro 		if (sizeof buf.f_blocks == 4) {
115c8b91accSAl Viro 			if ((st->f_blocks | st->f_bfree | st->f_bavail |
116c8b91accSAl Viro 			     st->f_bsize | st->f_frsize) &
1177ed1ee61SAl Viro 			    0xffffffff00000000ULL)
1187ed1ee61SAl Viro 				return -EOVERFLOW;
1197ed1ee61SAl Viro 			/*
1207ed1ee61SAl Viro 			 * f_files and f_ffree may be -1; it's okay to stuff
1217ed1ee61SAl Viro 			 * that into 32 bits
1227ed1ee61SAl Viro 			 */
123c8b91accSAl Viro 			if (st->f_files != -1 &&
124c8b91accSAl Viro 			    (st->f_files & 0xffffffff00000000ULL))
1257ed1ee61SAl Viro 				return -EOVERFLOW;
126c8b91accSAl Viro 			if (st->f_ffree != -1 &&
127c8b91accSAl Viro 			    (st->f_ffree & 0xffffffff00000000ULL))
1287ed1ee61SAl Viro 				return -EOVERFLOW;
1297ed1ee61SAl Viro 		}
1307ed1ee61SAl Viro 
131c8b91accSAl Viro 		buf.f_type = st->f_type;
132c8b91accSAl Viro 		buf.f_bsize = st->f_bsize;
133c8b91accSAl Viro 		buf.f_blocks = st->f_blocks;
134c8b91accSAl Viro 		buf.f_bfree = st->f_bfree;
135c8b91accSAl Viro 		buf.f_bavail = st->f_bavail;
136c8b91accSAl Viro 		buf.f_files = st->f_files;
137c8b91accSAl Viro 		buf.f_ffree = st->f_ffree;
138c8b91accSAl Viro 		buf.f_fsid = st->f_fsid;
139c8b91accSAl Viro 		buf.f_namelen = st->f_namelen;
140c8b91accSAl Viro 		buf.f_frsize = st->f_frsize;
141c8b91accSAl Viro 		buf.f_flags = st->f_flags;
142c8b91accSAl Viro 		memset(buf.f_spare, 0, sizeof(buf.f_spare));
1437ed1ee61SAl Viro 	}
144c8b91accSAl Viro 	if (copy_to_user(p, &buf, sizeof(buf)))
145c8b91accSAl Viro 		return -EFAULT;
1467ed1ee61SAl Viro 	return 0;
1477ed1ee61SAl Viro }
1487ed1ee61SAl Viro 
149c8b91accSAl Viro static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
1507ed1ee61SAl Viro {
151c8b91accSAl Viro 	struct statfs64 buf;
152c8b91accSAl Viro 	if (sizeof(buf) == sizeof(*st))
153c8b91accSAl Viro 		memcpy(&buf, st, sizeof(*st));
1547ed1ee61SAl Viro 	else {
155c8b91accSAl Viro 		buf.f_type = st->f_type;
156c8b91accSAl Viro 		buf.f_bsize = st->f_bsize;
157c8b91accSAl Viro 		buf.f_blocks = st->f_blocks;
158c8b91accSAl Viro 		buf.f_bfree = st->f_bfree;
159c8b91accSAl Viro 		buf.f_bavail = st->f_bavail;
160c8b91accSAl Viro 		buf.f_files = st->f_files;
161c8b91accSAl Viro 		buf.f_ffree = st->f_ffree;
162c8b91accSAl Viro 		buf.f_fsid = st->f_fsid;
163c8b91accSAl Viro 		buf.f_namelen = st->f_namelen;
164c8b91accSAl Viro 		buf.f_frsize = st->f_frsize;
165c8b91accSAl Viro 		buf.f_flags = st->f_flags;
166c8b91accSAl Viro 		memset(buf.f_spare, 0, sizeof(buf.f_spare));
1677ed1ee61SAl Viro 	}
168c8b91accSAl Viro 	if (copy_to_user(p, &buf, sizeof(buf)))
169c8b91accSAl Viro 		return -EFAULT;
1707ed1ee61SAl Viro 	return 0;
1717ed1ee61SAl Viro }
1727ed1ee61SAl Viro 
1737ed1ee61SAl Viro SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
1747ed1ee61SAl Viro {
175c8b91accSAl Viro 	struct kstatfs st;
176c8b91accSAl Viro 	int error = user_statfs(pathname, &st);
177c8b91accSAl Viro 	if (!error)
178c8b91accSAl Viro 		error = do_statfs_native(&st, buf);
1797ed1ee61SAl Viro 	return error;
1807ed1ee61SAl Viro }
1817ed1ee61SAl Viro 
1827ed1ee61SAl Viro SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
1837ed1ee61SAl Viro {
184c8b91accSAl Viro 	struct kstatfs st;
185c8b91accSAl Viro 	int error;
1867ed1ee61SAl Viro 	if (sz != sizeof(*buf))
1877ed1ee61SAl Viro 		return -EINVAL;
188c8b91accSAl Viro 	error = user_statfs(pathname, &st);
189c8b91accSAl Viro 	if (!error)
190c8b91accSAl Viro 		error = do_statfs64(&st, buf);
1917ed1ee61SAl Viro 	return error;
1927ed1ee61SAl Viro }
1937ed1ee61SAl Viro 
1947ed1ee61SAl Viro SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
1957ed1ee61SAl Viro {
196c8b91accSAl Viro 	struct kstatfs st;
197c8b91accSAl Viro 	int error = fd_statfs(fd, &st);
198c8b91accSAl Viro 	if (!error)
199c8b91accSAl Viro 		error = do_statfs_native(&st, buf);
2007ed1ee61SAl Viro 	return error;
2017ed1ee61SAl Viro }
2027ed1ee61SAl Viro 
2037ed1ee61SAl Viro SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
2047ed1ee61SAl Viro {
205c8b91accSAl Viro 	struct kstatfs st;
2067ed1ee61SAl Viro 	int error;
2077ed1ee61SAl Viro 
2087ed1ee61SAl Viro 	if (sz != sizeof(*buf))
2097ed1ee61SAl Viro 		return -EINVAL;
2107ed1ee61SAl Viro 
211c8b91accSAl Viro 	error = fd_statfs(fd, &st);
212c8b91accSAl Viro 	if (!error)
213c8b91accSAl Viro 		error = do_statfs64(&st, buf);
2147ed1ee61SAl Viro 	return error;
2157ed1ee61SAl Viro }
2167ed1ee61SAl Viro 
217cf31e70dSAl Viro int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
2187ed1ee61SAl Viro {
219cf31e70dSAl Viro 	struct super_block *s = user_get_super(dev);
2207ed1ee61SAl Viro 	int err;
2217ed1ee61SAl Viro 	if (!s)
2227ed1ee61SAl Viro 		return -EINVAL;
2237ed1ee61SAl Viro 
224cf31e70dSAl Viro 	err = statfs_by_dentry(s->s_root, sbuf);
2257ed1ee61SAl Viro 	drop_super(s);
226cf31e70dSAl Viro 	return err;
227cf31e70dSAl Viro }
228cf31e70dSAl Viro 
229cf31e70dSAl Viro SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
230cf31e70dSAl Viro {
231cf31e70dSAl Viro 	struct ustat tmp;
232cf31e70dSAl Viro 	struct kstatfs sbuf;
233cf31e70dSAl Viro 	int err = vfs_ustat(new_decode_dev(dev), &sbuf);
2347ed1ee61SAl Viro 	if (err)
2357ed1ee61SAl Viro 		return err;
2367ed1ee61SAl Viro 
2377ed1ee61SAl Viro 	memset(&tmp,0,sizeof(struct ustat));
2387ed1ee61SAl Viro 	tmp.f_tfree = sbuf.f_bfree;
2397ed1ee61SAl Viro 	tmp.f_tinode = sbuf.f_ffree;
2407ed1ee61SAl Viro 
2417ed1ee61SAl Viro 	return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
2427ed1ee61SAl Viro }
2434ada54eeSAl Viro 
2444ada54eeSAl Viro #ifdef CONFIG_COMPAT
2454ada54eeSAl Viro static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
2464ada54eeSAl Viro {
247*ae2a9762SAl Viro 	struct compat_statfs buf;
2484ada54eeSAl Viro 	if (sizeof ubuf->f_blocks == 4) {
2494ada54eeSAl Viro 		if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
2504ada54eeSAl Viro 		     kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
2514ada54eeSAl Viro 			return -EOVERFLOW;
2524ada54eeSAl Viro 		/* f_files and f_ffree may be -1; it's okay
2534ada54eeSAl Viro 		 * to stuff that into 32 bits */
2544ada54eeSAl Viro 		if (kbuf->f_files != 0xffffffffffffffffULL
2554ada54eeSAl Viro 		 && (kbuf->f_files & 0xffffffff00000000ULL))
2564ada54eeSAl Viro 			return -EOVERFLOW;
2574ada54eeSAl Viro 		if (kbuf->f_ffree != 0xffffffffffffffffULL
2584ada54eeSAl Viro 		 && (kbuf->f_ffree & 0xffffffff00000000ULL))
2594ada54eeSAl Viro 			return -EOVERFLOW;
2604ada54eeSAl Viro 	}
261*ae2a9762SAl Viro 	memset(&buf, 0, sizeof(struct compat_statfs));
262*ae2a9762SAl Viro 	buf.f_type = kbuf->f_type;
263*ae2a9762SAl Viro 	buf.f_bsize = kbuf->f_bsize;
264*ae2a9762SAl Viro 	buf.f_blocks = kbuf->f_blocks;
265*ae2a9762SAl Viro 	buf.f_bfree = kbuf->f_bfree;
266*ae2a9762SAl Viro 	buf.f_bavail = kbuf->f_bavail;
267*ae2a9762SAl Viro 	buf.f_files = kbuf->f_files;
268*ae2a9762SAl Viro 	buf.f_ffree = kbuf->f_ffree;
269*ae2a9762SAl Viro 	buf.f_namelen = kbuf->f_namelen;
270*ae2a9762SAl Viro 	buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
271*ae2a9762SAl Viro 	buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
272*ae2a9762SAl Viro 	buf.f_frsize = kbuf->f_frsize;
273*ae2a9762SAl Viro 	buf.f_flags = kbuf->f_flags;
274*ae2a9762SAl Viro 	if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs)))
2754ada54eeSAl Viro 		return -EFAULT;
2764ada54eeSAl Viro 	return 0;
2774ada54eeSAl Viro }
2784ada54eeSAl Viro 
2794ada54eeSAl Viro /*
2804ada54eeSAl Viro  * The following statfs calls are copies of code from fs/statfs.c and
2814ada54eeSAl Viro  * should be checked against those from time to time
2824ada54eeSAl Viro  */
2834ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
2844ada54eeSAl Viro {
2854ada54eeSAl Viro 	struct kstatfs tmp;
2864ada54eeSAl Viro 	int error = user_statfs(pathname, &tmp);
2874ada54eeSAl Viro 	if (!error)
2884ada54eeSAl Viro 		error = put_compat_statfs(buf, &tmp);
2894ada54eeSAl Viro 	return error;
2904ada54eeSAl Viro }
2914ada54eeSAl Viro 
2924ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
2934ada54eeSAl Viro {
2944ada54eeSAl Viro 	struct kstatfs tmp;
2954ada54eeSAl Viro 	int error = fd_statfs(fd, &tmp);
2964ada54eeSAl Viro 	if (!error)
2974ada54eeSAl Viro 		error = put_compat_statfs(buf, &tmp);
2984ada54eeSAl Viro 	return error;
2994ada54eeSAl Viro }
3004ada54eeSAl Viro 
3014ada54eeSAl Viro static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
3024ada54eeSAl Viro {
303*ae2a9762SAl Viro 	struct compat_statfs64 buf;
3044ada54eeSAl Viro 	if (sizeof(ubuf->f_bsize) == 4) {
3054ada54eeSAl Viro 		if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen |
3064ada54eeSAl Viro 		     kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL)
3074ada54eeSAl Viro 			return -EOVERFLOW;
3084ada54eeSAl Viro 		/* f_files and f_ffree may be -1; it's okay
3094ada54eeSAl Viro 		 * to stuff that into 32 bits */
3104ada54eeSAl Viro 		if (kbuf->f_files != 0xffffffffffffffffULL
3114ada54eeSAl Viro 		 && (kbuf->f_files & 0xffffffff00000000ULL))
3124ada54eeSAl Viro 			return -EOVERFLOW;
3134ada54eeSAl Viro 		if (kbuf->f_ffree != 0xffffffffffffffffULL
3144ada54eeSAl Viro 		 && (kbuf->f_ffree & 0xffffffff00000000ULL))
3154ada54eeSAl Viro 			return -EOVERFLOW;
3164ada54eeSAl Viro 	}
317*ae2a9762SAl Viro 	memset(&buf, 0, sizeof(struct compat_statfs64));
318*ae2a9762SAl Viro 	buf.f_type = kbuf->f_type;
319*ae2a9762SAl Viro 	buf.f_bsize = kbuf->f_bsize;
320*ae2a9762SAl Viro 	buf.f_blocks = kbuf->f_blocks;
321*ae2a9762SAl Viro 	buf.f_bfree = kbuf->f_bfree;
322*ae2a9762SAl Viro 	buf.f_bavail = kbuf->f_bavail;
323*ae2a9762SAl Viro 	buf.f_files = kbuf->f_files;
324*ae2a9762SAl Viro 	buf.f_ffree = kbuf->f_ffree;
325*ae2a9762SAl Viro 	buf.f_namelen = kbuf->f_namelen;
326*ae2a9762SAl Viro 	buf.f_fsid.val[0] = kbuf->f_fsid.val[0];
327*ae2a9762SAl Viro 	buf.f_fsid.val[1] = kbuf->f_fsid.val[1];
328*ae2a9762SAl Viro 	buf.f_frsize = kbuf->f_frsize;
329*ae2a9762SAl Viro 	buf.f_flags = kbuf->f_flags;
330*ae2a9762SAl Viro 	if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64)))
3314ada54eeSAl Viro 		return -EFAULT;
3324ada54eeSAl Viro 	return 0;
3334ada54eeSAl Viro }
3344ada54eeSAl Viro 
3354ada54eeSAl Viro COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
3364ada54eeSAl Viro {
3374ada54eeSAl Viro 	struct kstatfs tmp;
3384ada54eeSAl Viro 	int error;
3394ada54eeSAl Viro 
3404ada54eeSAl Viro 	if (sz != sizeof(*buf))
3414ada54eeSAl Viro 		return -EINVAL;
3424ada54eeSAl Viro 
3434ada54eeSAl Viro 	error = user_statfs(pathname, &tmp);
3444ada54eeSAl Viro 	if (!error)
3454ada54eeSAl Viro 		error = put_compat_statfs64(buf, &tmp);
3464ada54eeSAl Viro 	return error;
3474ada54eeSAl Viro }
3484ada54eeSAl Viro 
3494ada54eeSAl Viro COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
3504ada54eeSAl Viro {
3514ada54eeSAl Viro 	struct kstatfs tmp;
3524ada54eeSAl Viro 	int error;
3534ada54eeSAl Viro 
3544ada54eeSAl Viro 	if (sz != sizeof(*buf))
3554ada54eeSAl Viro 		return -EINVAL;
3564ada54eeSAl Viro 
3574ada54eeSAl Viro 	error = fd_statfs(fd, &tmp);
3584ada54eeSAl Viro 	if (!error)
3594ada54eeSAl Viro 		error = put_compat_statfs64(buf, &tmp);
3604ada54eeSAl Viro 	return error;
3614ada54eeSAl Viro }
3624ada54eeSAl Viro 
3634ada54eeSAl Viro /*
3644ada54eeSAl Viro  * This is a copy of sys_ustat, just dealing with a structure layout.
3654ada54eeSAl Viro  * Given how simple this syscall is that apporach is more maintainable
3664ada54eeSAl Viro  * than the various conversion hacks.
3674ada54eeSAl Viro  */
3684ada54eeSAl Viro COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
3694ada54eeSAl Viro {
3704ada54eeSAl Viro 	struct compat_ustat tmp;
3714ada54eeSAl Viro 	struct kstatfs sbuf;
3724ada54eeSAl Viro 	int err = vfs_ustat(new_decode_dev(dev), &sbuf);
3734ada54eeSAl Viro 	if (err)
3744ada54eeSAl Viro 		return err;
3754ada54eeSAl Viro 
3764ada54eeSAl Viro 	memset(&tmp, 0, sizeof(struct compat_ustat));
3774ada54eeSAl Viro 	tmp.f_tfree = sbuf.f_bfree;
3784ada54eeSAl Viro 	tmp.f_tinode = sbuf.f_ffree;
3794ada54eeSAl Viro 	if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
3804ada54eeSAl Viro 		return -EFAULT;
3814ada54eeSAl Viro 	return 0;
3824ada54eeSAl Viro }
3834ada54eeSAl Viro #endif
384