aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c69
1 files changed, 7 insertions, 62 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 2df6be43c667..a7568bcc0f99 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -563,7 +563,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
563 struct address_space *mapping = file->f_mapping; 563 struct address_space *mapping = file->f_mapping;
564 unsigned int offset, this_len; 564 unsigned int offset, this_len;
565 struct page *page; 565 struct page *page;
566 pgoff_t index; 566 void *fsdata;
567 int ret; 567 int ret;
568 568
569 /* 569 /*
@@ -573,49 +573,16 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
573 if (unlikely(ret)) 573 if (unlikely(ret))
574 return ret; 574 return ret;
575 575
576 index = sd->pos >> PAGE_CACHE_SHIFT;
577 offset = sd->pos & ~PAGE_CACHE_MASK; 576 offset = sd->pos & ~PAGE_CACHE_MASK;
578 577
579 this_len = sd->len; 578 this_len = sd->len;
580 if (this_len + offset > PAGE_CACHE_SIZE) 579 if (this_len + offset > PAGE_CACHE_SIZE)
581 this_len = PAGE_CACHE_SIZE - offset; 580 this_len = PAGE_CACHE_SIZE - offset;
582 581
583find_page: 582 ret = pagecache_write_begin(file, mapping, sd->pos, this_len,
584 page = find_lock_page(mapping, index); 583 AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata);
585 if (!page) { 584 if (unlikely(ret))
586 ret = -ENOMEM; 585 goto out;
587 page = page_cache_alloc_cold(mapping);
588 if (unlikely(!page))
589 goto out_ret;
590
591 /*
592 * This will also lock the page
593 */
594 ret = add_to_page_cache_lru(page, mapping, index,
595 GFP_KERNEL);
596 if (unlikely(ret))
597 goto out_release;
598 }
599
600 ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len);
601 if (unlikely(ret)) {
602 loff_t isize = i_size_read(mapping->host);
603
604 if (ret != AOP_TRUNCATED_PAGE)
605 unlock_page(page);
606 page_cache_release(page);
607 if (ret == AOP_TRUNCATED_PAGE)
608 goto find_page;
609
610 /*
611 * prepare_write() may have instantiated a few blocks
612 * outside i_size. Trim these off again.
613 */
614 if (sd->pos + this_len > isize)
615 vmtruncate(mapping->host, isize);
616
617 goto out_ret;
618 }
619 586
620 if (buf->page != page) { 587 if (buf->page != page) {
621 /* 588 /*
@@ -629,31 +596,9 @@ find_page:
629 kunmap_atomic(dst, KM_USER1); 596 kunmap_atomic(dst, KM_USER1);
630 buf->ops->unmap(pipe, buf, src); 597 buf->ops->unmap(pipe, buf, src);
631 } 598 }
632 599 ret = pagecache_write_end(file, mapping, sd->pos, this_len, this_len,
633 ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len); 600 page, fsdata);
634 if (ret) {
635 if (ret == AOP_TRUNCATED_PAGE) {
636 page_cache_release(page);
637 goto find_page;
638 }
639 if (ret < 0)
640 goto out;
641 /*
642 * Partial write has happened, so 'ret' already initialized by
643 * number of bytes written, Where is nothing we have to do here.
644 */
645 } else
646 ret = this_len;
647 /*
648 * Return the number of bytes written and mark page as
649 * accessed, we are now done!
650 */
651 mark_page_accessed(page);
652out: 601out:
653 unlock_page(page);
654out_release:
655 page_cache_release(page);
656out_ret:
657 return ret; 602 return ret;
658} 603}
659 604