aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2009-04-14 13:48:36 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-04-15 06:10:11 -0400
commitb3c2d2ddd63944ef2a1e4a43077b602288107e01 (patch)
tree2264092a285ab6af01f5f86d2cf06d2068546d37 /fs/splice.c
parent91e463c8f5f7a5b09d3d034c01a88567af60c504 (diff)
splice: split up __splice_from_pipe()
Split up __splice_from_pipe() into four helper functions: splice_from_pipe_begin() splice_from_pipe_next() splice_from_pipe_feed() splice_from_pipe_end() splice_from_pipe_next() will wait (if necessary) for more buffers to be added to the pipe. splice_from_pipe_feed() will feed the buffers to the supplied actor and return when there's no more data available (or if all of the requested data has been copied). This is necessary so that implementations can do locking around the non-waiting splice_from_pipe_feed(). This patch should not cause any change in behavior. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c217
1 files changed, 143 insertions, 74 deletions
diff --git a/fs/splice.c b/fs/splice.c
index c18aa7e03e2b..fd6b278d447b 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -601,107 +601,176 @@ out:
601 return ret; 601 return ret;
602} 602}
603 603
604static void wakeup_pipe_writers(struct pipe_inode_info *pipe)
605{
606 smp_mb();
607 if (waitqueue_active(&pipe->wait))
608 wake_up_interruptible(&pipe->wait);
609 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
610}
611
604/** 612/**
605 * __splice_from_pipe - splice data from a pipe to given actor 613 * splice_from_pipe_feed - feed available data from a pipe to a file
606 * @pipe: pipe to splice from 614 * @pipe: pipe to splice from
607 * @sd: information to @actor 615 * @sd: information to @actor
608 * @actor: handler that splices the data 616 * @actor: handler that splices the data
609 * 617 *
610 * Description: 618 * Description:
611 * This function does little more than loop over the pipe and call 619
612 * @actor to do the actual moving of a single struct pipe_buffer to 620 * This function loops over the pipe and calls @actor to do the
613 * the desired destination. See pipe_to_file, pipe_to_sendpage, or 621 * actual moving of a single struct pipe_buffer to the desired
614 * pipe_to_user. 622 * destination. It returns when there's no more buffers left in
623 * the pipe or if the requested number of bytes (@sd->total_len)
624 * have been copied. It returns a positive number (one) if the
625 * pipe needs to be filled with more data, zero if the required
626 * number of bytes have been copied and -errno on error.
615 * 627 *
628 * This, together with splice_from_pipe_{begin,end,next}, may be
629 * used to implement the functionality of __splice_from_pipe() when
630 * locking is required around copying the pipe buffers to the
631 * destination.
616 */ 632 */
617ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, 633int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_desc *sd,
618 splice_actor *actor) 634 splice_actor *actor)
619{ 635{
620 int ret, do_wakeup, err; 636 int ret;
621
622 ret = 0;
623 do_wakeup = 0;
624
625 for (;;) {
626 if (pipe->nrbufs) {
627 struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
628 const struct pipe_buf_operations *ops = buf->ops;
629 637
630 sd->len = buf->len; 638 while (pipe->nrbufs) {
631 if (sd->len > sd->total_len) 639 struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
632 sd->len = sd->total_len; 640 const struct pipe_buf_operations *ops = buf->ops;
633 641
634 err = actor(pipe, buf, sd); 642 sd->len = buf->len;
635 if (err <= 0) { 643 if (sd->len > sd->total_len)
636 if (!ret && err != -ENODATA) 644 sd->len = sd->total_len;
637 ret = err;
638 645
639 break; 646 ret = actor(pipe, buf, sd);
640 } 647 if (ret <= 0) {
648 if (ret == -ENODATA)
649 ret = 0;
650 return ret;
651 }
652 buf->offset += ret;
653 buf->len -= ret;
641 654
642 ret += err; 655 sd->num_spliced += ret;
643 buf->offset += err; 656 sd->len -= ret;
644 buf->len -= err; 657 sd->pos += ret;
658 sd->total_len -= ret;
645 659
646 sd->len -= err; 660 if (!buf->len) {
647 sd->pos += err; 661 buf->ops = NULL;
648 sd->total_len -= err; 662 ops->release(pipe, buf);
649 if (sd->len) 663 pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
650 continue; 664 pipe->nrbufs--;
665 if (pipe->inode)
666 sd->need_wakeup = true;
667 }
651 668
652 if (!buf->len) { 669 if (!sd->total_len)
653 buf->ops = NULL; 670 return 0;
654 ops->release(pipe, buf); 671 }
655 pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
656 pipe->nrbufs--;
657 if (pipe->inode)
658 do_wakeup = 1;
659 }
660 672
661 if (!sd->total_len) 673 return 1;
662 break; 674}
663 } 675EXPORT_SYMBOL(splice_from_pipe_feed);
664 676
665 if (pipe->nrbufs) 677/**
666 continue; 678 * splice_from_pipe_next - wait for some data to splice from
679 * @pipe: pipe to splice from
680 * @sd: information about the splice operation
681 *
682 * Description:
683 * This function will wait for some data and return a positive
684 * value (one) if pipe buffers are available. It will return zero
685 * or -errno if no more data needs to be spliced.
686 */
687int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_desc *sd)
688{
689 while (!pipe->nrbufs) {
667 if (!pipe->writers) 690 if (!pipe->writers)
668 break; 691 return 0;
669 if (!pipe->waiting_writers) {
670 if (ret)
671 break;
672 }
673 692
674 if (sd->flags & SPLICE_F_NONBLOCK) { 693 if (!pipe->waiting_writers && sd->num_spliced)
675 if (!ret) 694 return 0;
676 ret = -EAGAIN;
677 break;
678 }
679 695
680 if (signal_pending(current)) { 696 if (sd->flags & SPLICE_F_NONBLOCK)
681 if (!ret) 697 return -EAGAIN;
682 ret = -ERESTARTSYS;
683 break;
684 }
685 698
686 if (do_wakeup) { 699 if (signal_pending(current))
687 smp_mb(); 700 return -ERESTARTSYS;
688 if (waitqueue_active(&pipe->wait)) 701
689 wake_up_interruptible_sync(&pipe->wait); 702 if (sd->need_wakeup) {
690 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); 703 wakeup_pipe_writers(pipe);
691 do_wakeup = 0; 704 sd->need_wakeup = false;
692 } 705 }
693 706
694 pipe_wait(pipe); 707 pipe_wait(pipe);
695 } 708 }
696 709
697 if (do_wakeup) { 710 return 1;
698 smp_mb(); 711}
699 if (waitqueue_active(&pipe->wait)) 712EXPORT_SYMBOL(splice_from_pipe_next);
700 wake_up_interruptible(&pipe->wait);
701 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
702 }
703 713
704 return ret; 714/**
715 * splice_from_pipe_begin - start splicing from pipe
716 * @pipe: pipe to splice from
717 *
718 * Description:
719 * This function should be called before a loop containing
720 * splice_from_pipe_next() and splice_from_pipe_feed() to
721 * initialize the necessary fields of @sd.
722 */
723void splice_from_pipe_begin(struct splice_desc *sd)
724{
725 sd->num_spliced = 0;
726 sd->need_wakeup = false;
727}
728EXPORT_SYMBOL(splice_from_pipe_begin);
729
730/**
731 * splice_from_pipe_end - finish splicing from pipe
732 * @pipe: pipe to splice from
733 * @sd: information about the splice operation
734 *
735 * Description:
736 * This function will wake up pipe writers if necessary. It should
737 * be called after a loop containing splice_from_pipe_next() and
738 * splice_from_pipe_feed().
739 */
740void splice_from_pipe_end(struct pipe_inode_info *pipe, struct splice_desc *sd)
741{
742 if (sd->need_wakeup)
743 wakeup_pipe_writers(pipe);
744}
745EXPORT_SYMBOL(splice_from_pipe_end);
746
747/**
748 * __splice_from_pipe - splice data from a pipe to given actor
749 * @pipe: pipe to splice from
750 * @sd: information to @actor
751 * @actor: handler that splices the data
752 *
753 * Description:
754 * This function does little more than loop over the pipe and call
755 * @actor to do the actual moving of a single struct pipe_buffer to
756 * the desired destination. See pipe_to_file, pipe_to_sendpage, or
757 * pipe_to_user.
758 *
759 */
760ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
761 splice_actor *actor)
762{
763 int ret;
764
765 splice_from_pipe_begin(sd);
766 do {
767 ret = splice_from_pipe_next(pipe, sd);
768 if (ret > 0)
769 ret = splice_from_pipe_feed(pipe, sd, actor);
770 } while (ret > 0);
771 splice_from_pipe_end(pipe, sd);
772
773 return sd->num_spliced ? sd->num_spliced : ret;
705} 774}
706EXPORT_SYMBOL(__splice_from_pipe); 775EXPORT_SYMBOL(__splice_from_pipe);
707 776