diff options
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 109 |
1 files changed, 31 insertions, 78 deletions
diff --git a/fs/splice.c b/fs/splice.c index 2fca6ebf4cc2..5428b0ff3b6f 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -576,76 +576,21 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
576 | if (this_len + offset > PAGE_CACHE_SIZE) | 576 | if (this_len + offset > PAGE_CACHE_SIZE) |
577 | this_len = PAGE_CACHE_SIZE - offset; | 577 | this_len = PAGE_CACHE_SIZE - offset; |
578 | 578 | ||
579 | /* | ||
580 | * Reuse buf page, if SPLICE_F_MOVE is set and we are doing a full | ||
581 | * page. | ||
582 | */ | ||
583 | if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) { | ||
584 | /* | ||
585 | * If steal succeeds, buf->page is now pruned from the | ||
586 | * pagecache and we can reuse it. The page will also be | ||
587 | * locked on successful return. | ||
588 | */ | ||
589 | if (buf->ops->steal(pipe, buf)) | ||
590 | goto find_page; | ||
591 | |||
592 | page = buf->page; | ||
593 | if (add_to_page_cache(page, mapping, index, GFP_KERNEL)) { | ||
594 | unlock_page(page); | ||
595 | goto find_page; | ||
596 | } | ||
597 | |||
598 | page_cache_get(page); | ||
599 | |||
600 | if (!(buf->flags & PIPE_BUF_FLAG_LRU)) | ||
601 | lru_cache_add(page); | ||
602 | } else { | ||
603 | find_page: | 579 | find_page: |
604 | page = find_lock_page(mapping, index); | 580 | page = find_lock_page(mapping, index); |
605 | if (!page) { | 581 | if (!page) { |
606 | ret = -ENOMEM; | 582 | ret = -ENOMEM; |
607 | page = page_cache_alloc_cold(mapping); | 583 | page = page_cache_alloc_cold(mapping); |
608 | if (unlikely(!page)) | 584 | if (unlikely(!page)) |
609 | goto out_ret; | 585 | goto out_ret; |
610 | |||
611 | /* | ||
612 | * This will also lock the page | ||
613 | */ | ||
614 | ret = add_to_page_cache_lru(page, mapping, index, | ||
615 | GFP_KERNEL); | ||
616 | if (unlikely(ret)) | ||
617 | goto out; | ||
618 | } | ||
619 | 586 | ||
620 | /* | 587 | /* |
621 | * We get here with the page locked. If the page is also | 588 | * This will also lock the page |
622 | * uptodate, we don't need to do more. If it isn't, we | ||
623 | * may need to bring it in if we are not going to overwrite | ||
624 | * the full page. | ||
625 | */ | 589 | */ |
626 | if (!PageUptodate(page)) { | 590 | ret = add_to_page_cache_lru(page, mapping, index, |
627 | if (this_len < PAGE_CACHE_SIZE) { | 591 | GFP_KERNEL); |
628 | ret = mapping->a_ops->readpage(file, page); | 592 | if (unlikely(ret)) |
629 | if (unlikely(ret)) | 593 | goto out; |
630 | goto out; | ||
631 | |||
632 | lock_page(page); | ||
633 | |||
634 | if (!PageUptodate(page)) { | ||
635 | /* | ||
636 | * Page got invalidated, repeat. | ||
637 | */ | ||
638 | if (!page->mapping) { | ||
639 | unlock_page(page); | ||
640 | page_cache_release(page); | ||
641 | goto find_page; | ||
642 | } | ||
643 | ret = -EIO; | ||
644 | goto out; | ||
645 | } | ||
646 | } else | ||
647 | SetPageUptodate(page); | ||
648 | } | ||
649 | } | 594 | } |
650 | 595 | ||
651 | ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); | 596 | ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); |
@@ -682,18 +627,25 @@ find_page: | |||
682 | } | 627 | } |
683 | 628 | ||
684 | ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len); | 629 | ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len); |
685 | if (!ret) { | 630 | if (ret) { |
631 | if (ret == AOP_TRUNCATED_PAGE) { | ||
632 | page_cache_release(page); | ||
633 | goto find_page; | ||
634 | } | ||
635 | if (ret < 0) | ||
636 | goto out; | ||
686 | /* | 637 | /* |
687 | * Return the number of bytes written and mark page as | 638 | * Partial write has happened, so 'ret' already initialized by |
688 | * accessed, we are now done! | 639 | * number of bytes written, Where is nothing we have to do here. |
689 | */ | 640 | */ |
641 | } else | ||
690 | ret = this_len; | 642 | ret = this_len; |
691 | mark_page_accessed(page); | 643 | /* |
692 | balance_dirty_pages_ratelimited(mapping); | 644 | * Return the number of bytes written and mark page as |
693 | } else if (ret == AOP_TRUNCATED_PAGE) { | 645 | * accessed, we are now done! |
694 | page_cache_release(page); | 646 | */ |
695 | goto find_page; | 647 | mark_page_accessed(page); |
696 | } | 648 | balance_dirty_pages_ratelimited(mapping); |
697 | out: | 649 | out: |
698 | page_cache_release(page); | 650 | page_cache_release(page); |
699 | unlock_page(page); | 651 | unlock_page(page); |
@@ -706,9 +658,9 @@ out_ret: | |||
706 | * key here is the 'actor' worker passed in that actually moves the data | 658 | * key here is the 'actor' worker passed in that actually moves the data |
707 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | 659 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. |
708 | */ | 660 | */ |
709 | static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | 661 | ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, |
710 | struct file *out, loff_t *ppos, size_t len, | 662 | struct file *out, loff_t *ppos, size_t len, |
711 | unsigned int flags, splice_actor *actor) | 663 | unsigned int flags, splice_actor *actor) |
712 | { | 664 | { |
713 | int ret, do_wakeup, err; | 665 | int ret, do_wakeup, err; |
714 | struct splice_desc sd; | 666 | struct splice_desc sd; |
@@ -802,6 +754,7 @@ static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
802 | 754 | ||
803 | return ret; | 755 | return ret; |
804 | } | 756 | } |
757 | EXPORT_SYMBOL(__splice_from_pipe); | ||
805 | 758 | ||
806 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | 759 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, |
807 | loff_t *ppos, size_t len, unsigned int flags, | 760 | loff_t *ppos, size_t len, unsigned int flags, |