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 /fs/aio.c | |
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>
Diffstat (limited to 'fs/aio.c')
-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 | ||