aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c148
1 files changed, 130 insertions, 18 deletions
diff --git a/fs/splice.c b/fs/splice.c
index a5326127aad5..c47b561edac0 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -680,8 +680,7 @@ EXPORT_SYMBOL(generic_splice_sendpage);
680 * Attempt to initiate a splice from pipe to file. 680 * Attempt to initiate a splice from pipe to file.
681 */ 681 */
682static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, 682static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
683 loff_t __user *off_out, size_t len, 683 size_t len, unsigned int flags)
684 unsigned int flags)
685{ 684{
686 loff_t pos; 685 loff_t pos;
687 int ret; 686 int ret;
@@ -692,9 +691,6 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
692 if (!(out->f_mode & FMODE_WRITE)) 691 if (!(out->f_mode & FMODE_WRITE))
693 return -EBADF; 692 return -EBADF;
694 693
695 if (off_out && copy_from_user(&out->f_pos, off_out, sizeof(loff_t)))
696 return -EFAULT;
697
698 pos = out->f_pos; 694 pos = out->f_pos;
699 695
700 ret = rw_verify_area(WRITE, out, &pos, len); 696 ret = rw_verify_area(WRITE, out, &pos, len);
@@ -707,9 +703,8 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
707/* 703/*
708 * Attempt to initiate a splice from a file to a pipe. 704 * Attempt to initiate a splice from a file to a pipe.
709 */ 705 */
710static long do_splice_to(struct file *in, loff_t __user *off_in, 706static long do_splice_to(struct file *in, struct pipe_inode_info *pipe,
711 struct pipe_inode_info *pipe, size_t len, 707 size_t len, unsigned int flags)
712 unsigned int flags)
713{ 708{
714 loff_t pos, isize, left; 709 loff_t pos, isize, left;
715 int ret; 710 int ret;
@@ -720,9 +715,6 @@ static long do_splice_to(struct file *in, loff_t __user *off_in,
720 if (!(in->f_mode & FMODE_READ)) 715 if (!(in->f_mode & FMODE_READ))
721 return -EBADF; 716 return -EBADF;
722 717
723 if (off_in && copy_from_user(&in->f_pos, off_in, sizeof(loff_t)))
724 return -EFAULT;
725
726 pos = in->f_pos; 718 pos = in->f_pos;
727 719
728 ret = rw_verify_area(READ, in, &pos, len); 720 ret = rw_verify_area(READ, in, &pos, len);
@@ -740,6 +732,118 @@ static long do_splice_to(struct file *in, loff_t __user *off_in,
740 return in->f_op->splice_read(in, pipe, len, flags); 732 return in->f_op->splice_read(in, pipe, len, flags);
741} 733}
742 734
735long do_splice_direct(struct file *in, struct file *out, size_t len,
736 unsigned int flags)
737{
738 struct pipe_inode_info *pipe;
739 long ret, bytes;
740 umode_t i_mode;
741 int i;
742
743 /*
744 * We require the input being a regular file, as we don't want to
745 * randomly drop data for eg socket -> socket splicing. Use the
746 * piped splicing for that!
747 */
748 i_mode = in->f_dentry->d_inode->i_mode;
749 if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
750 return -EINVAL;
751
752 /*
753 * neither in nor out is a pipe, setup an internal pipe attached to
754 * 'out' and transfer the wanted data from 'in' to 'out' through that
755 */
756 pipe = current->splice_pipe;
757 if (!pipe) {
758 pipe = alloc_pipe_info(NULL);
759 if (!pipe)
760 return -ENOMEM;
761
762 /*
763 * We don't have an immediate reader, but we'll read the stuff
764 * out of the pipe right after the move_to_pipe(). So set
765 * PIPE_READERS appropriately.
766 */
767 pipe->readers = 1;
768
769 current->splice_pipe = pipe;
770 }
771
772 /*
773 * do the splice
774 */
775 ret = 0;
776 bytes = 0;
777
778 while (len) {
779 size_t read_len, max_read_len;
780
781 /*
782 * Do at most PIPE_BUFFERS pages worth of transfer:
783 */
784 max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
785
786 ret = do_splice_to(in, pipe, max_read_len, flags);
787 if (unlikely(ret < 0))
788 goto out_release;
789
790 read_len = ret;
791
792 /*
793 * NOTE: nonblocking mode only applies to the input. We
794 * must not do the output in nonblocking mode as then we
795 * could get stuck data in the internal pipe:
796 */
797 ret = do_splice_from(pipe, out, read_len,
798 flags & ~SPLICE_F_NONBLOCK);
799 if (unlikely(ret < 0))
800 goto out_release;
801
802 bytes += ret;
803 len -= ret;
804
805 /*
806 * In nonblocking mode, if we got back a short read then
807 * that was due to either an IO error or due to the
808 * pagecache entry not being there. In the IO error case
809 * the _next_ splice attempt will produce a clean IO error
810 * return value (not a short read), so in both cases it's
811 * correct to break out of the loop here:
812 */
813 if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len))
814 break;
815 }
816
817 pipe->nrbufs = pipe->curbuf = 0;
818
819 return bytes;
820
821out_release:
822 /*
823 * If we did an incomplete transfer we must release
824 * the pipe buffers in question:
825 */
826 for (i = 0; i < PIPE_BUFFERS; i++) {
827 struct pipe_buffer *buf = pipe->bufs + i;
828
829 if (buf->ops) {
830 buf->ops->release(pipe, buf);
831 buf->ops = NULL;
832 }
833 }
834 pipe->nrbufs = pipe->curbuf = 0;
835
836 /*
837 * If we transferred some data, return the number of bytes:
838 */
839 if (bytes > 0)
840 return bytes;
841
842 return ret;
843}
844
845EXPORT_SYMBOL(do_splice_direct);
846
743/* 847/*
744 * Determine where to splice to/from. 848 * Determine where to splice to/from.
745 */ 849 */
@@ -749,25 +853,33 @@ static long do_splice(struct file *in, loff_t __user *off_in,
749{ 853{
750 struct pipe_inode_info *pipe; 854 struct pipe_inode_info *pipe;
751 855
752 if (off_out && out->f_op->llseek == no_llseek)
753 return -EINVAL;
754 if (off_in && in->f_op->llseek == no_llseek)
755 return -EINVAL;
756
757 pipe = in->f_dentry->d_inode->i_pipe; 856 pipe = in->f_dentry->d_inode->i_pipe;
758 if (pipe) { 857 if (pipe) {
759 if (off_in) 858 if (off_in)
760 return -ESPIPE; 859 return -ESPIPE;
860 if (off_out) {
861 if (out->f_op->llseek == no_llseek)
862 return -EINVAL;
863 if (copy_from_user(&out->f_pos, off_out,
864 sizeof(loff_t)))
865 return -EFAULT;
866 }
761 867
762 return do_splice_from(pipe, out, off_out, len, flags); 868 return do_splice_from(pipe, out, len, flags);
763 } 869 }
764 870
765 pipe = out->f_dentry->d_inode->i_pipe; 871 pipe = out->f_dentry->d_inode->i_pipe;
766 if (pipe) { 872 if (pipe) {
767 if (off_out) 873 if (off_out)
768 return -ESPIPE; 874 return -ESPIPE;
875 if (off_in) {
876 if (in->f_op->llseek == no_llseek)
877 return -EINVAL;
878 if (copy_from_user(&in->f_pos, off_in, sizeof(loff_t)))
879 return -EFAULT;
880 }
769 881
770 return do_splice_to(in, off_in, pipe, len, flags); 882 return do_splice_to(in, pipe, len, flags);
771 } 883 }
772 884
773 return -EINVAL; 885 return -EINVAL;