aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-04-02 15:46:35 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-02 15:46:35 -0400
commit29e350944fdc2dfca102500790d8ad6d6ff4f69d (patch)
tree7630809d75149b0053dcc45ad34e95d5506e88b3 /fs/splice.c
parentb45e516f701e0fc81fb3dbd1ba9db35f991a4465 (diff)
splice: add SPLICE_F_NONBLOCK flag
It doesn't make the splice itself necessarily nonblocking (because the actual file descriptors that are spliced from/to may block unless they have the O_NONBLOCK flag set), but it makes the splice pipe operations nonblocking. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 7c2bbf18d7a7..6081cf7d2d1b 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -106,7 +106,7 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = {
106 106
107static ssize_t move_to_pipe(struct inode *inode, struct page **pages, 107static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
108 int nr_pages, unsigned long offset, 108 int nr_pages, unsigned long offset,
109 unsigned long len) 109 unsigned long len, unsigned int flags)
110{ 110{
111 struct pipe_inode_info *info; 111 struct pipe_inode_info *info;
112 int ret, do_wakeup, i; 112 int ret, do_wakeup, i;
@@ -159,6 +159,12 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
159 break; 159 break;
160 } 160 }
161 161
162 if (flags & SPLICE_F_NONBLOCK) {
163 if (!ret)
164 ret = -EAGAIN;
165 break;
166 }
167
162 if (signal_pending(current)) { 168 if (signal_pending(current)) {
163 if (!ret) 169 if (!ret)
164 ret = -ERESTARTSYS; 170 ret = -ERESTARTSYS;
@@ -191,7 +197,7 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
191} 197}
192 198
193static int __generic_file_splice_read(struct file *in, struct inode *pipe, 199static int __generic_file_splice_read(struct file *in, struct inode *pipe,
194 size_t len) 200 size_t len, unsigned int flags)
195{ 201{
196 struct address_space *mapping = in->f_mapping; 202 struct address_space *mapping = in->f_mapping;
197 unsigned int offset, nr_pages; 203 unsigned int offset, nr_pages;
@@ -279,7 +285,7 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
279 * Now we splice them into the pipe.. 285 * Now we splice them into the pipe..
280 */ 286 */
281splice_them: 287splice_them:
282 return move_to_pipe(pipe, pages, i, offset, len); 288 return move_to_pipe(pipe, pages, i, offset, len, flags);
283} 289}
284 290
285ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, 291ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
@@ -291,7 +297,7 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
291 ret = 0; 297 ret = 0;
292 spliced = 0; 298 spliced = 0;
293 while (len) { 299 while (len) {
294 ret = __generic_file_splice_read(in, pipe, len); 300 ret = __generic_file_splice_read(in, pipe, len, flags);
295 301
296 if (ret <= 0) 302 if (ret <= 0)
297 break; 303 break;
@@ -299,6 +305,11 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
299 in->f_pos += ret; 305 in->f_pos += ret;
300 len -= ret; 306 len -= ret;
301 spliced += ret; 307 spliced += ret;
308
309 if (!(flags & SPLICE_F_NONBLOCK))
310 continue;
311 ret = -EAGAIN;
312 break;
302 } 313 }
303 314
304 if (spliced) 315 if (spliced)
@@ -527,6 +538,12 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out,
527 break; 538 break;
528 } 539 }
529 540
541 if (flags & SPLICE_F_NONBLOCK) {
542 if (!ret)
543 ret = -EAGAIN;
544 break;
545 }
546
530 if (signal_pending(current)) { 547 if (signal_pending(current)) {
531 if (!ret) 548 if (!ret)
532 ret = -ERESTARTSYS; 549 ret = -ERESTARTSYS;