[PATCH] splice: fix offset problems

Make the move_from_pipe() actors return number of bytes processed, then
move_from_pipe() can decide more cleverly when to move on to the next
buffer.

This fixes problems with pipe offset and differing file offset.

Signed-off-by: Jens Axboe <axboe@suse.de>

authored by Jens Axboe and committed by Jens Axboe 016b661e ba5f5d90

+27 -19
+27 -19
fs/splice.c
··· 439 440 /* 441 * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos' 442 - * using sendpage(). 443 */ 444 static int pipe_to_sendpage(struct pipe_inode_info *info, 445 struct pipe_buffer *buf, struct splice_desc *sd) 446 { 447 struct file *file = sd->file; 448 loff_t pos = sd->pos; 449 - unsigned int offset; 450 ssize_t ret; 451 void *ptr; 452 int more; ··· 460 if (IS_ERR(ptr)) 461 return PTR_ERR(ptr); 462 463 - offset = pos & ~PAGE_CACHE_MASK; 464 more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; 465 466 - ret = file->f_op->sendpage(file, buf->page, offset, sd->len, &pos,more); 467 468 buf->ops->unmap(info, buf); 469 - if (ret == sd->len) 470 - return 0; 471 - 472 - return -EIO; 473 } 474 475 /* ··· 495 struct file *file = sd->file; 496 struct address_space *mapping = file->f_mapping; 497 gfp_t gfp_mask = mapping_gfp_mask(mapping); 498 - unsigned int offset; 499 struct page *page; 500 pgoff_t index; 501 char *src; ··· 510 511 index = sd->pos >> PAGE_CACHE_SHIFT; 512 offset = sd->pos & ~PAGE_CACHE_MASK; 513 514 /* 515 * Reuse buf page, if SPLICE_F_MOVE is set. ··· 558 * the full page. 559 */ 560 if (!PageUptodate(page)) { 561 - if (sd->len < PAGE_CACHE_SIZE) { 562 ret = mapping->a_ops->readpage(file, page); 563 if (unlikely(ret)) 564 goto out; ··· 582 } 583 } 584 585 - ret = mapping->a_ops->prepare_write(file, page, 0, sd->len); 586 if (ret == AOP_TRUNCATED_PAGE) { 587 page_cache_release(page); 588 goto find_page; ··· 592 if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) { 593 char *dst = kmap_atomic(page, KM_USER0); 594 595 - memcpy(dst + offset, src + buf->offset, sd->len); 596 flush_dcache_page(page); 597 kunmap_atomic(dst, KM_USER0); 598 } 599 600 - ret = mapping->a_ops->commit_write(file, page, 0, sd->len); 601 if (ret == AOP_TRUNCATED_PAGE) { 602 page_cache_release(page); 603 goto find_page; 604 } else if (ret) 605 goto out; 606 607 mark_page_accessed(page); 608 balance_dirty_pages_ratelimited(mapping); 609 out: ··· 656 sd.len = sd.total_len; 657 658 err = actor(pipe, buf, &sd); 659 - if (err) { 660 if (!ret && err != -ENODATA) 661 ret = err; 662 663 break; 664 } 665 666 - ret += sd.len; 667 - buf->offset += sd.len; 668 - buf->len -= sd.len; 669 670 if (!buf->len) { 671 buf->ops = NULL; ··· 682 do_wakeup = 1; 683 } 684 685 - sd.pos += sd.len; 686 - sd.total_len -= sd.len; 687 if (!sd.total_len) 688 break; 689 }
··· 439 440 /* 441 * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos' 442 + * using sendpage(). Return the number of bytes sent. 443 */ 444 static int pipe_to_sendpage(struct pipe_inode_info *info, 445 struct pipe_buffer *buf, struct splice_desc *sd) 446 { 447 struct file *file = sd->file; 448 loff_t pos = sd->pos; 449 ssize_t ret; 450 void *ptr; 451 int more; ··· 461 if (IS_ERR(ptr)) 462 return PTR_ERR(ptr); 463 464 more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; 465 466 + ret = file->f_op->sendpage(file, buf->page, buf->offset, sd->len, 467 + &pos, more); 468 469 buf->ops->unmap(info, buf); 470 + return ret; 471 } 472 473 /* ··· 499 struct file *file = sd->file; 500 struct address_space *mapping = file->f_mapping; 501 gfp_t gfp_mask = mapping_gfp_mask(mapping); 502 + unsigned int offset, this_len; 503 struct page *page; 504 pgoff_t index; 505 char *src; ··· 514 515 index = sd->pos >> PAGE_CACHE_SHIFT; 516 offset = sd->pos & ~PAGE_CACHE_MASK; 517 + 518 + this_len = sd->len; 519 + if (this_len + offset > PAGE_CACHE_SIZE) 520 + this_len = PAGE_CACHE_SIZE - offset; 521 522 /* 523 * Reuse buf page, if SPLICE_F_MOVE is set. ··· 558 * the full page. 559 */ 560 if (!PageUptodate(page)) { 561 + if (this_len < PAGE_CACHE_SIZE) { 562 ret = mapping->a_ops->readpage(file, page); 563 if (unlikely(ret)) 564 goto out; ··· 582 } 583 } 584 585 + ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); 586 if (ret == AOP_TRUNCATED_PAGE) { 587 page_cache_release(page); 588 goto find_page; ··· 592 if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) { 593 char *dst = kmap_atomic(page, KM_USER0); 594 595 + memcpy(dst + offset, src + buf->offset, this_len); 596 flush_dcache_page(page); 597 kunmap_atomic(dst, KM_USER0); 598 } 599 600 + ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len); 601 if (ret == AOP_TRUNCATED_PAGE) { 602 page_cache_release(page); 603 goto find_page; 604 } else if (ret) 605 goto out; 606 607 + /* 608 + * Return the number of bytes written. 609 + */ 610 + ret = this_len; 611 mark_page_accessed(page); 612 balance_dirty_pages_ratelimited(mapping); 613 out: ··· 652 sd.len = sd.total_len; 653 654 err = actor(pipe, buf, &sd); 655 + if (err <= 0) { 656 if (!ret && err != -ENODATA) 657 ret = err; 658 659 break; 660 } 661 662 + ret += err; 663 + buf->offset += err; 664 + buf->len -= err; 665 + 666 + sd.len -= err; 667 + sd.pos += err; 668 + sd.total_len -= err; 669 + if (sd.len) 670 + continue; 671 672 if (!buf->len) { 673 buf->ops = NULL; ··· 672 do_wakeup = 1; 673 } 674 675 if (!sd.total_len) 676 break; 677 }