diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-06-12 15:17:17 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-07-10 02:04:12 -0400 |
commit | c66ab6fa705e1b2887a6d9246b798bdc526839e2 (patch) | |
tree | 764ece0ee44f937012dfaa1657709da548ed5b16 /fs/splice.c | |
parent | 71780f59e127bb281a9302d430495ca9586c14e7 (diff) |
splice: abstract out actor data
For direct splicing (or private splicing), the output may not be a file.
So abstract out the handling into a specified actor function and put
the data in the splice_desc structure earlier, so we can build on top
of that.
This is the first step in better splice handling for drivers, and also
for implementing vmsplice _to_ user memory.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 99 |
1 files changed, 70 insertions, 29 deletions
diff --git a/fs/splice.c b/fs/splice.c index e7d7080de2f9..68f6328236a6 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -668,31 +668,24 @@ out_ret: | |||
668 | * key here is the 'actor' worker passed in that actually moves the data | 668 | * key here is the 'actor' worker passed in that actually moves the data |
669 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | 669 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. |
670 | */ | 670 | */ |
671 | ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | 671 | ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, |
672 | struct file *out, loff_t *ppos, size_t len, | 672 | splice_actor *actor) |
673 | unsigned int flags, splice_actor *actor) | ||
674 | { | 673 | { |
675 | int ret, do_wakeup, err; | 674 | int ret, do_wakeup, err; |
676 | struct splice_desc sd; | ||
677 | 675 | ||
678 | ret = 0; | 676 | ret = 0; |
679 | do_wakeup = 0; | 677 | do_wakeup = 0; |
680 | 678 | ||
681 | sd.total_len = len; | ||
682 | sd.flags = flags; | ||
683 | sd.file = out; | ||
684 | sd.pos = *ppos; | ||
685 | |||
686 | for (;;) { | 679 | for (;;) { |
687 | if (pipe->nrbufs) { | 680 | if (pipe->nrbufs) { |
688 | struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; | 681 | struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; |
689 | const struct pipe_buf_operations *ops = buf->ops; | 682 | const struct pipe_buf_operations *ops = buf->ops; |
690 | 683 | ||
691 | sd.len = buf->len; | 684 | sd->len = buf->len; |
692 | if (sd.len > sd.total_len) | 685 | if (sd->len > sd->total_len) |
693 | sd.len = sd.total_len; | 686 | sd->len = sd->total_len; |
694 | 687 | ||
695 | err = actor(pipe, buf, &sd); | 688 | err = actor(pipe, buf, sd); |
696 | if (err <= 0) { | 689 | if (err <= 0) { |
697 | if (!ret && err != -ENODATA) | 690 | if (!ret && err != -ENODATA) |
698 | ret = err; | 691 | ret = err; |
@@ -704,10 +697,10 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
704 | buf->offset += err; | 697 | buf->offset += err; |
705 | buf->len -= err; | 698 | buf->len -= err; |
706 | 699 | ||
707 | sd.len -= err; | 700 | sd->len -= err; |
708 | sd.pos += err; | 701 | sd->pos += err; |
709 | sd.total_len -= err; | 702 | sd->total_len -= err; |
710 | if (sd.len) | 703 | if (sd->len) |
711 | continue; | 704 | continue; |
712 | 705 | ||
713 | if (!buf->len) { | 706 | if (!buf->len) { |
@@ -719,7 +712,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
719 | do_wakeup = 1; | 712 | do_wakeup = 1; |
720 | } | 713 | } |
721 | 714 | ||
722 | if (!sd.total_len) | 715 | if (!sd->total_len) |
723 | break; | 716 | break; |
724 | } | 717 | } |
725 | 718 | ||
@@ -732,7 +725,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
732 | break; | 725 | break; |
733 | } | 726 | } |
734 | 727 | ||
735 | if (flags & SPLICE_F_NONBLOCK) { | 728 | if (sd->flags & SPLICE_F_NONBLOCK) { |
736 | if (!ret) | 729 | if (!ret) |
737 | ret = -EAGAIN; | 730 | ret = -EAGAIN; |
738 | break; | 731 | break; |
@@ -772,6 +765,12 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
772 | { | 765 | { |
773 | ssize_t ret; | 766 | ssize_t ret; |
774 | struct inode *inode = out->f_mapping->host; | 767 | struct inode *inode = out->f_mapping->host; |
768 | struct splice_desc sd = { | ||
769 | .total_len = len, | ||
770 | .flags = flags, | ||
771 | .pos = *ppos, | ||
772 | .file = out, | ||
773 | }; | ||
775 | 774 | ||
776 | /* | 775 | /* |
777 | * The actor worker might be calling ->prepare_write and | 776 | * The actor worker might be calling ->prepare_write and |
@@ -780,7 +779,7 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
780 | * pipe->inode, we have to order lock acquiry here. | 779 | * pipe->inode, we have to order lock acquiry here. |
781 | */ | 780 | */ |
782 | inode_double_lock(inode, pipe->inode); | 781 | inode_double_lock(inode, pipe->inode); |
783 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor); | 782 | ret = __splice_from_pipe(pipe, &sd, actor); |
784 | inode_double_unlock(inode, pipe->inode); | 783 | inode_double_unlock(inode, pipe->inode); |
785 | 784 | ||
786 | return ret; | 785 | return ret; |
@@ -804,6 +803,12 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | |||
804 | { | 803 | { |
805 | struct address_space *mapping = out->f_mapping; | 804 | struct address_space *mapping = out->f_mapping; |
806 | struct inode *inode = mapping->host; | 805 | struct inode *inode = mapping->host; |
806 | struct splice_desc sd = { | ||
807 | .total_len = len, | ||
808 | .flags = flags, | ||
809 | .pos = *ppos, | ||
810 | .file = out, | ||
811 | }; | ||
807 | ssize_t ret; | 812 | ssize_t ret; |
808 | int err; | 813 | int err; |
809 | 814 | ||
@@ -811,7 +816,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | |||
811 | if (unlikely(err)) | 816 | if (unlikely(err)) |
812 | return err; | 817 | return err; |
813 | 818 | ||
814 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 819 | ret = __splice_from_pipe(pipe, &sd, pipe_to_file); |
815 | if (ret > 0) { | 820 | if (ret > 0) { |
816 | unsigned long nr_pages; | 821 | unsigned long nr_pages; |
817 | 822 | ||
@@ -956,14 +961,17 @@ static long do_splice_to(struct file *in, loff_t *ppos, | |||
956 | return in->f_op->splice_read(in, ppos, pipe, len, flags); | 961 | return in->f_op->splice_read(in, ppos, pipe, len, flags); |
957 | } | 962 | } |
958 | 963 | ||
959 | long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | 964 | /* |
960 | size_t len, unsigned int flags) | 965 | * Splices from an input file to an actor, using a 'direct' pipe. |
966 | */ | ||
967 | ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | ||
968 | splice_direct_actor *actor) | ||
961 | { | 969 | { |
962 | struct pipe_inode_info *pipe; | 970 | struct pipe_inode_info *pipe; |
963 | long ret, bytes; | 971 | long ret, bytes; |
964 | loff_t out_off; | ||
965 | umode_t i_mode; | 972 | umode_t i_mode; |
966 | int i; | 973 | size_t len; |
974 | int i, flags; | ||
967 | 975 | ||
968 | /* | 976 | /* |
969 | * We require the input being a regular file, as we don't want to | 977 | * We require the input being a regular file, as we don't want to |
@@ -999,7 +1007,13 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
999 | */ | 1007 | */ |
1000 | ret = 0; | 1008 | ret = 0; |
1001 | bytes = 0; | 1009 | bytes = 0; |
1002 | out_off = 0; | 1010 | len = sd->total_len; |
1011 | flags = sd->flags; | ||
1012 | |||
1013 | /* | ||
1014 | * Don't block on output, we have to drain the direct pipe. | ||
1015 | */ | ||
1016 | sd->flags &= ~SPLICE_F_NONBLOCK; | ||
1003 | 1017 | ||
1004 | while (len) { | 1018 | while (len) { |
1005 | size_t read_len, max_read_len; | 1019 | size_t read_len, max_read_len; |
@@ -1009,19 +1023,19 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
1009 | */ | 1023 | */ |
1010 | max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); | 1024 | max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); |
1011 | 1025 | ||
1012 | ret = do_splice_to(in, ppos, pipe, max_read_len, flags); | 1026 | ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags); |
1013 | if (unlikely(ret < 0)) | 1027 | if (unlikely(ret < 0)) |
1014 | goto out_release; | 1028 | goto out_release; |
1015 | 1029 | ||
1016 | read_len = ret; | 1030 | read_len = ret; |
1031 | sd->total_len = read_len; | ||
1017 | 1032 | ||
1018 | /* | 1033 | /* |
1019 | * NOTE: nonblocking mode only applies to the input. We | 1034 | * NOTE: nonblocking mode only applies to the input. We |
1020 | * must not do the output in nonblocking mode as then we | 1035 | * must not do the output in nonblocking mode as then we |
1021 | * could get stuck data in the internal pipe: | 1036 | * could get stuck data in the internal pipe: |
1022 | */ | 1037 | */ |
1023 | ret = do_splice_from(pipe, out, &out_off, read_len, | 1038 | ret = actor(pipe, sd); |
1024 | flags & ~SPLICE_F_NONBLOCK); | ||
1025 | if (unlikely(ret < 0)) | 1039 | if (unlikely(ret < 0)) |
1026 | goto out_release; | 1040 | goto out_release; |
1027 | 1041 | ||
@@ -1066,6 +1080,33 @@ out_release: | |||
1066 | return bytes; | 1080 | return bytes; |
1067 | 1081 | ||
1068 | return ret; | 1082 | return ret; |
1083 | |||
1084 | } | ||
1085 | EXPORT_SYMBOL(splice_direct_to_actor); | ||
1086 | |||
1087 | static int direct_splice_actor(struct pipe_inode_info *pipe, | ||
1088 | struct splice_desc *sd) | ||
1089 | { | ||
1090 | struct file *file = sd->file; | ||
1091 | |||
1092 | return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags); | ||
1093 | } | ||
1094 | |||
1095 | long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | ||
1096 | size_t len, unsigned int flags) | ||
1097 | { | ||
1098 | struct splice_desc sd = { | ||
1099 | .len = len, | ||
1100 | .total_len = len, | ||
1101 | .flags = flags, | ||
1102 | .pos = *ppos, | ||
1103 | .file = out, | ||
1104 | }; | ||
1105 | size_t ret; | ||
1106 | |||
1107 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); | ||
1108 | *ppos = sd.pos; | ||
1109 | return ret; | ||
1069 | } | 1110 | } |
1070 | 1111 | ||
1071 | /* | 1112 | /* |