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
396396 382 i386 pkey_free sys_pkey_free __ia32_sys_pkey_free
397397 383 i386 statx sys_statx __ia32_sys_statx
398398 384 i386 arch_prctl sys_arch_prctl __ia32_compat_sys_arch_prctl
399+385 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
341341 330 common pkey_alloc __x64_sys_pkey_alloc
342342 331 common pkey_free __x64_sys_pkey_free
343343 332 common statx __x64_sys_statx
344+333 common io_pgetevents __x64_sys_io_pgetevents
344345
345346 #
346347 # 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
13031303 wait_event_interruptible_hrtimeout(ctx->wait,
13041304 aio_read_events(ctx, min_nr, nr, event, &ret),
13051305 until);
1306−
1307− if (!ret && signal_pending(current))
1308− ret = -EINTR;
1309−
13101306 return ret;
13111307 }
13121308
@@ -1921,13 +1917,60 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id, · 608 unmodified lines
19211917 struct timespec __user *, timeout)
19221918 {
19231919 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+}
19241930
1925− if (timeout) {
1926− if (unlikely(get_timespec64(&ts, timeout)))
1931+SYSCALL_DEFINE6(io_pgetevents,
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)))
19271954 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);
19281971 }
19291972
1930− return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
1973+ return ret;
19311974 }
19321975
19331976 #ifdef CONFIG_COMPAT
@@ -1938,13 +1981,64 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id, · 4 unmodified lines
19381981 struct compat_timespec __user *, timeout)
19391982 {
19401983 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+
19411995
1942− if (timeout) {
1943− if (compat_get_timespec64(&t, timeout))
1996+struct __compat_aio_sigset {
1997+ compat_sigset_t __user *sigmask;
1998+ compat_size_t sigsetsize;
1999+};
2000+
2001+COMPAT_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))
19442024 return -EFAULT;
2025+ sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
2026+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
2027+ }
19452028
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);
19462040 }
19472041
1948− return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
2042+ return ret;
19492043 }
19502044 #endif
include/linux/compat.h+7−0
@@ -330,6 +330,7 @@ extern int put_compat_rusage(const struct rusage *, · 329 unmodified lines
330330 struct compat_rusage __user *);
331331
332332 struct compat_siginfo;
333+struct __compat_aio_sigset;
333334
334335 struct compat_dirent {
335336 u32 d_ino;
@@ -553,6 +554,12 @@ asmlinkage long compat_sys_io_getevents(compat_aio_context_t ctx_id, · 217 unmodified lines
553554 compat_long_t nr,
554555 struct io_event __user *events,
555556 struct compat_timespec __user *timeout);
557+asmlinkage 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);
556563
557564 /* fs/cookies.c */
558565 asmlinkage 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
290290 long nr,
291291 struct io_event __user *events,
292292 struct timespec __user *timeout);
293+asmlinkage 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);
293299
294300 /* fs/xattr.c */
295301 asmlinkage 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
732732 __SYSCALL(__NR_pkey_free, sys_pkey_free)
733733 #define __NR_statx 291
734734 __SYSCALL(__NR_statx, sys_statx)
735+#define __NR_io_pgetevents 292
736+__SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents)
735737
736738 #undef __NR_syscalls
737−#define __NR_syscalls 292
739+#define __NR_syscalls 293
738740
739741 /*
740742 * 32 bit systems traditionally used different
include/uapi/linux/aio_abi.h+6−0
@@ -29,6 +29,7 @@ · 28 unmodified lines
2929
3030 #include <linux/types.h>
3131 #include <linux/fs.h>
32+#include <linux/signal.h>
3233 #include <asm/byteorder.h>
3334
3435 typedef __kernel_ulong_t aio_context_t;
@@ -108,5 +109,10 @@ struct iocb { · 73 unmodified lines
108109 #undef IFBIG
109110 #undef IFLITTLE
110111
112+struct __aio_sigset {
113+ sigset_t __user *sigmask;
114+ size_t sigsetsize;
115+};
116+
111117 #endif /* __LINUX__AIO_ABI_H */
112118
kernel/sys_ni.c+2−0
@@ -43,7 +43,9 @@ COND_SYSCALL(io_submit); · 42 unmodified lines
4343 COND_SYSCALL_COMPAT(io_submit);
4444 COND_SYSCALL(io_cancel);
4545 COND_SYSCALL(io_getevents);
46+COND_SYSCALL(io_pgetevents);
4647 COND_SYSCALL_COMPAT(io_getevents);
48+COND_SYSCALL_COMPAT(io_pgetevents);
4749
4850 /* fs/xattr.c */
4951