aboutsummaryrefslogtreecommitdiffstats
path: root/fs/aio.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-05-02 13:51:00 -0400
committerChristoph Hellwig <hch@lst.de>2018-05-02 13:57:24 -0400
commit7a074e96dee62586c935c80cecd931431bfdd0be (patch)
treea1a29dad896070e82827d7447cfcc9a064e5a63d /fs/aio.c
parenta3c0d439e4d92411c2b4b21a526a4de720d0806b (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.c114
1 files changed, 104 insertions, 10 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 61d2e6942951..f3eae5d5771b 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -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) { 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_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) { 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#endif 2044#endif