switch compat readv/writev variants to COMPAT_SYSCALL_DEFINE
Al Viro [Wed, 20 Mar 2013 14:42:10 +0000 (10:42 -0400)]
... and take to fs/read_write.c

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

arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/syscalls.S
fs/compat.c
fs/read_write.c
fs/read_write.h

index 3c98c4d..4d720a6 100644 (file)
@@ -1387,22 +1387,6 @@ ENTRY(compat_sys_keyctl_wrapper)
        llgfr   %r6,%r6                 # u32
        jg      compat_sys_keyctl       # branch to system call
 
-ENTRY(compat_sys_preadv_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgtr   %r3,%r3                 # compat_iovec *
-       llgfr   %r4,%r4                 # unsigned long
-       llgfr   %r5,%r5                 # u32
-       llgfr   %r6,%r6                 # u32
-       jg      compat_sys_preadv       # branch to system call
-
-ENTRY(compat_sys_pwritev_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgtr   %r3,%r3                 # compat_iovec *
-       llgfr   %r4,%r4                 # unsigned long
-       llgfr   %r5,%r5                 # u32
-       llgfr   %r6,%r6                 # u32
-       jg      compat_sys_pwritev      # branch to system call
-
 ENTRY(sys_perf_event_open_wrapper)
        llgtr   %r2,%r2                 # const struct perf_event_attr *
        lgfr    %r3,%r3                 # pid_t
index 630b935..84e8b1a 100644 (file)
@@ -336,8 +336,8 @@ SYSCALL(sys_inotify_init1,sys_inotify_init1,sys_inotify_init1_wrapper)
 SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */
 SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper)
 SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper)
-SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
-SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
+SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv)
+SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev)
 SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */
 SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
 SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper)
index daa3b77..5058345 100644 (file)
@@ -1069,192 +1069,6 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
 }
 #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
 
-static ssize_t compat_do_readv_writev(int type, struct file *file,
-                              const struct compat_iovec __user *uvector,
-                              unsigned long nr_segs, loff_t *pos)
-{
-       compat_ssize_t tot_len;
-       struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov = iovstack;
-       ssize_t ret;
-       io_fn_t fn;
-       iov_fn_t fnv;
-
-       ret = -EINVAL;
-       if (!file->f_op)
-               goto out;
-
-       ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
-                                              UIO_FASTIOV, iovstack, &iov);
-       if (ret <= 0)
-               goto out;
-
-       tot_len = ret;
-       ret = rw_verify_area(type, file, pos, tot_len);
-       if (ret < 0)
-               goto out;
-
-       fnv = NULL;
-       if (type == READ) {
-               fn = file->f_op->read;
-               fnv = file->f_op->aio_read;
-       } else {
-               fn = (io_fn_t)file->f_op->write;
-               fnv = file->f_op->aio_write;
-       }
-
-       if (fnv) {
-               file_start_write(file);
-               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-                                               pos, fnv);
-               file_end_write(file);
-       } else
-               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
-
-out:
-       if (iov != iovstack)
-               kfree(iov);
-       if ((ret + (type == READ)) > 0) {
-               if (type == READ)
-                       fsnotify_access(file);
-               else
-                       fsnotify_modify(file);
-       }
-       return ret;
-}
-
-static size_t compat_readv(struct file *file,
-                          const struct compat_iovec __user *vec,
-                          unsigned long vlen, loff_t *pos)
-{
-       ssize_t ret = -EBADF;
-
-       if (!(file->f_mode & FMODE_READ))
-               goto out;
-
-       ret = -EINVAL;
-       if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
-               goto out;
-
-       ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
-
-out:
-       if (ret > 0)
-               add_rchar(current, ret);
-       inc_syscr(current);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
-                unsigned long vlen)
-{
-       struct fd f = fdget(fd);
-       ssize_t ret;
-       loff_t pos;
-
-       if (!f.file)
-               return -EBADF;
-       pos = f.file->f_pos;
-       ret = compat_readv(f.file, vec, vlen, &pos);
-       f.file->f_pos = pos;
-       fdput(f);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec,
-                   unsigned long vlen, loff_t pos)
-{
-       struct fd f;
-       ssize_t ret;
-
-       if (pos < 0)
-               return -EINVAL;
-       f = fdget(fd);
-       if (!f.file)
-               return -EBADF;
-       ret = -ESPIPE;
-       if (f.file->f_mode & FMODE_PREAD)
-               ret = compat_readv(f.file, vec, vlen, &pos);
-       fdput(f);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
-                 unsigned long vlen, u32 pos_low, u32 pos_high)
-{
-       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-       return compat_sys_preadv64(fd, vec, vlen, pos);
-}
-
-static size_t compat_writev(struct file *file,
-                           const struct compat_iovec __user *vec,
-                           unsigned long vlen, loff_t *pos)
-{
-       ssize_t ret = -EBADF;
-
-       if (!(file->f_mode & FMODE_WRITE))
-               goto out;
-
-       ret = -EINVAL;
-       if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
-               goto out;
-
-       ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
-
-out:
-       if (ret > 0)
-               add_wchar(current, ret);
-       inc_syscw(current);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
-                 unsigned long vlen)
-{
-       struct fd f = fdget(fd);
-       ssize_t ret;
-       loff_t pos;
-
-       if (!f.file)
-               return -EBADF;
-       pos = f.file->f_pos;
-       ret = compat_writev(f.file, vec, vlen, &pos);
-       f.file->f_pos = pos;
-       fdput(f);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec,
-                    unsigned long vlen, loff_t pos)
-{
-       struct fd f;
-       ssize_t ret;
-
-       if (pos < 0)
-               return -EINVAL;
-       f = fdget(fd);
-       if (!f.file)
-               return -EBADF;
-       ret = -ESPIPE;
-       if (f.file->f_mode & FMODE_PWRITE)
-               ret = compat_writev(f.file, vec, vlen, &pos);
-       fdput(f);
-       return ret;
-}
-
-asmlinkage ssize_t
-compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
-                  unsigned long vlen, u32 pos_low, u32 pos_high)
-{
-       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-       return compat_sys_pwritev64(fd, vec, vlen, pos);
-}
-
 asmlinkage long
 compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
                    unsigned int nr_segs, unsigned int flags)
index 3e1791a..e6dd1c2 100644 (file)
@@ -591,7 +591,7 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
 }
 EXPORT_SYMBOL(iov_shorten);
 
-ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
                unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
 {
        struct kiocb kiocb;
@@ -616,7 +616,7 @@ ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
 }
 
 /* Do it by hand, with file-ops */
-ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
+static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
                unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
 {
        struct iovec *vector = iov;
@@ -898,6 +898,199 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
        return ret;
 }
 
+#ifdef CONFIG_COMPAT
+
+static ssize_t compat_do_readv_writev(int type, struct file *file,
+                              const struct compat_iovec __user *uvector,
+                              unsigned long nr_segs, loff_t *pos)
+{
+       compat_ssize_t tot_len;
+       struct iovec iovstack[UIO_FASTIOV];
+       struct iovec *iov = iovstack;
+       ssize_t ret;
+       io_fn_t fn;
+       iov_fn_t fnv;
+
+       ret = -EINVAL;
+       if (!file->f_op)
+               goto out;
+
+       ret = -EFAULT;
+       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+               goto out;
+
+       ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
+                                              UIO_FASTIOV, iovstack, &iov);
+       if (ret <= 0)
+               goto out;
+
+       tot_len = ret;
+       ret = rw_verify_area(type, file, pos, tot_len);
+       if (ret < 0)
+               goto out;
+
+       fnv = NULL;
+       if (type == READ) {
+               fn = file->f_op->read;
+               fnv = file->f_op->aio_read;
+       } else {
+               fn = (io_fn_t)file->f_op->write;
+               fnv = file->f_op->aio_write;
+       }
+
+       if (fnv) {
+               file_start_write(file);
+               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
+                                               pos, fnv);
+               file_end_write(file);
+       } else
+               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
+
+out:
+       if (iov != iovstack)
+               kfree(iov);
+       if ((ret + (type == READ)) > 0) {
+               if (type == READ)
+                       fsnotify_access(file);
+               else
+                       fsnotify_modify(file);
+       }
+       return ret;
+}
+
+static size_t compat_readv(struct file *file,
+                          const struct compat_iovec __user *vec,
+                          unsigned long vlen, loff_t *pos)
+{
+       ssize_t ret = -EBADF;
+
+       if (!(file->f_mode & FMODE_READ))
+               goto out;
+
+       ret = -EINVAL;
+       if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
+               goto out;
+
+       ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
+
+out:
+       if (ret > 0)
+               add_rchar(current, ret);
+       inc_syscr(current);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen)
+{
+       struct fd f = fdget(fd);
+       ssize_t ret;
+       loff_t pos;
+
+       if (!f.file)
+               return -EBADF;
+       pos = f.file->f_pos;
+       ret = compat_readv(f.file, vec, vlen, &pos);
+       f.file->f_pos = pos;
+       fdput(f);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, loff_t, pos)
+{
+       struct fd f;
+       ssize_t ret;
+
+       if (pos < 0)
+               return -EINVAL;
+       f = fdget(fd);
+       if (!f.file)
+               return -EBADF;
+       ret = -ESPIPE;
+       if (f.file->f_mode & FMODE_PREAD)
+               ret = compat_readv(f.file, vec, vlen, &pos);
+       fdput(f);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE5(preadv, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, u32, pos_low, u32, pos_high)
+{
+       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+       return compat_sys_preadv64(fd, vec, vlen, pos);
+}
+
+static size_t compat_writev(struct file *file,
+                           const struct compat_iovec __user *vec,
+                           unsigned long vlen, loff_t *pos)
+{
+       ssize_t ret = -EBADF;
+
+       if (!(file->f_mode & FMODE_WRITE))
+               goto out;
+
+       ret = -EINVAL;
+       if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
+               goto out;
+
+       ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
+
+out:
+       if (ret > 0)
+               add_wchar(current, ret);
+       inc_syscw(current);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd,
+               const struct compat_iovec __user *, vec,
+               unsigned long, vlen)
+{
+       struct fd f = fdget(fd);
+       ssize_t ret;
+       loff_t pos;
+
+       if (!f.file)
+               return -EBADF;
+       pos = f.file->f_pos;
+       ret = compat_writev(f.file, vec, vlen, &pos);
+       f.file->f_pos = pos;
+       fdput(f);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, loff_t, pos)
+{
+       struct fd f;
+       ssize_t ret;
+
+       if (pos < 0)
+               return -EINVAL;
+       f = fdget(fd);
+       if (!f.file)
+               return -EBADF;
+       ret = -ESPIPE;
+       if (f.file->f_mode & FMODE_PWRITE)
+               ret = compat_writev(f.file, vec, vlen, &pos);
+       fdput(f);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE5(pwritev, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, u32, pos_low, u32, pos_high)
+{
+       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+       return compat_sys_pwritev64(fd, vec, vlen, pos);
+}
+#endif
+
 ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
                    loff_t max)
 {
index d3e00ef..b987806 100644 (file)
@@ -8,9 +8,5 @@ typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
                unsigned long, loff_t);
 
-ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
-               unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn);
-ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
-               unsigned long nr_segs, loff_t *ppos, io_fn_t fn);
 ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
                    loff_t max);