diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-21 13:59:34 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-06 04:40:12 -0500 |
commit | b6cce9b8e8139e8b9130dd2efe950bac0d4fea50 (patch) | |
tree | 4695de59132398d90c1378636e1cd3cbdc261dc4 /fs | |
parent | c1df5a63716b0f73e95b1b26d878691e6175ea34 (diff) |
splice: reinstate SIGPIPE/EPIPE handling
commit 52bce91165e5f2db422b2b972e83d389e5e4725c upstream.
Commit 8924feff66f3 ("splice: lift pipe_lock out of splice_to_pipe()")
caused a regression when there were no more readers left on a pipe that
was being spliced into: rather than the expected SIGPIPE and -EPIPE
return value, the writer would end up waiting forever for space to free
up (which obviously was not going to happen with no readers around).
Fixes: 8924feff66f3 ("splice: lift pipe_lock out of splice_to_pipe()")
Reported-and-tested-by: Andreas Schwab <schwab@linux-m68k.org>
Debugged-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/splice.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/splice.c b/fs/splice.c index 5a7750bd2eea..63b8f54485dc 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -1086,7 +1086,13 @@ EXPORT_SYMBOL(do_splice_direct); | |||
1086 | 1086 | ||
1087 | static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags) | 1087 | static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags) |
1088 | { | 1088 | { |
1089 | while (pipe->nrbufs == pipe->buffers) { | 1089 | for (;;) { |
1090 | if (unlikely(!pipe->readers)) { | ||
1091 | send_sig(SIGPIPE, current, 0); | ||
1092 | return -EPIPE; | ||
1093 | } | ||
1094 | if (pipe->nrbufs != pipe->buffers) | ||
1095 | return 0; | ||
1090 | if (flags & SPLICE_F_NONBLOCK) | 1096 | if (flags & SPLICE_F_NONBLOCK) |
1091 | return -EAGAIN; | 1097 | return -EAGAIN; |
1092 | if (signal_pending(current)) | 1098 | if (signal_pending(current)) |
@@ -1095,7 +1101,6 @@ static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags) | |||
1095 | pipe_wait(pipe); | 1101 | pipe_wait(pipe); |
1096 | pipe->waiting_writers--; | 1102 | pipe->waiting_writers--; |
1097 | } | 1103 | } |
1098 | return 0; | ||
1099 | } | 1104 | } |
1100 | 1105 | ||
1101 | static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, | 1106 | static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, |