17ed1ee61SAl Viro #include <linux/syscalls.h> 27ed1ee61SAl Viro #include <linux/module.h> 37ed1ee61SAl Viro #include <linux/fs.h> 47ed1ee61SAl Viro #include <linux/file.h> 57ed1ee61SAl Viro #include <linux/namei.h> 67ed1ee61SAl Viro #include <linux/statfs.h> 77ed1ee61SAl Viro #include <linux/security.h> 87ed1ee61SAl Viro #include <linux/uaccess.h> 97ed1ee61SAl Viro 10*ebabe9a9SChristoph Hellwig int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) 117ed1ee61SAl Viro { 12*ebabe9a9SChristoph Hellwig int retval; 137ed1ee61SAl Viro 14*ebabe9a9SChristoph Hellwig if (!dentry->d_sb->s_op->statfs) 15*ebabe9a9SChristoph Hellwig return -ENOSYS; 16*ebabe9a9SChristoph Hellwig 177ed1ee61SAl Viro memset(buf, 0, sizeof(*buf)); 187ed1ee61SAl Viro retval = security_sb_statfs(dentry); 197ed1ee61SAl Viro if (retval) 207ed1ee61SAl Viro return retval; 217ed1ee61SAl Viro retval = dentry->d_sb->s_op->statfs(dentry, buf); 227ed1ee61SAl Viro if (retval == 0 && buf->f_frsize == 0) 237ed1ee61SAl Viro buf->f_frsize = buf->f_bsize; 247ed1ee61SAl Viro return retval; 257ed1ee61SAl Viro } 267ed1ee61SAl Viro 27*ebabe9a9SChristoph Hellwig int vfs_statfs(struct path *path, struct kstatfs *buf) 28*ebabe9a9SChristoph Hellwig { 29*ebabe9a9SChristoph Hellwig return statfs_by_dentry(path->dentry, buf); 30*ebabe9a9SChristoph Hellwig } 317ed1ee61SAl Viro EXPORT_SYMBOL(vfs_statfs); 327ed1ee61SAl Viro 33*ebabe9a9SChristoph Hellwig static int do_statfs_native(struct path *path, struct statfs *buf) 347ed1ee61SAl Viro { 357ed1ee61SAl Viro struct kstatfs st; 367ed1ee61SAl Viro int retval; 377ed1ee61SAl Viro 38*ebabe9a9SChristoph Hellwig retval = vfs_statfs(path, &st); 397ed1ee61SAl Viro if (retval) 407ed1ee61SAl Viro return retval; 417ed1ee61SAl Viro 427ed1ee61SAl Viro if (sizeof(*buf) == sizeof(st)) 437ed1ee61SAl Viro memcpy(buf, &st, sizeof(st)); 447ed1ee61SAl Viro else { 457ed1ee61SAl Viro if (sizeof buf->f_blocks == 4) { 467ed1ee61SAl Viro if ((st.f_blocks | st.f_bfree | st.f_bavail | 477ed1ee61SAl Viro st.f_bsize | st.f_frsize) & 487ed1ee61SAl Viro 0xffffffff00000000ULL) 497ed1ee61SAl Viro return -EOVERFLOW; 507ed1ee61SAl Viro /* 517ed1ee61SAl Viro * f_files and f_ffree may be -1; it's okay to stuff 527ed1ee61SAl Viro * that into 32 bits 537ed1ee61SAl Viro */ 547ed1ee61SAl Viro if (st.f_files != -1 && 557ed1ee61SAl Viro (st.f_files & 0xffffffff00000000ULL)) 567ed1ee61SAl Viro return -EOVERFLOW; 577ed1ee61SAl Viro if (st.f_ffree != -1 && 587ed1ee61SAl Viro (st.f_ffree & 0xffffffff00000000ULL)) 597ed1ee61SAl Viro return -EOVERFLOW; 607ed1ee61SAl Viro } 617ed1ee61SAl Viro 627ed1ee61SAl Viro buf->f_type = st.f_type; 637ed1ee61SAl Viro buf->f_bsize = st.f_bsize; 647ed1ee61SAl Viro buf->f_blocks = st.f_blocks; 657ed1ee61SAl Viro buf->f_bfree = st.f_bfree; 667ed1ee61SAl Viro buf->f_bavail = st.f_bavail; 677ed1ee61SAl Viro buf->f_files = st.f_files; 687ed1ee61SAl Viro buf->f_ffree = st.f_ffree; 697ed1ee61SAl Viro buf->f_fsid = st.f_fsid; 707ed1ee61SAl Viro buf->f_namelen = st.f_namelen; 717ed1ee61SAl Viro buf->f_frsize = st.f_frsize; 727ed1ee61SAl Viro memset(buf->f_spare, 0, sizeof(buf->f_spare)); 737ed1ee61SAl Viro } 747ed1ee61SAl Viro return 0; 757ed1ee61SAl Viro } 767ed1ee61SAl Viro 77*ebabe9a9SChristoph Hellwig static int do_statfs64(struct path *path, struct statfs64 *buf) 787ed1ee61SAl Viro { 797ed1ee61SAl Viro struct kstatfs st; 807ed1ee61SAl Viro int retval; 817ed1ee61SAl Viro 82*ebabe9a9SChristoph Hellwig retval = vfs_statfs(path, &st); 837ed1ee61SAl Viro if (retval) 847ed1ee61SAl Viro return retval; 857ed1ee61SAl Viro 867ed1ee61SAl Viro if (sizeof(*buf) == sizeof(st)) 877ed1ee61SAl Viro memcpy(buf, &st, sizeof(st)); 887ed1ee61SAl Viro else { 897ed1ee61SAl Viro buf->f_type = st.f_type; 907ed1ee61SAl Viro buf->f_bsize = st.f_bsize; 917ed1ee61SAl Viro buf->f_blocks = st.f_blocks; 927ed1ee61SAl Viro buf->f_bfree = st.f_bfree; 937ed1ee61SAl Viro buf->f_bavail = st.f_bavail; 947ed1ee61SAl Viro buf->f_files = st.f_files; 957ed1ee61SAl Viro buf->f_ffree = st.f_ffree; 967ed1ee61SAl Viro buf->f_fsid = st.f_fsid; 977ed1ee61SAl Viro buf->f_namelen = st.f_namelen; 987ed1ee61SAl Viro buf->f_frsize = st.f_frsize; 997ed1ee61SAl Viro memset(buf->f_spare, 0, sizeof(buf->f_spare)); 1007ed1ee61SAl Viro } 1017ed1ee61SAl Viro return 0; 1027ed1ee61SAl Viro } 1037ed1ee61SAl Viro 1047ed1ee61SAl Viro SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf) 1057ed1ee61SAl Viro { 1067ed1ee61SAl Viro struct path path; 1077ed1ee61SAl Viro int error; 1087ed1ee61SAl Viro 1097ed1ee61SAl Viro error = user_path(pathname, &path); 1107ed1ee61SAl Viro if (!error) { 1117ed1ee61SAl Viro struct statfs tmp; 112*ebabe9a9SChristoph Hellwig error = do_statfs_native(&path, &tmp); 1137ed1ee61SAl Viro if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 1147ed1ee61SAl Viro error = -EFAULT; 1157ed1ee61SAl Viro path_put(&path); 1167ed1ee61SAl Viro } 1177ed1ee61SAl Viro return error; 1187ed1ee61SAl Viro } 1197ed1ee61SAl Viro 1207ed1ee61SAl Viro SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf) 1217ed1ee61SAl Viro { 1227ed1ee61SAl Viro struct path path; 1237ed1ee61SAl Viro long error; 1247ed1ee61SAl Viro 1257ed1ee61SAl Viro if (sz != sizeof(*buf)) 1267ed1ee61SAl Viro return -EINVAL; 1277ed1ee61SAl Viro error = user_path(pathname, &path); 1287ed1ee61SAl Viro if (!error) { 1297ed1ee61SAl Viro struct statfs64 tmp; 130*ebabe9a9SChristoph Hellwig error = do_statfs64(&path, &tmp); 1317ed1ee61SAl Viro if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 1327ed1ee61SAl Viro error = -EFAULT; 1337ed1ee61SAl Viro path_put(&path); 1347ed1ee61SAl Viro } 1357ed1ee61SAl Viro return error; 1367ed1ee61SAl Viro } 1377ed1ee61SAl Viro 1387ed1ee61SAl Viro SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf) 1397ed1ee61SAl Viro { 1407ed1ee61SAl Viro struct file *file; 1417ed1ee61SAl Viro struct statfs tmp; 1427ed1ee61SAl Viro int error; 1437ed1ee61SAl Viro 1447ed1ee61SAl Viro error = -EBADF; 1457ed1ee61SAl Viro file = fget(fd); 1467ed1ee61SAl Viro if (!file) 1477ed1ee61SAl Viro goto out; 148*ebabe9a9SChristoph Hellwig error = do_statfs_native(&file->f_path, &tmp); 1497ed1ee61SAl Viro if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 1507ed1ee61SAl Viro error = -EFAULT; 1517ed1ee61SAl Viro fput(file); 1527ed1ee61SAl Viro out: 1537ed1ee61SAl Viro return error; 1547ed1ee61SAl Viro } 1557ed1ee61SAl Viro 1567ed1ee61SAl Viro SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf) 1577ed1ee61SAl Viro { 1587ed1ee61SAl Viro struct file *file; 1597ed1ee61SAl Viro struct statfs64 tmp; 1607ed1ee61SAl Viro int error; 1617ed1ee61SAl Viro 1627ed1ee61SAl Viro if (sz != sizeof(*buf)) 1637ed1ee61SAl Viro return -EINVAL; 1647ed1ee61SAl Viro 1657ed1ee61SAl Viro error = -EBADF; 1667ed1ee61SAl Viro file = fget(fd); 1677ed1ee61SAl Viro if (!file) 1687ed1ee61SAl Viro goto out; 169*ebabe9a9SChristoph Hellwig error = do_statfs64(&file->f_path, &tmp); 1707ed1ee61SAl Viro if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 1717ed1ee61SAl Viro error = -EFAULT; 1727ed1ee61SAl Viro fput(file); 1737ed1ee61SAl Viro out: 1747ed1ee61SAl Viro return error; 1757ed1ee61SAl Viro } 1767ed1ee61SAl Viro 1777ed1ee61SAl Viro SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf) 1787ed1ee61SAl Viro { 1797ed1ee61SAl Viro struct super_block *s; 1807ed1ee61SAl Viro struct ustat tmp; 1817ed1ee61SAl Viro struct kstatfs sbuf; 1827ed1ee61SAl Viro int err; 1837ed1ee61SAl Viro 1847ed1ee61SAl Viro s = user_get_super(new_decode_dev(dev)); 1857ed1ee61SAl Viro if (!s) 1867ed1ee61SAl Viro return -EINVAL; 1877ed1ee61SAl Viro 188*ebabe9a9SChristoph Hellwig err = statfs_by_dentry(s->s_root, &sbuf); 1897ed1ee61SAl Viro drop_super(s); 1907ed1ee61SAl Viro if (err) 1917ed1ee61SAl Viro return err; 1927ed1ee61SAl Viro 1937ed1ee61SAl Viro memset(&tmp,0,sizeof(struct ustat)); 1947ed1ee61SAl Viro tmp.f_tfree = sbuf.f_bfree; 1957ed1ee61SAl Viro tmp.f_tinode = sbuf.f_ffree; 1967ed1ee61SAl Viro 1977ed1ee61SAl Viro return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0; 1987ed1ee61SAl Viro } 199