diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-27 03:10:07 +0300 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-30 06:19:29 +0300 |
commit | 67ba049f94ebe49ed557e590dd243b6db45c9aff (patch) | |
tree | daae1d99acb30a148b9fe7546d7894cd397f1029 | |
parent | 95af8496ac48263badf5b8dde5e06ef35aaace2b (diff) | |
download | linux-67ba049f94ebe49ed557e590dd243b6db45c9aff.tar.xz |
aio: fold do_io_submit() into callers
get rid of insane "copy array of 32bit pointers into an array of
native ones" glue.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/aio.c | 99 |
1 files changed, 45 insertions, 54 deletions
@@ -1818,8 +1818,20 @@ out_put_req: return ret; } -static long do_io_submit(aio_context_t ctx_id, long nr, - struct iocb __user *__user *iocbpp, bool compat) +/* sys_io_submit: + * Queue the nr iocbs pointed to by iocbpp for processing. Returns + * the number of iocbs queued. May return -EINVAL if the aio_context + * specified by ctx_id is invalid, if nr is < 0, if the iocb at + * *iocbpp[0] is not properly initialized, if the operation specified + * is invalid for the file descriptor in the iocb. May fail with + * -EFAULT if any of the data structures point to invalid data. May + * fail with -EBADF if the file descriptor specified in the first + * iocb is invalid. May fail with -EAGAIN if insufficient resources + * are available to queue any iocbs. Will return 0 if nr is 0. Will + * fail with -ENOSYS if not implemented. + */ +SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, + struct iocb __user * __user *, iocbpp) { struct kioctx *ctx; long ret = 0; @@ -1832,9 +1844,6 @@ static long do_io_submit(aio_context_t ctx_id, long nr, if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) nr = LONG_MAX/sizeof(*iocbpp); - if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) - return -EFAULT; - ctx = lookup_ioctx(ctx_id); if (unlikely(!ctx)) { pr_debug("EINVAL: invalid context id\n"); @@ -1842,20 +1851,15 @@ static long do_io_submit(aio_context_t ctx_id, long nr, } blk_start_plug(&plug); - - /* - * AKPM: should this return a partial result if some of the IOs were - * successfully submitted? - */ - for (i=0; i<nr; i++) { + for (i = 0; i < nr; i++) { struct iocb __user *user_iocb; - if (unlikely(__get_user(user_iocb, iocbpp + i))) { + if (unlikely(get_user(user_iocb, iocbpp + i))) { ret = -EFAULT; break; } - ret = io_submit_one(ctx, user_iocb, compat); + ret = io_submit_one(ctx, user_iocb, false); if (ret) break; } @@ -1865,47 +1869,16 @@ static long do_io_submit(aio_context_t ctx_id, long nr, return i ? i : ret; } -/* sys_io_submit: - * Queue the nr iocbs pointed to by iocbpp for processing. Returns - * the number of iocbs queued. May return -EINVAL if the aio_context - * specified by ctx_id is invalid, if nr is < 0, if the iocb at - * *iocbpp[0] is not properly initialized, if the operation specified - * is invalid for the file descriptor in the iocb. May fail with - * -EFAULT if any of the data structures point to invalid data. May - * fail with -EBADF if the file descriptor specified in the first - * iocb is invalid. May fail with -EAGAIN if insufficient resources - * are available to queue any iocbs. Will return 0 if nr is 0. Will - * fail with -ENOSYS if not implemented. - */ -SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, - struct iocb __user * __user *, iocbpp) -{ - return do_io_submit(ctx_id, nr, iocbpp, 0); -} - #ifdef CONFIG_COMPAT -static inline long -copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64) -{ - compat_uptr_t uptr; - int i; - - for (i = 0; i < nr; ++i) { - if (get_user(uptr, ptr32 + i)) - return -EFAULT; - if (put_user(compat_ptr(uptr), ptr64 + i)) - return -EFAULT; - } - return 0; -} - #define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, - int, nr, u32 __user *, iocb) + int, nr, compat_uptr_t __user *, iocbpp) { - struct iocb __user * __user *iocb64; - long ret; + struct kioctx *ctx; + long ret = 0; + int i = 0; + struct blk_plug plug; if (unlikely(nr < 0)) return -EINVAL; @@ -1913,11 +1886,29 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, if (nr > MAX_AIO_SUBMITS) nr = MAX_AIO_SUBMITS; - iocb64 = compat_alloc_user_space(nr * sizeof(*iocb64)); - ret = copy_iocb(nr, iocb, iocb64); - if (!ret) - ret = do_io_submit(ctx_id, nr, iocb64, 1); - return ret; + ctx = lookup_ioctx(ctx_id); + if (unlikely(!ctx)) { + pr_debug("EINVAL: invalid context id\n"); + return -EINVAL; + } + + blk_start_plug(&plug); + for (i = 0; i < nr; i++) { + compat_uptr_t user_iocb; + + if (unlikely(get_user(user_iocb, iocbpp + i))) { + ret = -EFAULT; + break; + } + + ret = io_submit_one(ctx, compat_ptr(user_iocb), true); + if (ret) + break; + } + blk_finish_plug(&plug); + + percpu_ref_put(&ctx->users); + return i ? i : ret; } #endif |