diff options
| -rw-r--r-- | fs/pipe.c | 31 | ||||
| -rw-r--r-- | include/linux/pipe_fs_i.h | 1 |
2 files changed, 30 insertions, 2 deletions
| @@ -346,6 +346,16 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { | |||
| 346 | .get = generic_pipe_buf_get, | 346 | .get = generic_pipe_buf_get, |
| 347 | }; | 347 | }; |
| 348 | 348 | ||
| 349 | static const struct pipe_buf_operations packet_pipe_buf_ops = { | ||
| 350 | .can_merge = 0, | ||
| 351 | .map = generic_pipe_buf_map, | ||
| 352 | .unmap = generic_pipe_buf_unmap, | ||
| 353 | .confirm = generic_pipe_buf_confirm, | ||
| 354 | .release = anon_pipe_buf_release, | ||
| 355 | .steal = generic_pipe_buf_steal, | ||
| 356 | .get = generic_pipe_buf_get, | ||
| 357 | }; | ||
| 358 | |||
| 349 | static ssize_t | 359 | static ssize_t |
| 350 | pipe_read(struct kiocb *iocb, const struct iovec *_iov, | 360 | pipe_read(struct kiocb *iocb, const struct iovec *_iov, |
| 351 | unsigned long nr_segs, loff_t pos) | 361 | unsigned long nr_segs, loff_t pos) |
| @@ -407,6 +417,13 @@ redo: | |||
| 407 | ret += chars; | 417 | ret += chars; |
| 408 | buf->offset += chars; | 418 | buf->offset += chars; |
| 409 | buf->len -= chars; | 419 | buf->len -= chars; |
| 420 | |||
| 421 | /* Was it a packet buffer? Clean up and exit */ | ||
| 422 | if (buf->flags & PIPE_BUF_FLAG_PACKET) { | ||
| 423 | total_len = chars; | ||
| 424 | buf->len = 0; | ||
| 425 | } | ||
| 426 | |||
| 410 | if (!buf->len) { | 427 | if (!buf->len) { |
| 411 | buf->ops = NULL; | 428 | buf->ops = NULL; |
| 412 | ops->release(pipe, buf); | 429 | ops->release(pipe, buf); |
| @@ -459,6 +476,11 @@ redo: | |||
| 459 | return ret; | 476 | return ret; |
| 460 | } | 477 | } |
| 461 | 478 | ||
| 479 | static inline int is_packetized(struct file *file) | ||
| 480 | { | ||
| 481 | return (file->f_flags & O_DIRECT) != 0; | ||
| 482 | } | ||
| 483 | |||
| 462 | static ssize_t | 484 | static ssize_t |
| 463 | pipe_write(struct kiocb *iocb, const struct iovec *_iov, | 485 | pipe_write(struct kiocb *iocb, const struct iovec *_iov, |
| 464 | unsigned long nr_segs, loff_t ppos) | 486 | unsigned long nr_segs, loff_t ppos) |
| @@ -593,6 +615,11 @@ redo2: | |||
| 593 | buf->ops = &anon_pipe_buf_ops; | 615 | buf->ops = &anon_pipe_buf_ops; |
| 594 | buf->offset = 0; | 616 | buf->offset = 0; |
| 595 | buf->len = chars; | 617 | buf->len = chars; |
| 618 | buf->flags = 0; | ||
| 619 | if (is_packetized(filp)) { | ||
| 620 | buf->ops = &packet_pipe_buf_ops; | ||
| 621 | buf->flags = PIPE_BUF_FLAG_PACKET; | ||
| 622 | } | ||
| 596 | pipe->nrbufs = ++bufs; | 623 | pipe->nrbufs = ++bufs; |
| 597 | pipe->tmp_page = NULL; | 624 | pipe->tmp_page = NULL; |
| 598 | 625 | ||
| @@ -1013,7 +1040,7 @@ struct file *create_write_pipe(int flags) | |||
| 1013 | goto err_dentry; | 1040 | goto err_dentry; |
| 1014 | f->f_mapping = inode->i_mapping; | 1041 | f->f_mapping = inode->i_mapping; |
| 1015 | 1042 | ||
| 1016 | f->f_flags = O_WRONLY | (flags & O_NONBLOCK); | 1043 | f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); |
| 1017 | f->f_version = 0; | 1044 | f->f_version = 0; |
| 1018 | 1045 | ||
| 1019 | return f; | 1046 | return f; |
| @@ -1057,7 +1084,7 @@ int do_pipe_flags(int *fd, int flags) | |||
| 1057 | int error; | 1084 | int error; |
| 1058 | int fdw, fdr; | 1085 | int fdw, fdr; |
| 1059 | 1086 | ||
| 1060 | if (flags & ~(O_CLOEXEC | O_NONBLOCK)) | 1087 | if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT)) |
| 1061 | return -EINVAL; | 1088 | return -EINVAL; |
| 1062 | 1089 | ||
| 1063 | fw = create_write_pipe(flags); | 1090 | fw = create_write_pipe(flags); |
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 6d626ff0cfd0..e1ac1ce16fb0 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */ | 6 | #define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */ |
| 7 | #define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */ | 7 | #define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */ |
| 8 | #define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */ | 8 | #define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */ |
| 9 | #define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */ | ||
| 9 | 10 | ||
| 10 | /** | 11 | /** |
| 11 | * struct pipe_buffer - a linux kernel pipe buffer | 12 | * struct pipe_buffer - a linux kernel pipe buffer |
