diff options
author | Christoph Hellwig <hch@lst.de> | 2018-05-02 13:51:00 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2018-05-02 13:57:24 -0400 |
commit | 7a074e96dee62586c935c80cecd931431bfdd0be (patch) | |
tree | a1a29dad896070e82827d7447cfcc9a064e5a63d /fs/aio.c | |
parent | a3c0d439e4d92411c2b4b21a526a4de720d0806b (diff) |
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.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 114 |
1 files changed, 104 insertions, 10 deletions
@@ -1303,10 +1303,6 @@ static long read_events(struct kioctx *ctx, long min_nr, long nr, | |||
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, | |||
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) { | 1931 | SYSCALL_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_COMPAT | 1976 | #ifdef CONFIG_COMPAT |
@@ -1938,13 +1981,64 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id, | |||
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) { | 1996 | struct __compat_aio_sigset { |
1943 | if (compat_get_timespec64(&t, timeout)) | 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)) | ||
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 | #endif | 2044 | #endif |