diff options
Diffstat (limited to 'fs/pipe.c')
-rw-r--r-- | fs/pipe.c | 40 |
1 files changed, 34 insertions, 6 deletions
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/log2.h> | 14 | #include <linux/log2.h> |
15 | #include <linux/mount.h> | 15 | #include <linux/mount.h> |
16 | #include <linux/magic.h> | ||
16 | #include <linux/pipe_fs_i.h> | 17 | #include <linux/pipe_fs_i.h> |
17 | #include <linux/uio.h> | 18 | #include <linux/uio.h> |
18 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
@@ -230,7 +231,7 @@ void *generic_pipe_buf_map(struct pipe_inode_info *pipe, | |||
230 | { | 231 | { |
231 | if (atomic) { | 232 | if (atomic) { |
232 | buf->flags |= PIPE_BUF_FLAG_ATOMIC; | 233 | buf->flags |= PIPE_BUF_FLAG_ATOMIC; |
233 | return kmap_atomic(buf->page, KM_USER0); | 234 | return kmap_atomic(buf->page); |
234 | } | 235 | } |
235 | 236 | ||
236 | return kmap(buf->page); | 237 | return kmap(buf->page); |
@@ -251,7 +252,7 @@ void generic_pipe_buf_unmap(struct pipe_inode_info *pipe, | |||
251 | { | 252 | { |
252 | if (buf->flags & PIPE_BUF_FLAG_ATOMIC) { | 253 | if (buf->flags & PIPE_BUF_FLAG_ATOMIC) { |
253 | buf->flags &= ~PIPE_BUF_FLAG_ATOMIC; | 254 | buf->flags &= ~PIPE_BUF_FLAG_ATOMIC; |
254 | kunmap_atomic(map_data, KM_USER0); | 255 | kunmap_atomic(map_data); |
255 | } else | 256 | } else |
256 | kunmap(buf->page); | 257 | kunmap(buf->page); |
257 | } | 258 | } |
@@ -345,6 +346,16 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { | |||
345 | .get = generic_pipe_buf_get, | 346 | .get = generic_pipe_buf_get, |
346 | }; | 347 | }; |
347 | 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 | |||
348 | static ssize_t | 359 | static ssize_t |
349 | pipe_read(struct kiocb *iocb, const struct iovec *_iov, | 360 | pipe_read(struct kiocb *iocb, const struct iovec *_iov, |
350 | unsigned long nr_segs, loff_t pos) | 361 | unsigned long nr_segs, loff_t pos) |
@@ -406,6 +417,13 @@ redo: | |||
406 | ret += chars; | 417 | ret += chars; |
407 | buf->offset += chars; | 418 | buf->offset += chars; |
408 | 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 | |||
409 | if (!buf->len) { | 427 | if (!buf->len) { |
410 | buf->ops = NULL; | 428 | buf->ops = NULL; |
411 | ops->release(pipe, buf); | 429 | ops->release(pipe, buf); |
@@ -458,6 +476,11 @@ redo: | |||
458 | return ret; | 476 | return ret; |
459 | } | 477 | } |
460 | 478 | ||
479 | static inline int is_packetized(struct file *file) | ||
480 | { | ||
481 | return (file->f_flags & O_DIRECT) != 0; | ||
482 | } | ||
483 | |||
461 | static ssize_t | 484 | static ssize_t |
462 | pipe_write(struct kiocb *iocb, const struct iovec *_iov, | 485 | pipe_write(struct kiocb *iocb, const struct iovec *_iov, |
463 | unsigned long nr_segs, loff_t ppos) | 486 | unsigned long nr_segs, loff_t ppos) |
@@ -565,14 +588,14 @@ redo1: | |||
565 | iov_fault_in_pages_read(iov, chars); | 588 | iov_fault_in_pages_read(iov, chars); |
566 | redo2: | 589 | redo2: |
567 | if (atomic) | 590 | if (atomic) |
568 | src = kmap_atomic(page, KM_USER0); | 591 | src = kmap_atomic(page); |
569 | else | 592 | else |
570 | src = kmap(page); | 593 | src = kmap(page); |
571 | 594 | ||
572 | error = pipe_iov_copy_from_user(src, iov, chars, | 595 | error = pipe_iov_copy_from_user(src, iov, chars, |
573 | atomic); | 596 | atomic); |
574 | if (atomic) | 597 | if (atomic) |
575 | kunmap_atomic(src, KM_USER0); | 598 | kunmap_atomic(src); |
576 | else | 599 | else |
577 | kunmap(page); | 600 | kunmap(page); |
578 | 601 | ||
@@ -592,6 +615,11 @@ redo2: | |||
592 | buf->ops = &anon_pipe_buf_ops; | 615 | buf->ops = &anon_pipe_buf_ops; |
593 | buf->offset = 0; | 616 | buf->offset = 0; |
594 | 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 | } | ||
595 | pipe->nrbufs = ++bufs; | 623 | pipe->nrbufs = ++bufs; |
596 | pipe->tmp_page = NULL; | 624 | pipe->tmp_page = NULL; |
597 | 625 | ||
@@ -1012,7 +1040,7 @@ struct file *create_write_pipe(int flags) | |||
1012 | goto err_dentry; | 1040 | goto err_dentry; |
1013 | f->f_mapping = inode->i_mapping; | 1041 | f->f_mapping = inode->i_mapping; |
1014 | 1042 | ||
1015 | f->f_flags = O_WRONLY | (flags & O_NONBLOCK); | 1043 | f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); |
1016 | f->f_version = 0; | 1044 | f->f_version = 0; |
1017 | 1045 | ||
1018 | return f; | 1046 | return f; |
@@ -1056,7 +1084,7 @@ int do_pipe_flags(int *fd, int flags) | |||
1056 | int error; | 1084 | int error; |
1057 | int fdw, fdr; | 1085 | int fdw, fdr; |
1058 | 1086 | ||
1059 | if (flags & ~(O_CLOEXEC | O_NONBLOCK)) | 1087 | if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT)) |
1060 | return -EINVAL; | 1088 | return -EINVAL; |
1061 | 1089 | ||
1062 | fw = create_write_pipe(flags); | 1090 | fw = create_write_pipe(flags); |