aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-05-04 13:25:40 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-05-04 13:25:40 -0400
commitcbdf811c77cf2906a099b8da92e9f6f335b68a73 (patch)
treec4f96893936eddb31c60476ea4e776499d9046df
parent936ef1d48ac9a9fc90746bacd93624969711775a (diff)
parent98232d504db0a1f91ecaa93686ed3bf61963103b (diff)
Merge branch 'splice' of git://brick.kernel.dk/data/git/linux-2.6-block
* 'splice' of git://brick.kernel.dk/data/git/linux-2.6-block: [PATCH] compat_sys_vmsplice: one-off in UIO_MAXIOV check [PATCH] splice: redo page lookup if add_to_page_cache() returns -EEXIST [PATCH] splice: rename remaining info variables to pipe [PATCH] splice: LRU fixups [PATCH] splice: fix unlocking of page on error ->prepare_write()
-rw-r--r--fs/compat.c2
-rw-r--r--fs/splice.c74
-rw-r--r--include/linux/pipe_fs_i.h5
3 files changed, 43 insertions, 38 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 3f3e8f4d43d6..970888aad843 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1323,7 +1323,7 @@ compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
1323{ 1323{
1324 unsigned i; 1324 unsigned i;
1325 struct iovec *iov; 1325 struct iovec *iov;
1326 if (nr_segs >= UIO_MAXIOV) 1326 if (nr_segs > UIO_MAXIOV)
1327 return -EINVAL; 1327 return -EINVAL;
1328 iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec)); 1328 iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
1329 for (i = 0; i < nr_segs; i++) { 1329 for (i = 0; i < nr_segs; i++) {
diff --git a/fs/splice.c b/fs/splice.c
index 7fb04970c72d..a285fd746dc0 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -51,7 +51,7 @@ struct splice_pipe_desc {
51 * addition of remove_mapping(). If success is returned, the caller may 51 * addition of remove_mapping(). If success is returned, the caller may
52 * attempt to reuse this page for another destination. 52 * attempt to reuse this page for another destination.
53 */ 53 */
54static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, 54static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,
55 struct pipe_buffer *buf) 55 struct pipe_buffer *buf)
56{ 56{
57 struct page *page = buf->page; 57 struct page *page = buf->page;
@@ -78,16 +78,18 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
78 return 1; 78 return 1;
79 } 79 }
80 80
81 buf->flags |= PIPE_BUF_FLAG_LRU;
81 return 0; 82 return 0;
82} 83}
83 84
84static void page_cache_pipe_buf_release(struct pipe_inode_info *info, 85static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,
85 struct pipe_buffer *buf) 86 struct pipe_buffer *buf)
86{ 87{
87 page_cache_release(buf->page); 88 page_cache_release(buf->page);
89 buf->flags &= ~PIPE_BUF_FLAG_LRU;
88} 90}
89 91
90static int page_cache_pipe_buf_pin(struct pipe_inode_info *info, 92static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe,
91 struct pipe_buffer *buf) 93 struct pipe_buffer *buf)
92{ 94{
93 struct page *page = buf->page; 95 struct page *page = buf->page;
@@ -141,6 +143,7 @@ static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
141 if (!(buf->flags & PIPE_BUF_FLAG_GIFT)) 143 if (!(buf->flags & PIPE_BUF_FLAG_GIFT))
142 return 1; 144 return 1;
143 145
146 buf->flags |= PIPE_BUF_FLAG_LRU;
144 return generic_pipe_buf_steal(pipe, buf); 147 return generic_pipe_buf_steal(pipe, buf);
145} 148}
146 149
@@ -321,6 +324,8 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
321 mapping_gfp_mask(mapping)); 324 mapping_gfp_mask(mapping));
322 if (unlikely(error)) { 325 if (unlikely(error)) {
323 page_cache_release(page); 326 page_cache_release(page);
327 if (error == -EEXIST)
328 continue;
324 break; 329 break;
325 } 330 }
326 /* 331 /*
@@ -497,14 +502,14 @@ EXPORT_SYMBOL(generic_file_splice_read);
497 * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos' 502 * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos'
498 * using sendpage(). Return the number of bytes sent. 503 * using sendpage(). Return the number of bytes sent.
499 */ 504 */
500static int pipe_to_sendpage(struct pipe_inode_info *info, 505static int pipe_to_sendpage(struct pipe_inode_info *pipe,
501 struct pipe_buffer *buf, struct splice_desc *sd) 506 struct pipe_buffer *buf, struct splice_desc *sd)
502{ 507{
503 struct file *file = sd->file; 508 struct file *file = sd->file;
504 loff_t pos = sd->pos; 509 loff_t pos = sd->pos;
505 int ret, more; 510 int ret, more;
506 511
507 ret = buf->ops->pin(info, buf); 512 ret = buf->ops->pin(pipe, buf);
508 if (!ret) { 513 if (!ret) {
509 more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; 514 more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
510 515
@@ -535,7 +540,7 @@ static int pipe_to_sendpage(struct pipe_inode_info *info,
535 * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create 540 * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
536 * a new page in the output file page cache and fill/dirty that. 541 * a new page in the output file page cache and fill/dirty that.
537 */ 542 */
538static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, 543static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
539 struct splice_desc *sd) 544 struct splice_desc *sd)
540{ 545{
541 struct file *file = sd->file; 546 struct file *file = sd->file;
@@ -549,7 +554,7 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
549 /* 554 /*
550 * make sure the data in this buffer is uptodate 555 * make sure the data in this buffer is uptodate
551 */ 556 */
552 ret = buf->ops->pin(info, buf); 557 ret = buf->ops->pin(pipe, buf);
553 if (unlikely(ret)) 558 if (unlikely(ret))
554 return ret; 559 return ret;
555 560
@@ -566,37 +571,23 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
566 */ 571 */
567 if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) { 572 if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) {
568 /* 573 /*
569 * If steal succeeds, buf->page is now pruned from the vm 574 * If steal succeeds, buf->page is now pruned from the
570 * side (page cache) and we can reuse it. The page will also 575 * pagecache and we can reuse it. The page will also be
571 * be locked on successful return. 576 * locked on successful return.
572 */ 577 */
573 if (buf->ops->steal(info, buf)) 578 if (buf->ops->steal(pipe, buf))
574 goto find_page; 579 goto find_page;
575 580
576 page = buf->page; 581 page = buf->page;
577 page_cache_get(page);
578
579 /*
580 * page must be on the LRU for adding to the pagecache.
581 * Check this without grabbing the zone lock, if it isn't
582 * the do grab the zone lock, recheck, and add if necessary.
583 */
584 if (!PageLRU(page)) {
585 struct zone *zone = page_zone(page);
586
587 spin_lock_irq(&zone->lru_lock);
588 if (!PageLRU(page)) {
589 SetPageLRU(page);
590 add_page_to_inactive_list(zone, page);
591 }
592 spin_unlock_irq(&zone->lru_lock);
593 }
594
595 if (add_to_page_cache(page, mapping, index, gfp_mask)) { 582 if (add_to_page_cache(page, mapping, index, gfp_mask)) {
596 page_cache_release(page);
597 unlock_page(page); 583 unlock_page(page);
598 goto find_page; 584 goto find_page;
599 } 585 }
586
587 page_cache_get(page);
588
589 if (!(buf->flags & PIPE_BUF_FLAG_LRU))
590 lru_cache_add(page);
600 } else { 591 } else {
601find_page: 592find_page:
602 page = find_lock_page(mapping, index); 593 page = find_lock_page(mapping, index);
@@ -647,23 +638,36 @@ find_page:
647 } 638 }
648 639
649 ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); 640 ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len);
650 if (ret == AOP_TRUNCATED_PAGE) { 641 if (unlikely(ret)) {
642 loff_t isize = i_size_read(mapping->host);
643
644 if (ret != AOP_TRUNCATED_PAGE)
645 unlock_page(page);
651 page_cache_release(page); 646 page_cache_release(page);
652 goto find_page; 647 if (ret == AOP_TRUNCATED_PAGE)
653 } else if (ret) 648 goto find_page;
649
650 /*
651 * prepare_write() may have instantiated a few blocks
652 * outside i_size. Trim these off again.
653 */
654 if (sd->pos + this_len > isize)
655 vmtruncate(mapping->host, isize);
656
654 goto out; 657 goto out;
658 }
655 659
656 if (buf->page != page) { 660 if (buf->page != page) {
657 /* 661 /*
658 * Careful, ->map() uses KM_USER0! 662 * Careful, ->map() uses KM_USER0!
659 */ 663 */
660 char *src = buf->ops->map(info, buf, 1); 664 char *src = buf->ops->map(pipe, buf, 1);
661 char *dst = kmap_atomic(page, KM_USER1); 665 char *dst = kmap_atomic(page, KM_USER1);
662 666
663 memcpy(dst + offset, src + buf->offset, this_len); 667 memcpy(dst + offset, src + buf->offset, this_len);
664 flush_dcache_page(page); 668 flush_dcache_page(page);
665 kunmap_atomic(dst, KM_USER1); 669 kunmap_atomic(dst, KM_USER1);
666 buf->ops->unmap(info, buf, src); 670 buf->ops->unmap(pipe, buf, src);
667 } 671 }
668 672
669 ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len); 673 ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len);
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index ba73108cbf8b..ea4f7cd7bfd8 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -5,8 +5,9 @@
5 5
6#define PIPE_BUFFERS (16) 6#define PIPE_BUFFERS (16)
7 7
8#define PIPE_BUF_FLAG_ATOMIC 0x01 /* was atomically mapped */ 8#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */
9#define PIPE_BUF_FLAG_GIFT 0x02 /* page is a gift */ 9#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
10#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
10 11
11struct pipe_buffer { 12struct pipe_buffer {
12 struct page *page; 13 struct page *page;