clean statfs-like syscalls up
Al Viro [Sat, 12 Mar 2011 15:41:39 +0000 (10:41 -0500)]
New helpers: user_statfs() and fd_statfs(), taking userland pathname and
descriptor resp. and filling struct kstatfs.  Syscalls of statfs family
(native, compat and foreign - osf and hpux on alpha and parisc resp.)
switched to those.  Removes some boilerplate code, simplifies cleanup
on errors...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

arch/alpha/kernel/osf_sys.c
arch/parisc/hpux/sys_hpux.c
fs/compat.c
fs/statfs.c
include/linux/fs.h

index fe698b5..376f221 100644 (file)
@@ -230,44 +230,24 @@ linux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_st
        return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;
 }
 
-static int
-do_osf_statfs(struct path *path, struct osf_statfs __user *buffer,
-             unsigned long bufsiz)
+SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
+               struct osf_statfs __user *, buffer, unsigned long, bufsiz)
 {
        struct kstatfs linux_stat;
-       int error = vfs_statfs(path, &linux_stat);
+       int error = user_statfs(pathname, &linux_stat);
        if (!error)
                error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
        return error;   
 }
 
-SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
-               struct osf_statfs __user *, buffer, unsigned long, bufsiz)
-{
-       struct path path;
-       int retval;
-
-       retval = user_path(pathname, &path);
-       if (!retval) {
-               retval = do_osf_statfs(&path, buffer, bufsiz);
-               path_put(&path);
-       }
-       return retval;
-}
-
 SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd,
                struct osf_statfs __user *, buffer, unsigned long, bufsiz)
 {
-       struct file *file;
-       int retval;
-
-       retval = -EBADF;
-       file = fget(fd);
-       if (file) {
-               retval = do_osf_statfs(&file->f_path, buffer, bufsiz);
-               fput(file);
-       }
-       return retval;
+       struct kstatfs linux_stat;
+       int error = fd_statfs(fd, &linux_stat);
+       if (!error)
+               error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
+       return error;
 }
 
 /*
index 3039408..6ab9580 100644 (file)
@@ -185,26 +185,21 @@ struct hpux_statfs {
      int16_t f_pad;
 };
 
-static int do_statfs_hpux(struct path *path, struct hpux_statfs *buf)
+static int do_statfs_hpux(struct kstatfs *st, struct hpux_statfs __user *p)
 {
-       struct kstatfs st;
-       int retval;
-       
-       retval = vfs_statfs(path, &st);
-       if (retval)
-               return retval;
-
-       memset(buf, 0, sizeof(*buf));
-       buf->f_type = st.f_type;
-       buf->f_bsize = st.f_bsize;
-       buf->f_blocks = st.f_blocks;
-       buf->f_bfree = st.f_bfree;
-       buf->f_bavail = st.f_bavail;
-       buf->f_files = st.f_files;
-       buf->f_ffree = st.f_ffree;
-       buf->f_fsid[0] = st.f_fsid.val[0];
-       buf->f_fsid[1] = st.f_fsid.val[1];
-
+       struct hpux_statfs buf;
+       memset(&buf, 0, sizeof(buf));
+       buf.f_type = st->f_type;
+       buf.f_bsize = st->f_bsize;
+       buf.f_blocks = st->f_blocks;
+       buf.f_bfree = st->f_bfree;
+       buf.f_bavail = st->f_bavail;
+       buf.f_files = st->f_files;
+       buf.f_ffree = st->f_ffree;
+       buf.f_fsid[0] = st->f_fsid.val[0];
+       buf.f_fsid[1] = st->f_fsid.val[1];
+       if (copy_to_user(p, &buf, sizeof(buf)))
+               return -EFAULT;
        return 0;
 }
 
@@ -212,35 +207,19 @@ static int do_statfs_hpux(struct path *path, struct hpux_statfs *buf)
 asmlinkage long hpux_statfs(const char __user *pathname,
                                                struct hpux_statfs __user *buf)
 {
-       struct path path;
-       int error;
-
-       error = user_path(pathname, &path);
-       if (!error) {
-               struct hpux_statfs tmp;
-               error = do_statfs_hpux(&path, &tmp);
-               if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-                       error = -EFAULT;
-               path_put(&path);
-       }
+       struct kstatfs st;
+       int error = user_statfs(pathname, &st);
+       if (!error)
+               error = do_statfs_hpux(&st, buf);
        return error;
 }
 
 asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
 {
-       struct file *file;
-       struct hpux_statfs tmp;
-       int error;
-
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
-       error = do_statfs_hpux(&file->f_path, &tmp);
-       if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-               error = -EFAULT;
-       fput(file);
- out:
+       struct kstatfs st;
+       int error = fd_statfs(fd, &st);
+       if (!error)
+               error = do_statfs_hpux(&st, buf);
        return error;
 }
 
index 691c3fd..a071775 100644 (file)
@@ -262,35 +262,19 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
  */
 asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
 {
-       struct path path;
-       int error;
-
-       error = user_path(pathname, &path);
-       if (!error) {
-               struct kstatfs tmp;
-               error = vfs_statfs(&path, &tmp);
-               if (!error)
-                       error = put_compat_statfs(buf, &tmp);
-               path_put(&path);
-       }
+       struct kstatfs tmp;
+       int error = user_statfs(pathname, &tmp);
+       if (!error)
+               error = put_compat_statfs(buf, &tmp);
        return error;
 }
 
 asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf)
 {
-       struct file * file;
        struct kstatfs tmp;
-       int error;
-
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
-       error = vfs_statfs(&file->f_path, &tmp);
+       int error = fd_statfs(fd, &tmp);
        if (!error)
                error = put_compat_statfs(buf, &tmp);
-       fput(file);
-out:
        return error;
 }
 
@@ -329,41 +313,29 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
 
 asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
-       struct path path;
+       struct kstatfs tmp;
        int error;
 
        if (sz != sizeof(*buf))
                return -EINVAL;
 
-       error = user_path(pathname, &path);
-       if (!error) {
-               struct kstatfs tmp;
-               error = vfs_statfs(&path, &tmp);
-               if (!error)
-                       error = put_compat_statfs64(buf, &tmp);
-               path_put(&path);
-       }
+       error = user_statfs(pathname, &tmp);
+       if (!error)
+               error = put_compat_statfs64(buf, &tmp);
        return error;
 }
 
 asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
-       struct file * file;
        struct kstatfs tmp;
        int error;
 
        if (sz != sizeof(*buf))
                return -EINVAL;
 
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
-       error = vfs_statfs(&file->f_path, &tmp);
+       error = fd_statfs(fd, &tmp);
        if (!error)
                error = put_compat_statfs64(buf, &tmp);
-       fput(file);
-out:
        return error;
 }
 
index 30ea8c8..8244924 100644 (file)
@@ -73,149 +73,135 @@ int vfs_statfs(struct path *path, struct kstatfs *buf)
 }
 EXPORT_SYMBOL(vfs_statfs);
 
-static int do_statfs_native(struct path *path, struct statfs *buf)
+int user_statfs(const char __user *pathname, struct kstatfs *st)
 {
-       struct kstatfs st;
-       int retval;
+       struct path path;
+       int error = user_path(pathname, &path);
+       if (!error) {
+               error = vfs_statfs(&path, st);
+               path_put(&path);
+       }
+       return error;
+}
 
-       retval = vfs_statfs(path, &st);
-       if (retval)
-               return retval;
+int fd_statfs(int fd, struct kstatfs *st)
+{
+       struct file *file = fget(fd);
+       int error = -EBADF;
+       if (file) {
+               error = vfs_statfs(&file->f_path, st);
+               fput(file);
+       }
+       return error;
+}
 
-       if (sizeof(*buf) == sizeof(st))
-               memcpy(buf, &st, sizeof(st));
+static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
+{
+       struct statfs buf;
+
+       if (sizeof(buf) == sizeof(*st))
+               memcpy(&buf, st, sizeof(*st));
        else {
-               if (sizeof buf->f_blocks == 4) {
-                       if ((st.f_blocks | st.f_bfree | st.f_bavail |
-                            st.f_bsize | st.f_frsize) &
+               if (sizeof buf.f_blocks == 4) {
+                       if ((st->f_blocks | st->f_bfree | st->f_bavail |
+                            st->f_bsize | st->f_frsize) &
                            0xffffffff00000000ULL)
                                return -EOVERFLOW;
                        /*
                         * f_files and f_ffree may be -1; it's okay to stuff
                         * that into 32 bits
                         */
-                       if (st.f_files != -1 &&
-                           (st.f_files & 0xffffffff00000000ULL))
+                       if (st->f_files != -1 &&
+                           (st->f_files & 0xffffffff00000000ULL))
                                return -EOVERFLOW;
-                       if (st.f_ffree != -1 &&
-                           (st.f_ffree & 0xffffffff00000000ULL))
+                       if (st->f_ffree != -1 &&
+                           (st->f_ffree & 0xffffffff00000000ULL))
                                return -EOVERFLOW;
                }
 
-               buf->f_type = st.f_type;
-               buf->f_bsize = st.f_bsize;
-               buf->f_blocks = st.f_blocks;
-               buf->f_bfree = st.f_bfree;
-               buf->f_bavail = st.f_bavail;
-               buf->f_files = st.f_files;
-               buf->f_ffree = st.f_ffree;
-               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));
+               buf.f_type = st->f_type;
+               buf.f_bsize = st->f_bsize;
+               buf.f_blocks = st->f_blocks;
+               buf.f_bfree = st->f_bfree;
+               buf.f_bavail = st->f_bavail;
+               buf.f_files = st->f_files;
+               buf.f_ffree = st->f_ffree;
+               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));
        }
+       if (copy_to_user(p, &buf, sizeof(buf)))
+               return -EFAULT;
        return 0;
 }
 
-static int do_statfs64(struct path *path, struct statfs64 *buf)
+static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
 {
-       struct kstatfs st;
-       int retval;
-
-       retval = vfs_statfs(path, &st);
-       if (retval)
-               return retval;
-
-       if (sizeof(*buf) == sizeof(st))
-               memcpy(buf, &st, sizeof(st));
+       struct statfs64 buf;
+       if (sizeof(buf) == sizeof(*st))
+               memcpy(&buf, st, sizeof(*st));
        else {
-               buf->f_type = st.f_type;
-               buf->f_bsize = st.f_bsize;
-               buf->f_blocks = st.f_blocks;
-               buf->f_bfree = st.f_bfree;
-               buf->f_bavail = st.f_bavail;
-               buf->f_files = st.f_files;
-               buf->f_ffree = st.f_ffree;
-               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));
+               buf.f_type = st->f_type;
+               buf.f_bsize = st->f_bsize;
+               buf.f_blocks = st->f_blocks;
+               buf.f_bfree = st->f_bfree;
+               buf.f_bavail = st->f_bavail;
+               buf.f_files = st->f_files;
+               buf.f_ffree = st->f_ffree;
+               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));
        }
+       if (copy_to_user(p, &buf, sizeof(buf)))
+               return -EFAULT;
        return 0;
 }
 
 SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
 {
-       struct path path;
-       int error;
-
-       error = user_path(pathname, &path);
-       if (!error) {
-               struct statfs tmp;
-               error = do_statfs_native(&path, &tmp);
-               if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-                       error = -EFAULT;
-               path_put(&path);
-       }
+       struct kstatfs st;
+       int error = user_statfs(pathname, &st);
+       if (!error)
+               error = do_statfs_native(&st, buf);
        return error;
 }
 
 SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
 {
-       struct path path;
-       long error;
-
+       struct kstatfs st;
+       int error;
        if (sz != sizeof(*buf))
                return -EINVAL;
-       error = user_path(pathname, &path);
-       if (!error) {
-               struct statfs64 tmp;
-               error = do_statfs64(&path, &tmp);
-               if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-                       error = -EFAULT;
-               path_put(&path);
-       }
+       error = user_statfs(pathname, &st);
+       if (!error)
+               error = do_statfs64(&st, buf);
        return error;
 }
 
 SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
 {
-       struct file *file;
-       struct statfs tmp;
-       int error;
-
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
-       error = do_statfs_native(&file->f_path, &tmp);
-       if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-               error = -EFAULT;
-       fput(file);
-out:
+       struct kstatfs st;
+       int error = fd_statfs(fd, &st);
+       if (!error)
+               error = do_statfs_native(&st, buf);
        return error;
 }
 
 SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
 {
-       struct file *file;
-       struct statfs64 tmp;
+       struct kstatfs st;
        int error;
 
        if (sz != sizeof(*buf))
                return -EINVAL;
 
-       error = -EBADF;
-       file = fget(fd);
-       if (!file)
-               goto out;
-       error = do_statfs64(&file->f_path, &tmp);
-       if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-               error = -EFAULT;
-       fput(file);
-out:
+       error = fd_statfs(fd, &st);
+       if (!error)
+               error = do_statfs64(&st, buf);
        return error;
 }
 
index bf5c3c8..b7178b0 100644 (file)
@@ -1874,6 +1874,8 @@ extern void drop_collected_mounts(struct vfsmount *);
 extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
                          struct vfsmount *);
 extern int vfs_statfs(struct path *, struct kstatfs *);
+extern int user_statfs(const char __user *, struct kstatfs *);
+extern int fd_statfs(int, struct kstatfs *);
 extern int statfs_by_dentry(struct dentry *, struct kstatfs *);
 extern int freeze_super(struct super_block *super);
 extern int thaw_super(struct super_block *super);