aboutsummaryrefslogtreecommitdiffstats
path: root/fs/aio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-17 14:54:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-17 14:54:55 -0500
commit93f30c73ecd0281cf3685ef0e4e384980a176176 (patch)
treebd272334a0dbd258c08b5b2237e8bf5e17ce7255 /fs/aio.c
parent06ede5f6086757f746b7be860ae76137f4e95032 (diff)
parent96271654f55c74ff7325fbdfc535466c9deb0ce6 (diff)
Merge branch 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull compat and uaccess updates from Al Viro: - {get,put}_compat_sigset() series - assorted compat ioctl stuff - more set_fs() elimination - a few more timespec64 conversions - several removals of pointless access_ok() in places where it was followed only by non-__ variants of primitives * 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (24 commits) coredump: call do_unlinkat directly instead of sys_unlink fs: expose do_unlinkat for built-in callers ext4: take handling of EXT4_IOC_GROUP_ADD into a helper, get rid of set_fs() ipmi: get rid of pointless access_ok() pi433: sanitize ioctl cxlflash: get rid of pointless access_ok() mtdchar: get rid of pointless access_ok() r128: switch compat ioctls to drm_ioctl_kernel() selection: get rid of field-by-field copyin VT_RESIZEX: get rid of field-by-field copyin i2c compat ioctls: move to ->compat_ioctl() sched_rr_get_interval(): move compat to native, get rid of set_fs() mips: switch to {get,put}_compat_sigset() sparc: switch to {get,put}_compat_sigset() s390: switch to {get,put}_compat_sigset() ppc: switch to {get,put}_compat_sigset() parisc: switch to {get,put}_compat_sigset() get_compat_sigset() get rid of {get,put}_compat_itimerspec() io_getevents: Use timespec64 to represent timeouts ...
Diffstat (limited to 'fs/aio.c')
-rw-r--r--fs/aio.c55
1 files changed, 30 insertions, 25 deletions
diff --git a/fs/aio.c b/fs/aio.c
index e6de7715228c..a062d75109cb 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1297,20 +1297,10 @@ static bool aio_read_events(struct kioctx *ctx, long min_nr, long nr,
1297 1297
1298static long read_events(struct kioctx *ctx, long min_nr, long nr, 1298static long read_events(struct kioctx *ctx, long min_nr, long nr,
1299 struct io_event __user *event, 1299 struct io_event __user *event,
1300 struct timespec __user *timeout) 1300 ktime_t until)
1301{ 1301{
1302 ktime_t until = KTIME_MAX;
1303 long ret = 0; 1302 long ret = 0;
1304 1303
1305 if (timeout) {
1306 struct timespec ts;
1307
1308 if (unlikely(copy_from_user(&ts, timeout, sizeof(ts))))
1309 return -EFAULT;
1310
1311 until = timespec_to_ktime(ts);
1312 }
1313
1314 /* 1304 /*
1315 * Note that aio_read_events() is being called as the conditional - i.e. 1305 * Note that aio_read_events() is being called as the conditional - i.e.
1316 * we're calling it after prepare_to_wait() has set task state to 1306 * we're calling it after prepare_to_wait() has set task state to
@@ -1826,6 +1816,25 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
1826 return ret; 1816 return ret;
1827} 1817}
1828 1818
1819static long do_io_getevents(aio_context_t ctx_id,
1820 long min_nr,
1821 long nr,
1822 struct io_event __user *events,
1823 struct timespec64 *ts)
1824{
1825 ktime_t until = ts ? timespec64_to_ktime(*ts) : KTIME_MAX;
1826 struct kioctx *ioctx = lookup_ioctx(ctx_id);
1827 long ret = -EINVAL;
1828
1829 if (likely(ioctx)) {
1830 if (likely(min_nr <= nr && min_nr >= 0))
1831 ret = read_events(ioctx, min_nr, nr, events, until);
1832 percpu_ref_put(&ioctx->users);
1833 }
1834
1835 return ret;
1836}
1837
1829/* io_getevents: 1838/* io_getevents:
1830 * Attempts to read at least min_nr events and up to nr events from 1839 * Attempts to read at least min_nr events and up to nr events from
1831 * the completion queue for the aio_context specified by ctx_id. If 1840 * the completion queue for the aio_context specified by ctx_id. If
@@ -1844,15 +1853,14 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
1844 struct io_event __user *, events, 1853 struct io_event __user *, events,
1845 struct timespec __user *, timeout) 1854 struct timespec __user *, timeout)
1846{ 1855{
1847 struct kioctx *ioctx = lookup_ioctx(ctx_id); 1856 struct timespec64 ts;
1848 long ret = -EINVAL;
1849 1857
1850 if (likely(ioctx)) { 1858 if (timeout) {
1851 if (likely(min_nr <= nr && min_nr >= 0)) 1859 if (unlikely(get_timespec64(&ts, timeout)))
1852 ret = read_events(ioctx, min_nr, nr, events, timeout); 1860 return -EFAULT;
1853 percpu_ref_put(&ioctx->users);
1854 } 1861 }
1855 return ret; 1862
1863 return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
1856} 1864}
1857 1865
1858#ifdef CONFIG_COMPAT 1866#ifdef CONFIG_COMPAT
@@ -1862,17 +1870,14 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
1862 struct io_event __user *, events, 1870 struct io_event __user *, events,
1863 struct compat_timespec __user *, timeout) 1871 struct compat_timespec __user *, timeout)
1864{ 1872{
1865 struct timespec t; 1873 struct timespec64 t;
1866 struct timespec __user *ut = NULL;
1867 1874
1868 if (timeout) { 1875 if (timeout) {
1869 if (compat_get_timespec(&t, timeout)) 1876 if (compat_get_timespec64(&t, timeout))
1870 return -EFAULT; 1877 return -EFAULT;
1871 1878
1872 ut = compat_alloc_user_space(sizeof(*ut));
1873 if (copy_to_user(ut, &t, sizeof(t)))
1874 return -EFAULT;
1875 } 1879 }
1876 return sys_io_getevents(ctx_id, min_nr, nr, events, ut); 1880
1881 return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
1877} 1882}
1878#endif 1883#endif