diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/file.c | 49 |
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 | ||
622 | out: | ||
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) { |