diff options
Diffstat (limited to 'fs/ceph/addr.c')
| -rw-r--r-- | fs/ceph/addr.c | 88 |
1 files changed, 42 insertions, 46 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 38b5c1bc6776..5318a3b704f6 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
| @@ -439,13 +439,12 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) | |||
| 439 | struct ceph_inode_info *ci; | 439 | struct ceph_inode_info *ci; |
| 440 | struct ceph_fs_client *fsc; | 440 | struct ceph_fs_client *fsc; |
| 441 | struct ceph_osd_client *osdc; | 441 | struct ceph_osd_client *osdc; |
| 442 | loff_t page_off = page_offset(page); | ||
| 443 | int len = PAGE_CACHE_SIZE; | ||
| 444 | loff_t i_size; | ||
| 445 | int err = 0; | ||
| 446 | struct ceph_snap_context *snapc, *oldest; | 442 | struct ceph_snap_context *snapc, *oldest; |
| 447 | u64 snap_size = 0; | 443 | loff_t page_off = page_offset(page); |
| 448 | long writeback_stat; | 444 | long writeback_stat; |
| 445 | u64 truncate_size, snap_size = 0; | ||
| 446 | u32 truncate_seq; | ||
| 447 | int err = 0, len = PAGE_CACHE_SIZE; | ||
| 449 | 448 | ||
| 450 | dout("writepage %p idx %lu\n", page, page->index); | 449 | dout("writepage %p idx %lu\n", page, page->index); |
| 451 | 450 | ||
| @@ -475,13 +474,20 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) | |||
| 475 | } | 474 | } |
| 476 | ceph_put_snap_context(oldest); | 475 | ceph_put_snap_context(oldest); |
| 477 | 476 | ||
| 477 | spin_lock(&ci->i_ceph_lock); | ||
| 478 | truncate_seq = ci->i_truncate_seq; | ||
| 479 | truncate_size = ci->i_truncate_size; | ||
| 480 | if (!snap_size) | ||
| 481 | snap_size = i_size_read(inode); | ||
| 482 | spin_unlock(&ci->i_ceph_lock); | ||
| 483 | |||
| 478 | /* is this a partial page at end of file? */ | 484 | /* is this a partial page at end of file? */ |
| 479 | if (snap_size) | 485 | if (page_off >= snap_size) { |
| 480 | i_size = snap_size; | 486 | dout("%p page eof %llu\n", page, snap_size); |
| 481 | else | 487 | goto out; |
| 482 | i_size = i_size_read(inode); | 488 | } |
| 483 | if (i_size < page_off + len) | 489 | if (snap_size < page_off + len) |
| 484 | len = i_size - page_off; | 490 | len = snap_size - page_off; |
| 485 | 491 | ||
| 486 | dout("writepage %p page %p index %lu on %llu~%u snapc %p\n", | 492 | dout("writepage %p page %p index %lu on %llu~%u snapc %p\n", |
| 487 | inode, page, page->index, page_off, len, snapc); | 493 | inode, page, page->index, page_off, len, snapc); |
| @@ -495,7 +501,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) | |||
| 495 | err = ceph_osdc_writepages(osdc, ceph_vino(inode), | 501 | err = ceph_osdc_writepages(osdc, ceph_vino(inode), |
| 496 | &ci->i_layout, snapc, | 502 | &ci->i_layout, snapc, |
| 497 | page_off, len, | 503 | page_off, len, |
| 498 | ci->i_truncate_seq, ci->i_truncate_size, | 504 | truncate_seq, truncate_size, |
| 499 | &inode->i_mtime, &page, 1); | 505 | &inode->i_mtime, &page, 1); |
| 500 | if (err < 0) { | 506 | if (err < 0) { |
| 501 | dout("writepage setting page/mapping error %d %p\n", err, page); | 507 | dout("writepage setting page/mapping error %d %p\n", err, page); |
| @@ -632,25 +638,6 @@ static void writepages_finish(struct ceph_osd_request *req, | |||
| 632 | ceph_osdc_put_request(req); | 638 | ceph_osdc_put_request(req); |
| 633 | } | 639 | } |
| 634 | 640 | ||
| 635 | static struct ceph_osd_request * | ||
| 636 | ceph_writepages_osd_request(struct inode *inode, u64 offset, u64 *len, | ||
| 637 | struct ceph_snap_context *snapc, int num_ops) | ||
| 638 | { | ||
| 639 | struct ceph_fs_client *fsc; | ||
| 640 | struct ceph_inode_info *ci; | ||
| 641 | struct ceph_vino vino; | ||
| 642 | |||
| 643 | fsc = ceph_inode_to_client(inode); | ||
| 644 | ci = ceph_inode(inode); | ||
| 645 | vino = ceph_vino(inode); | ||
| 646 | /* BUG_ON(vino.snap != CEPH_NOSNAP); */ | ||
| 647 | |||
| 648 | return ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, | ||
| 649 | vino, offset, len, num_ops, CEPH_OSD_OP_WRITE, | ||
| 650 | CEPH_OSD_FLAG_WRITE|CEPH_OSD_FLAG_ONDISK, | ||
| 651 | snapc, ci->i_truncate_seq, ci->i_truncate_size, true); | ||
| 652 | } | ||
| 653 | |||
| 654 | /* | 641 | /* |
| 655 | * initiate async writeback | 642 | * initiate async writeback |
| 656 | */ | 643 | */ |
| @@ -659,7 +646,8 @@ static int ceph_writepages_start(struct address_space *mapping, | |||
| 659 | { | 646 | { |
| 660 | struct inode *inode = mapping->host; | 647 | struct inode *inode = mapping->host; |
| 661 | struct ceph_inode_info *ci = ceph_inode(inode); | 648 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 662 | struct ceph_fs_client *fsc; | 649 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
| 650 | struct ceph_vino vino = ceph_vino(inode); | ||
| 663 | pgoff_t index, start, end; | 651 | pgoff_t index, start, end; |
| 664 | int range_whole = 0; | 652 | int range_whole = 0; |
| 665 | int should_loop = 1; | 653 | int should_loop = 1; |
| @@ -671,22 +659,22 @@ static int ceph_writepages_start(struct address_space *mapping, | |||
| 671 | unsigned wsize = 1 << inode->i_blkbits; | 659 | unsigned wsize = 1 << inode->i_blkbits; |
| 672 | struct ceph_osd_request *req = NULL; | 660 | struct ceph_osd_request *req = NULL; |
| 673 | int do_sync; | 661 | int do_sync; |
| 674 | u64 snap_size; | 662 | u64 truncate_size, snap_size; |
| 663 | u32 truncate_seq; | ||
| 675 | 664 | ||
| 676 | /* | 665 | /* |
| 677 | * Include a 'sync' in the OSD request if this is a data | 666 | * Include a 'sync' in the OSD request if this is a data |
| 678 | * integrity write (e.g., O_SYNC write or fsync()), or if our | 667 | * integrity write (e.g., O_SYNC write or fsync()), or if our |
| 679 | * cap is being revoked. | 668 | * cap is being revoked. |
| 680 | */ | 669 | */ |
| 681 | do_sync = wbc->sync_mode == WB_SYNC_ALL; | 670 | if ((wbc->sync_mode == WB_SYNC_ALL) || |
| 682 | if (ceph_caps_revoking(ci, CEPH_CAP_FILE_BUFFER)) | 671 | ceph_caps_revoking(ci, CEPH_CAP_FILE_BUFFER)) |
| 683 | do_sync = 1; | 672 | do_sync = 1; |
| 684 | dout("writepages_start %p dosync=%d (mode=%s)\n", | 673 | dout("writepages_start %p dosync=%d (mode=%s)\n", |
| 685 | inode, do_sync, | 674 | inode, do_sync, |
| 686 | wbc->sync_mode == WB_SYNC_NONE ? "NONE" : | 675 | wbc->sync_mode == WB_SYNC_NONE ? "NONE" : |
| 687 | (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD")); | 676 | (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD")); |
| 688 | 677 | ||
| 689 | fsc = ceph_inode_to_client(inode); | ||
| 690 | if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) { | 678 | if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) { |
| 691 | pr_warning("writepage_start %p on forced umount\n", inode); | 679 | pr_warning("writepage_start %p on forced umount\n", inode); |
| 692 | return -EIO; /* we're in a forced umount, don't write! */ | 680 | return -EIO; /* we're in a forced umount, don't write! */ |
| @@ -729,6 +717,14 @@ retry: | |||
| 729 | snap_size = i_size_read(inode); | 717 | snap_size = i_size_read(inode); |
| 730 | dout(" oldest snapc is %p seq %lld (%d snaps)\n", | 718 | dout(" oldest snapc is %p seq %lld (%d snaps)\n", |
| 731 | snapc, snapc->seq, snapc->num_snaps); | 719 | snapc, snapc->seq, snapc->num_snaps); |
| 720 | |||
| 721 | spin_lock(&ci->i_ceph_lock); | ||
| 722 | truncate_seq = ci->i_truncate_seq; | ||
| 723 | truncate_size = ci->i_truncate_size; | ||
| 724 | if (!snap_size) | ||
| 725 | snap_size = i_size_read(inode); | ||
| 726 | spin_unlock(&ci->i_ceph_lock); | ||
| 727 | |||
| 732 | if (last_snapc && snapc != last_snapc) { | 728 | if (last_snapc && snapc != last_snapc) { |
| 733 | /* if we switched to a newer snapc, restart our scan at the | 729 | /* if we switched to a newer snapc, restart our scan at the |
| 734 | * start of the original file range. */ | 730 | * start of the original file range. */ |
| @@ -740,7 +736,6 @@ retry: | |||
| 740 | 736 | ||
| 741 | while (!done && index <= end) { | 737 | while (!done && index <= end) { |
| 742 | int num_ops = do_sync ? 2 : 1; | 738 | int num_ops = do_sync ? 2 : 1; |
| 743 | struct ceph_vino vino; | ||
| 744 | unsigned i; | 739 | unsigned i; |
| 745 | int first; | 740 | int first; |
| 746 | pgoff_t next; | 741 | pgoff_t next; |
| @@ -834,17 +829,18 @@ get_more_pages: | |||
| 834 | * that it will use. | 829 | * that it will use. |
| 835 | */ | 830 | */ |
| 836 | if (locked_pages == 0) { | 831 | if (locked_pages == 0) { |
| 837 | size_t size; | ||
| 838 | |||
| 839 | BUG_ON(pages); | 832 | BUG_ON(pages); |
| 840 | |||
| 841 | /* prepare async write request */ | 833 | /* prepare async write request */ |
| 842 | offset = (u64)page_offset(page); | 834 | offset = (u64)page_offset(page); |
| 843 | len = wsize; | 835 | len = wsize; |
| 844 | req = ceph_writepages_osd_request(inode, | 836 | req = ceph_osdc_new_request(&fsc->client->osdc, |
| 845 | offset, &len, snapc, | 837 | &ci->i_layout, vino, |
| 846 | num_ops); | 838 | offset, &len, num_ops, |
| 847 | 839 | CEPH_OSD_OP_WRITE, | |
| 840 | CEPH_OSD_FLAG_WRITE | | ||
| 841 | CEPH_OSD_FLAG_ONDISK, | ||
| 842 | snapc, truncate_seq, | ||
| 843 | truncate_size, true); | ||
| 848 | if (IS_ERR(req)) { | 844 | if (IS_ERR(req)) { |
| 849 | rc = PTR_ERR(req); | 845 | rc = PTR_ERR(req); |
| 850 | unlock_page(page); | 846 | unlock_page(page); |
| @@ -855,8 +851,8 @@ get_more_pages: | |||
| 855 | req->r_inode = inode; | 851 | req->r_inode = inode; |
| 856 | 852 | ||
| 857 | max_pages = calc_pages_for(0, (u64)len); | 853 | max_pages = calc_pages_for(0, (u64)len); |
| 858 | size = max_pages * sizeof (*pages); | 854 | pages = kmalloc(max_pages * sizeof (*pages), |
| 859 | pages = kmalloc(size, GFP_NOFS); | 855 | GFP_NOFS); |
| 860 | if (!pages) { | 856 | if (!pages) { |
| 861 | pool = fsc->wb_pagevec_pool; | 857 | pool = fsc->wb_pagevec_pool; |
| 862 | pages = mempool_alloc(pool, GFP_NOFS); | 858 | pages = mempool_alloc(pool, GFP_NOFS); |
