diff options
Diffstat (limited to 'fs/splice.c')
| -rw-r--r-- | fs/splice.c | 84 |
1 files changed, 15 insertions, 69 deletions
diff --git a/fs/splice.c b/fs/splice.c index 2fca6ebf4cc2..07f6556add0a 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); |
| @@ -706,9 +651,9 @@ out_ret: | |||
| 706 | * key here is the 'actor' worker passed in that actually moves the data | 651 | * 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. | 652 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. |
| 708 | */ | 653 | */ |
| 709 | static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | 654 | ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, |
| 710 | struct file *out, loff_t *ppos, size_t len, | 655 | struct file *out, loff_t *ppos, size_t len, |
| 711 | unsigned int flags, splice_actor *actor) | 656 | unsigned int flags, splice_actor *actor) |
| 712 | { | 657 | { |
| 713 | int ret, do_wakeup, err; | 658 | int ret, do_wakeup, err; |
| 714 | struct splice_desc sd; | 659 | struct splice_desc sd; |
| @@ -802,6 +747,7 @@ static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
| 802 | 747 | ||
| 803 | return ret; | 748 | return ret; |
| 804 | } | 749 | } |
| 750 | EXPORT_SYMBOL(__splice_from_pipe); | ||
| 805 | 751 | ||
| 806 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | 752 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, |
| 807 | loff_t *ppos, size_t len, unsigned int flags, | 753 | loff_t *ppos, size_t len, unsigned int flags, |
