History

aio: implement io_pgetevents

This is the io_getevents equivalent of ppoll/pselect and allows to properly mix signals and aio completions (especially with IOCB_CMD_POLL) and atomically executes the following sequence: sigset_t origmask; pthread_sigmask(SIG_SETMASK, &sigmask, &origmask); ret = io_getevents(ctx, min_nr, nr, events, timeout); pthread_sigmask(SIG_SETMASK, &origmask, NULL); Note that unlike many other signal related calls we do not pass a sigmask size, as that would get us to 7 arguments, which aren't easily supported by the syscall infrastructure. It seems a lot less painful to just add a new syscall variant in the unlikely case we're going to increase the sigset size.

Christoph Hellwig committed 8 years ago

Commit 7a074e91 parent a3c0d438 files · +130 −11Browse files

Unified · Split

8 files
  1. arch/x86/entry/syscalls/syscall_32.tbl +1 −0
  2. arch/x86/entry/syscalls/syscall_64.tbl +1 −0
  3. fs/aio.c +104 −10
  4. include/linux/compat.h +7 −0
  5. include/linux/syscalls.h +6 −0
  6. include/uapi/asm-generic/unistd.h +3 −1
  7. include/uapi/linux/aio_abi.h +6 −0
  8. kernel/sys_ni.c +2 −0
arch/x86/entry/syscalls/syscall_32.tbl+1−0
@@ -396,3 +396,4 @@ · 395 unmodified lines
396382 i386 pkey_free sys_pkey_free __ia32_sys_pkey_free396382 i386 pkey_free sys_pkey_free __ia32_sys_pkey_free
397383 i386 statx sys_statx __ia32_sys_statx397383 i386 statx sys_statx __ia32_sys_statx
398384 i386 arch_prctl sys_arch_prctl __ia32_compat_sys_arch_prctl398384 i386 arch_prctl sys_arch_prctl __ia32_compat_sys_arch_prctl
399385 i386 io_pgetevents sys_io_pgetevents __ia32_compat_sys_io_pgetevents
arch/x86/entry/syscalls/syscall_64.tbl+1−0
@@ -341,6 +341,7 @@ · 340 unmodified lines
341330 common pkey_alloc __x64_sys_pkey_alloc341330 common pkey_alloc __x64_sys_pkey_alloc
342331 common pkey_free __x64_sys_pkey_free342331 common pkey_free __x64_sys_pkey_free
343332 common statx __x64_sys_statx343332 common statx __x64_sys_statx
344333 common io_pgetevents __x64_sys_io_pgetevents
344 345
345#346#
346# x32-specific system call numbers start at 512 to avoid cache impact347# x32-specific system call numbers start at 512 to avoid cache impact
fs/aio.c+104−10
@@ -1303,10 +1303,6 @@ static long read_events(struct kioctx *ctx, long min_nr, long nr, · 1302 unmodified lines
1303 wait_event_interruptible_hrtimeout(ctx->wait,1303 wait_event_interruptible_hrtimeout(ctx->wait,
1304 aio_read_events(ctx, min_nr, nr, event, &ret),1304 aio_read_events(ctx, min_nr, nr, event, &ret),
1305 until);1305 until);
1306
1307 if (!ret && signal_pending(current))
1308 ret = -EINTR;
1309
1310 return ret;1306 return ret;
1311}1307}
1312 1308
@@ -1921,13 +1917,60 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id, · 608 unmodified lines
1921 struct timespec __user *, timeout)1917 struct timespec __user *, timeout)
1922{1918{
1923 struct timespec64 ts;1919 struct timespec64 ts;
1920 int ret;
1921
1922 if (timeout && unlikely(get_timespec64(&ts, timeout)))
1923 return -EFAULT;
1924
1925 ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
1926 if (!ret && signal_pending(current))
1927 ret = -EINTR;
1928 return ret;
1929}
1924 1930
1925 if (timeout) {1931SYSCALL_DEFINE6(io_pgetevents,
1926 if (unlikely(get_timespec64(&ts, timeout)))1932 aio_context_t, ctx_id,
1933 long, min_nr,
1934 long, nr,
1935 struct io_event __user *, events,
1936 struct timespec __user *, timeout,
1937 const struct __aio_sigset __user *, usig)
1938{
1939 struct __aio_sigset ksig = { NULL, };
1940 sigset_t ksigmask, sigsaved;
1941 struct timespec64 ts;
1942 int ret;
1943
1944 if (timeout && unlikely(get_timespec64(&ts, timeout)))
1945 return -EFAULT;
1946
1947 if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
1948 return -EFAULT;
1949
1950 if (ksig.sigmask) {
1951 if (ksig.sigsetsize != sizeof(sigset_t))
1952 return -EINVAL;
1953 if (copy_from_user(&ksigmask, ksig.sigmask, sizeof(ksigmask)))
1927 return -EFAULT;1954 return -EFAULT;
1955 sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
1956 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1957 }
1958
1959 ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
1960 if (signal_pending(current)) {
1961 if (ksig.sigmask) {
1962 current->saved_sigmask = sigsaved;
1963 set_restore_sigmask();
1964 }
1965
1966 if (!ret)
1967 ret = -ERESTARTNOHAND;
1968 } else {
1969 if (ksig.sigmask)
1970 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1928 }1971 }
1929 1972
1930 return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);1973 return ret;
1931}1974}
1932 1975
1933#ifdef CONFIG_COMPAT1976#ifdef CONFIG_COMPAT
@@ -1938,13 +1981,64 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id, · 4 unmodified lines
1938 struct compat_timespec __user *, timeout)1981 struct compat_timespec __user *, timeout)
1939{1982{
1940 struct timespec64 t;1983 struct timespec64 t;
1984 int ret;
1985
1986 if (timeout && compat_get_timespec64(&t, timeout))
1987 return -EFAULT;
1988
1989 ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
1990 if (!ret && signal_pending(current))
1991 ret = -EINTR;
1992 return ret;
1993}
1994
1941 1995
1942 if (timeout) {1996struct __compat_aio_sigset {
1943 if (compat_get_timespec64(&t, timeout))1997 compat_sigset_t __user *sigmask;
1998 compat_size_t sigsetsize;
1999};
2000
2001COMPAT_SYSCALL_DEFINE6(io_pgetevents,
2002 compat_aio_context_t, ctx_id,
2003 compat_long_t, min_nr,
2004 compat_long_t, nr,
2005 struct io_event __user *, events,
2006 struct compat_timespec __user *, timeout,
2007 const struct __compat_aio_sigset __user *, usig)
2008{
2009 struct __compat_aio_sigset ksig = { NULL, };
2010 sigset_t ksigmask, sigsaved;
2011 struct timespec64 t;
2012 int ret;
2013
2014 if (timeout && compat_get_timespec64(&t, timeout))
2015 return -EFAULT;
2016
2017 if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
2018 return -EFAULT;
2019
2020 if (ksig.sigmask) {
2021 if (ksig.sigsetsize != sizeof(compat_sigset_t))
2022 return -EINVAL;
2023 if (get_compat_sigset(&ksigmask, ksig.sigmask))
1944 return -EFAULT;2024 return -EFAULT;
2025 sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
2026 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
2027 }
1945 2028
2029 ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
2030 if (signal_pending(current)) {
2031 if (ksig.sigmask) {
2032 current->saved_sigmask = sigsaved;
2033 set_restore_sigmask();
2034 }
2035 if (!ret)
2036 ret = -ERESTARTNOHAND;
2037 } else {
2038 if (ksig.sigmask)
2039 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1946 }2040 }
1947 2041
1948 return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);2042 return ret;
1949}2043}
1950#endif2044#endif
include/linux/compat.h+7−0
@@ -330,6 +330,7 @@ extern int put_compat_rusage(const struct rusage *, · 329 unmodified lines
330 struct compat_rusage __user *);330 struct compat_rusage __user *);
331 331
332struct compat_siginfo;332struct compat_siginfo;
333struct __compat_aio_sigset;
333 334
334struct compat_dirent {335struct compat_dirent {
335 u32 d_ino;336 u32 d_ino;
@@ -553,6 +554,12 @@ asmlinkage long compat_sys_io_getevents(compat_aio_context_t ctx_id, · 217 unmodified lines
553 compat_long_t nr,554 compat_long_t nr,
554 struct io_event __user *events,555 struct io_event __user *events,
555 struct compat_timespec __user *timeout);556 struct compat_timespec __user *timeout);
557asmlinkage long compat_sys_io_pgetevents(compat_aio_context_t ctx_id,
558 compat_long_t min_nr,
559 compat_long_t nr,
560 struct io_event __user *events,
561 struct compat_timespec __user *timeout,
562 const struct __compat_aio_sigset __user *usig);
556 563
557/* fs/cookies.c */564/* fs/cookies.c */
558asmlinkage long compat_sys_lookup_dcookie(u32, u32, char __user *, compat_size_t);565asmlinkage long compat_sys_lookup_dcookie(u32, u32, char __user *, compat_size_t);
include/linux/syscalls.h+6−0
@@ -290,6 +290,12 @@ asmlinkage long sys_io_getevents(aio_context_t ctx_id, · 289 unmodified lines
290 long nr,290 long nr,
291 struct io_event __user *events,291 struct io_event __user *events,
292 struct timespec __user *timeout);292 struct timespec __user *timeout);
293asmlinkage long sys_io_pgetevents(aio_context_t ctx_id,
294 long min_nr,
295 long nr,
296 struct io_event __user *events,
297 struct timespec __user *timeout,
298 const struct __aio_sigset *sig);
293 299
294/* fs/xattr.c */300/* fs/xattr.c */
295asmlinkage long sys_setxattr(const char __user *path, const char __user *name,301asmlinkage long sys_setxattr(const char __user *path, const char __user *name,
include/uapi/asm-generic/unistd.h+3−1
@@ -732,9 +732,11 @@ __SYSCALL(__NR_pkey_alloc, sys_pkey_alloc) · 731 unmodified lines
732__SYSCALL(__NR_pkey_free, sys_pkey_free)732__SYSCALL(__NR_pkey_free, sys_pkey_free)
733#define __NR_statx 291733#define __NR_statx 291
734__SYSCALL(__NR_statx, sys_statx)734__SYSCALL(__NR_statx, sys_statx)
735#define __NR_io_pgetevents 292
736__SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents)
735 737
736#undef __NR_syscalls738#undef __NR_syscalls
737#define __NR_syscalls 292739#define __NR_syscalls 293
738 740
739/*741/*
740 * 32 bit systems traditionally used different742 * 32 bit systems traditionally used different
include/uapi/linux/aio_abi.h+6−0
@@ -29,6 +29,7 @@ · 28 unmodified lines
29 29
30#include <linux/types.h>30#include <linux/types.h>
31#include <linux/fs.h>31#include <linux/fs.h>
32#include <linux/signal.h>
32#include <asm/byteorder.h>33#include <asm/byteorder.h>
33 34
34typedef __kernel_ulong_t aio_context_t;35typedef __kernel_ulong_t aio_context_t;
@@ -108,5 +109,10 @@ struct iocb { · 73 unmodified lines
108#undef IFBIG109#undef IFBIG
109#undef IFLITTLE110#undef IFLITTLE
110 111
112struct __aio_sigset {
113 sigset_t __user *sigmask;
114 size_t sigsetsize;
115};
116
111#endif /* __LINUX__AIO_ABI_H */117#endif /* __LINUX__AIO_ABI_H */
112 118
kernel/sys_ni.c+2−0
@@ -43,7 +43,9 @@ COND_SYSCALL(io_submit); · 42 unmodified lines
43COND_SYSCALL_COMPAT(io_submit);43COND_SYSCALL_COMPAT(io_submit);
44COND_SYSCALL(io_cancel);44COND_SYSCALL(io_cancel);
45COND_SYSCALL(io_getevents);45COND_SYSCALL(io_getevents);
46COND_SYSCALL(io_pgetevents);
46COND_SYSCALL_COMPAT(io_getevents);47COND_SYSCALL_COMPAT(io_getevents);
48COND_SYSCALL_COMPAT(io_pgetevents);
47 49
48/* fs/xattr.c */50/* fs/xattr.c */
49 51