diff options
-rw-r--r-- | fs/ceph/addr.c | 59 | ||||
-rw-r--r-- | include/linux/ceph/osd_client.h | 1 | ||||
-rw-r--r-- | net/ceph/osd_client.c | 13 |
3 files changed, 47 insertions, 26 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 0a3d2ce89660..5d8ce79385ed 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -737,10 +737,14 @@ retry: | |||
737 | 737 | ||
738 | while (!done && index <= end) { | 738 | while (!done && index <= end) { |
739 | struct ceph_osd_req_op ops[2]; | 739 | struct ceph_osd_req_op ops[2]; |
740 | int num_ops = do_sync ? 2 : 1; | ||
741 | struct ceph_vino vino; | ||
740 | unsigned i; | 742 | unsigned i; |
741 | int first; | 743 | int first; |
742 | pgoff_t next; | 744 | pgoff_t next; |
743 | int pvec_pages, locked_pages; | 745 | int pvec_pages, locked_pages; |
746 | struct page **pages = NULL; | ||
747 | mempool_t *pool = NULL; /* Becomes non-null if mempool used */ | ||
744 | struct page *page; | 748 | struct page *page; |
745 | int want; | 749 | int want; |
746 | u64 offset, len; | 750 | u64 offset, len; |
@@ -824,16 +828,19 @@ get_more_pages: | |||
824 | break; | 828 | break; |
825 | } | 829 | } |
826 | 830 | ||
827 | /* ok */ | 831 | /* |
832 | * We have something to write. If this is | ||
833 | * the first locked page this time through, | ||
834 | * allocate an osd request and a page array | ||
835 | * that it will use. | ||
836 | */ | ||
828 | if (locked_pages == 0) { | 837 | if (locked_pages == 0) { |
829 | struct ceph_vino vino; | ||
830 | int num_ops = do_sync ? 2 : 1; | ||
831 | size_t size; | 838 | size_t size; |
832 | struct page **pages; | 839 | |
833 | mempool_t *pool = NULL; | 840 | BUG_ON(pages); |
834 | 841 | ||
835 | /* prepare async write request */ | 842 | /* prepare async write request */ |
836 | offset = (u64) page_offset(page); | 843 | offset = (u64)page_offset(page); |
837 | len = wsize; | 844 | len = wsize; |
838 | req = ceph_writepages_osd_request(inode, | 845 | req = ceph_writepages_osd_request(inode, |
839 | offset, &len, snapc, | 846 | offset, &len, snapc, |
@@ -845,11 +852,6 @@ get_more_pages: | |||
845 | break; | 852 | break; |
846 | } | 853 | } |
847 | 854 | ||
848 | vino = ceph_vino(inode); | ||
849 | ceph_osdc_build_request(req, offset, | ||
850 | num_ops, ops, snapc, vino.snap, | ||
851 | &inode->i_mtime); | ||
852 | |||
853 | req->r_callback = writepages_finish; | 855 | req->r_callback = writepages_finish; |
854 | req->r_inode = inode; | 856 | req->r_inode = inode; |
855 | 857 | ||
@@ -858,16 +860,9 @@ get_more_pages: | |||
858 | pages = kmalloc(size, GFP_NOFS); | 860 | pages = kmalloc(size, GFP_NOFS); |
859 | if (!pages) { | 861 | if (!pages) { |
860 | pool = fsc->wb_pagevec_pool; | 862 | pool = fsc->wb_pagevec_pool; |
861 | |||
862 | pages = mempool_alloc(pool, GFP_NOFS); | 863 | pages = mempool_alloc(pool, GFP_NOFS); |
863 | WARN_ON(!pages); | 864 | BUG_ON(!pages); |
864 | } | 865 | } |
865 | |||
866 | req->r_data_out.pages = pages; | ||
867 | req->r_data_out.pages_from_pool = !!pool; | ||
868 | req->r_data_out.type = CEPH_OSD_DATA_TYPE_PAGES; | ||
869 | req->r_data_out.length = len; | ||
870 | req->r_data_out.alignment = 0; | ||
871 | } | 866 | } |
872 | 867 | ||
873 | /* note position of first page in pvec */ | 868 | /* note position of first page in pvec */ |
@@ -885,7 +880,7 @@ get_more_pages: | |||
885 | } | 880 | } |
886 | 881 | ||
887 | set_page_writeback(page); | 882 | set_page_writeback(page); |
888 | req->r_data_out.pages[locked_pages] = page; | 883 | pages[locked_pages] = page; |
889 | locked_pages++; | 884 | locked_pages++; |
890 | next = page->index + 1; | 885 | next = page->index + 1; |
891 | } | 886 | } |
@@ -914,18 +909,30 @@ get_more_pages: | |||
914 | pvec.nr -= i-first; | 909 | pvec.nr -= i-first; |
915 | } | 910 | } |
916 | 911 | ||
917 | /* submit the write */ | 912 | /* Format the osd request message and submit the write */ |
918 | offset = page_offset(req->r_data_out.pages[0]); | 913 | |
914 | offset = page_offset(pages[0]); | ||
919 | len = min((snap_size ? snap_size : i_size_read(inode)) - offset, | 915 | len = min((snap_size ? snap_size : i_size_read(inode)) - offset, |
920 | (u64)locked_pages << PAGE_CACHE_SHIFT); | 916 | (u64)locked_pages << PAGE_CACHE_SHIFT); |
921 | dout("writepages got %d pages at %llu~%llu\n", | 917 | dout("writepages got %d pages at %llu~%llu\n", |
922 | locked_pages, offset, len); | 918 | locked_pages, offset, len); |
923 | 919 | ||
924 | /* revise final length, page count */ | 920 | req->r_data_out.type = CEPH_OSD_DATA_TYPE_PAGES; |
921 | req->r_data_out.pages = pages; | ||
925 | req->r_data_out.length = len; | 922 | req->r_data_out.length = len; |
926 | req->r_request_ops[0].extent.length = cpu_to_le64(len); | 923 | req->r_data_out.alignment = 0; |
927 | req->r_request_ops[0].payload_len = cpu_to_le32(len); | 924 | req->r_data_out.pages_from_pool = !!pool; |
928 | req->r_request->hdr.data_len = cpu_to_le32(len); | 925 | |
926 | pages = NULL; /* request message now owns the pages array */ | ||
927 | pool = NULL; | ||
928 | |||
929 | /* Update the write op length in case we changed it */ | ||
930 | |||
931 | osd_req_op_extent_update(&ops[0], len); | ||
932 | |||
933 | vino = ceph_vino(inode); | ||
934 | ceph_osdc_build_request(req, offset, num_ops, ops, | ||
935 | snapc, vino.snap, &inode->i_mtime); | ||
929 | 936 | ||
930 | rc = ceph_osdc_start_request(&fsc->client->osdc, req, true); | 937 | rc = ceph_osdc_start_request(&fsc->client->osdc, req, true); |
931 | BUG_ON(rc); | 938 | BUG_ON(rc); |
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index ffaf9076fdc4..5ee1a3776b4b 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h | |||
@@ -234,6 +234,7 @@ extern void osd_req_op_init(struct ceph_osd_req_op *op, u16 opcode); | |||
234 | extern void osd_req_op_extent_init(struct ceph_osd_req_op *op, u16 opcode, | 234 | extern void osd_req_op_extent_init(struct ceph_osd_req_op *op, u16 opcode, |
235 | u64 offset, u64 length, | 235 | u64 offset, u64 length, |
236 | u64 truncate_size, u32 truncate_seq); | 236 | u64 truncate_size, u32 truncate_seq); |
237 | extern void osd_req_op_extent_update(struct ceph_osd_req_op *op, u64 length); | ||
237 | extern void osd_req_op_cls_init(struct ceph_osd_req_op *op, u16 opcode, | 238 | extern void osd_req_op_cls_init(struct ceph_osd_req_op *op, u16 opcode, |
238 | const char *class, const char *method, | 239 | const char *class, const char *method, |
239 | const void *request_data, | 240 | const void *request_data, |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 9ca693d0df19..426ca1f2a721 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -296,6 +296,19 @@ void osd_req_op_extent_init(struct ceph_osd_req_op *op, u16 opcode, | |||
296 | } | 296 | } |
297 | EXPORT_SYMBOL(osd_req_op_extent_init); | 297 | EXPORT_SYMBOL(osd_req_op_extent_init); |
298 | 298 | ||
299 | void osd_req_op_extent_update(struct ceph_osd_req_op *op, u64 length) | ||
300 | { | ||
301 | u64 previous = op->extent.length; | ||
302 | |||
303 | if (length == previous) | ||
304 | return; /* Nothing to do */ | ||
305 | BUG_ON(length > previous); | ||
306 | |||
307 | op->extent.length = length; | ||
308 | op->payload_len -= previous - length; | ||
309 | } | ||
310 | EXPORT_SYMBOL(osd_req_op_extent_update); | ||
311 | |||
299 | void osd_req_op_cls_init(struct ceph_osd_req_op *op, u16 opcode, | 312 | void osd_req_op_cls_init(struct ceph_osd_req_op *op, u16 opcode, |
300 | const char *class, const char *method, | 313 | const char *class, const char *method, |
301 | const void *request_data, size_t request_data_size) | 314 | const void *request_data, size_t request_data_size) |