diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-26 20:10:07 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-29 23:19:29 -0400 |
| commit | 67ba049f94ebe49ed557e590dd243b6db45c9aff (patch) | |
| tree | daae1d99acb30a148b9fe7546d7894cd397f1029 | |
| parent | 95af8496ac48263badf5b8dde5e06ef35aaace2b (diff) | |
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: | |||
| 1818 | return ret; | 1818 | return ret; |
| 1819 | } | 1819 | } |
| 1820 | 1820 | ||
| 1821 | static long do_io_submit(aio_context_t ctx_id, long nr, | 1821 | /* sys_io_submit: |
| 1822 | struct iocb __user *__user *iocbpp, bool compat) | 1822 | * Queue the nr iocbs pointed to by iocbpp for processing. Returns |
| 1823 | * the number of iocbs queued. May return -EINVAL if the aio_context | ||
| 1824 | * specified by ctx_id is invalid, if nr is < 0, if the iocb at | ||
| 1825 | * *iocbpp[0] is not properly initialized, if the operation specified | ||
| 1826 | * is invalid for the file descriptor in the iocb. May fail with | ||
| 1827 | * -EFAULT if any of the data structures point to invalid data. May | ||
| 1828 | * fail with -EBADF if the file descriptor specified in the first | ||
| 1829 | * iocb is invalid. May fail with -EAGAIN if insufficient resources | ||
| 1830 | * are available to queue any iocbs. Will return 0 if nr is 0. Will | ||
| 1831 | * fail with -ENOSYS if not implemented. | ||
| 1832 | */ | ||
| 1833 | SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, | ||
| 1834 | struct iocb __user * __user *, iocbpp) | ||
| 1823 | { | 1835 | { |
| 1824 | struct kioctx *ctx; | 1836 | struct kioctx *ctx; |
| 1825 | long ret = 0; | 1837 | long ret = 0; |
| @@ -1832,9 +1844,6 @@ static long do_io_submit(aio_context_t ctx_id, long nr, | |||
| 1832 | if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) | 1844 | if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) |
| 1833 | nr = LONG_MAX/sizeof(*iocbpp); | 1845 | nr = LONG_MAX/sizeof(*iocbpp); |
| 1834 | 1846 | ||
| 1835 | if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) | ||
| 1836 | return -EFAULT; | ||
| 1837 | |||
| 1838 | ctx = lookup_ioctx(ctx_id); | 1847 | ctx = lookup_ioctx(ctx_id); |
| 1839 | if (unlikely(!ctx)) { | 1848 | if (unlikely(!ctx)) { |
| 1840 | pr_debug("EINVAL: invalid context id\n"); | 1849 | pr_debug("EINVAL: invalid context id\n"); |
| @@ -1842,20 +1851,15 @@ static long do_io_submit(aio_context_t ctx_id, long nr, | |||
| 1842 | } | 1851 | } |
| 1843 | 1852 | ||
| 1844 | blk_start_plug(&plug); | 1853 | blk_start_plug(&plug); |
| 1845 | 1854 | for (i = 0; i < nr; i++) { | |
| 1846 | /* | ||
| 1847 | * AKPM: should this return a partial result if some of the IOs were | ||
| 1848 | * successfully submitted? | ||
| 1849 | */ | ||
| 1850 | for (i=0; i<nr; i++) { | ||
| 1851 | struct iocb __user *user_iocb; | 1855 | struct iocb __user *user_iocb; |
| 1852 | 1856 | ||
| 1853 | if (unlikely(__get_user(user_iocb, iocbpp + i))) { | 1857 | if (unlikely(get_user(user_iocb, iocbpp + i))) { |
| 1854 | ret = -EFAULT; | 1858 | ret = -EFAULT; |
| 1855 | break; | 1859 | break; |
| 1856 | } | 1860 | } |
| 1857 | 1861 | ||
| 1858 | ret = io_submit_one(ctx, user_iocb, compat); | 1862 | ret = io_submit_one(ctx, user_iocb, false); |
| 1859 | if (ret) | 1863 | if (ret) |
| 1860 | break; | 1864 | break; |
| 1861 | } | 1865 | } |
| @@ -1865,47 +1869,16 @@ static long do_io_submit(aio_context_t ctx_id, long nr, | |||
| 1865 | return i ? i : ret; | 1869 | return i ? i : ret; |
| 1866 | } | 1870 | } |
| 1867 | 1871 | ||
| 1868 | /* sys_io_submit: | ||
| 1869 | * Queue the nr iocbs pointed to by iocbpp for processing. Returns | ||
| 1870 | * the number of iocbs queued. May return -EINVAL if the aio_context | ||
| 1871 | * specified by ctx_id is invalid, if nr is < 0, if the iocb at | ||
| 1872 | * *iocbpp[0] is not properly initialized, if the operation specified | ||
| 1873 | * is invalid for the file descriptor in the iocb. May fail with | ||
| 1874 | * -EFAULT if any of the data structures point to invalid data. May | ||
| 1875 | * fail with -EBADF if the file descriptor specified in the first | ||
| 1876 | * iocb is invalid. May fail with -EAGAIN if insufficient resources | ||
| 1877 | * are available to queue any iocbs. Will return 0 if nr is 0. Will | ||
| 1878 | * fail with -ENOSYS if not implemented. | ||
| 1879 | */ | ||
| 1880 | SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, | ||
| 1881 | struct iocb __user * __user *, iocbpp) | ||
| 1882 | { | ||
| 1883 | return do_io_submit(ctx_id, nr, iocbpp, 0); | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | #ifdef CONFIG_COMPAT | 1872 | #ifdef CONFIG_COMPAT |
| 1887 | static inline long | ||
| 1888 | copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64) | ||
| 1889 | { | ||
| 1890 | compat_uptr_t uptr; | ||
| 1891 | int i; | ||
| 1892 | |||
| 1893 | for (i = 0; i < nr; ++i) { | ||
| 1894 | if (get_user(uptr, ptr32 + i)) | ||
| 1895 | return -EFAULT; | ||
| 1896 | if (put_user(compat_ptr(uptr), ptr64 + i)) | ||
| 1897 | return -EFAULT; | ||
| 1898 | } | ||
| 1899 | return 0; | ||
| 1900 | } | ||
| 1901 | |||
| 1902 | #define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) | 1873 | #define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) |
| 1903 | 1874 | ||
| 1904 | COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, | 1875 | COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, |
| 1905 | int, nr, u32 __user *, iocb) | 1876 | int, nr, compat_uptr_t __user *, iocbpp) |
| 1906 | { | 1877 | { |
| 1907 | struct iocb __user * __user *iocb64; | 1878 | struct kioctx *ctx; |
| 1908 | long ret; | 1879 | long ret = 0; |
| 1880 | int i = 0; | ||
| 1881 | struct blk_plug plug; | ||
| 1909 | 1882 | ||
| 1910 | if (unlikely(nr < 0)) | 1883 | if (unlikely(nr < 0)) |
| 1911 | return -EINVAL; | 1884 | return -EINVAL; |
| @@ -1913,11 +1886,29 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, | |||
| 1913 | if (nr > MAX_AIO_SUBMITS) | 1886 | if (nr > MAX_AIO_SUBMITS) |
| 1914 | nr = MAX_AIO_SUBMITS; | 1887 | nr = MAX_AIO_SUBMITS; |
| 1915 | 1888 | ||
| 1916 | iocb64 = compat_alloc_user_space(nr * sizeof(*iocb64)); | 1889 | ctx = lookup_ioctx(ctx_id); |
| 1917 | ret = copy_iocb(nr, iocb, iocb64); | 1890 | if (unlikely(!ctx)) { |
| 1918 | if (!ret) | 1891 | pr_debug("EINVAL: invalid context id\n"); |
| 1919 | ret = do_io_submit(ctx_id, nr, iocb64, 1); | 1892 | return -EINVAL; |
| 1920 | return ret; | 1893 | } |
| 1894 | |||
| 1895 | blk_start_plug(&plug); | ||
| 1896 | for (i = 0; i < nr; i++) { | ||
| 1897 | compat_uptr_t user_iocb; | ||
| 1898 | |||
| 1899 | if (unlikely(get_user(user_iocb, iocbpp + i))) { | ||
| 1900 | ret = -EFAULT; | ||
| 1901 | break; | ||
| 1902 | } | ||
| 1903 | |||
| 1904 | ret = io_submit_one(ctx, compat_ptr(user_iocb), true); | ||
| 1905 | if (ret) | ||
| 1906 | break; | ||
| 1907 | } | ||
| 1908 | blk_finish_plug(&plug); | ||
| 1909 | |||
| 1910 | percpu_ref_put(&ctx->users); | ||
| 1911 | return i ? i : ret; | ||
| 1921 | } | 1912 | } |
| 1922 | #endif | 1913 | #endif |
| 1923 | 1914 | ||
