aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/file.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 672b0fedb17b..f68964076c0a 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -546,7 +546,6 @@ ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
546 int written = 0; 546 int written = 0;
547 int flags; 547 int flags;
548 int check_caps = 0; 548 int check_caps = 0;
549 int page_align;
550 int ret; 549 int ret;
551 struct timespec mtime = CURRENT_TIME; 550 struct timespec mtime = CURRENT_TIME;
552 loff_t pos = iocb->ki_pos; 551 loff_t pos = iocb->ki_pos;
@@ -575,10 +574,9 @@ ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
575 iov_iter_init(&i, WRITE, iov, nr_segs, count); 574 iov_iter_init(&i, WRITE, iov, nr_segs, count);
576 575
577 while (iov_iter_count(&i) > 0) { 576 while (iov_iter_count(&i) > 0) {
578 void __user *data = i.iov->iov_base + i.iov_offset; 577 u64 len = iov_iter_single_seg_count(&i);
579 u64 len = i.iov->iov_len - i.iov_offset; 578 size_t start;
580 579 ssize_t n;
581 page_align = (unsigned long)data & ~PAGE_MASK;
582 580
583 snapc = ci->i_snap_realm->cached_context; 581 snapc = ci->i_snap_realm->cached_context;
584 vino = ceph_vino(inode); 582 vino = ceph_vino(inode);
@@ -594,20 +592,21 @@ ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
594 break; 592 break;
595 } 593 }
596 594
597 num_pages = calc_pages_for(page_align, len); 595 n = iov_iter_get_pages_alloc(&i, &pages, len, &start);
598 pages = ceph_get_direct_page_vector(data, num_pages, false); 596 if (unlikely(n < 0)) {
599 if (IS_ERR(pages)) { 597 ret = n;
600 ret = PTR_ERR(pages); 598 ceph_osdc_put_request(req);
601 goto out; 599 break;
602 } 600 }
603 601
602 num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE;
604 /* 603 /*
605 * throw out any page cache pages in this range. this 604 * throw out any page cache pages in this range. this
606 * may block. 605 * may block.
607 */ 606 */
608 truncate_inode_pages_range(inode->i_mapping, pos, 607 truncate_inode_pages_range(inode->i_mapping, pos,
609 (pos+len) | (PAGE_CACHE_SIZE-1)); 608 (pos+n) | (PAGE_CACHE_SIZE-1));
610 osd_req_op_extent_osd_data_pages(req, 0, pages, len, page_align, 609 osd_req_op_extent_osd_data_pages(req, 0, pages, n, start,
611 false, false); 610 false, false);
612 611
613 /* BUG_ON(vino.snap != CEPH_NOSNAP); */ 612 /* BUG_ON(vino.snap != CEPH_NOSNAP); */
@@ -619,22 +618,20 @@ ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
619 618
620 ceph_put_page_vector(pages, num_pages, false); 619 ceph_put_page_vector(pages, num_pages, false);
621 620
622out:
623 ceph_osdc_put_request(req); 621 ceph_osdc_put_request(req);
624 if (ret == 0) { 622 if (ret)
625 pos += len;
626 written += len;
627 iov_iter_advance(&i, (size_t)len);
628
629 if (pos > i_size_read(inode)) {
630 check_caps = ceph_inode_set_size(inode, pos);
631 if (check_caps)
632 ceph_check_caps(ceph_inode(inode),
633 CHECK_CAPS_AUTHONLY,
634 NULL);
635 }
636 } else
637 break; 623 break;
624 pos += n;
625 written += n;
626 iov_iter_advance(&i, n);
627
628 if (pos > i_size_read(inode)) {
629 check_caps = ceph_inode_set_size(inode, pos);
630 if (check_caps)
631 ceph_check_caps(ceph_inode(inode),
632 CHECK_CAPS_AUTHONLY,
633 NULL);
634 }
638 } 635 }
639 636
640 if (ret != -EOLDSNAPC && written > 0) { 637 if (ret != -EOLDSNAPC && written > 0) {