diff options
| -rw-r--r-- | fs/splice.c | 25 | ||||
| -rw-r--r-- | include/linux/pipe_fs_i.h | 3 |
2 files changed, 24 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 | ||
| 107 | static ssize_t move_to_pipe(struct inode *inode, struct page **pages, | 107 | static 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 | ||
| 193 | static int __generic_file_splice_read(struct file *in, struct inode *pipe, | 199 | static 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 | */ |
| 281 | splice_them: | 287 | splice_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 | ||
| 285 | ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, | 291 | ssize_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; |
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 75c7f55023ab..d218fc729319 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h | |||
| @@ -60,5 +60,8 @@ void free_pipe_info(struct inode* inode); | |||
| 60 | * add the splice flags here. | 60 | * add the splice flags here. |
| 61 | */ | 61 | */ |
| 62 | #define SPLICE_F_MOVE (0x01) /* move pages instead of copying */ | 62 | #define SPLICE_F_MOVE (0x01) /* move pages instead of copying */ |
| 63 | #define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */ | ||
| 64 | /* we may still block on the fd we splice */ | ||
| 65 | /* from/to, of course */ | ||
| 63 | 66 | ||
| 64 | #endif | 67 | #endif |
