aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/addr.c59
-rw-r--r--include/linux/ceph/osd_client.h1
-rw-r--r--net/ceph/osd_client.c13
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);
234extern void osd_req_op_extent_init(struct ceph_osd_req_op *op, u16 opcode, 234extern 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);
237extern void osd_req_op_extent_update(struct ceph_osd_req_op *op, u64 length);
237extern void osd_req_op_cls_init(struct ceph_osd_req_op *op, u16 opcode, 238extern 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}
297EXPORT_SYMBOL(osd_req_op_extent_init); 297EXPORT_SYMBOL(osd_req_op_extent_init);
298 298
299void 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}
310EXPORT_SYMBOL(osd_req_op_extent_update);
311
299void osd_req_op_cls_init(struct ceph_osd_req_op *op, u16 opcode, 312void 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)