aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-04-03 22:32:51 -0400
committerSage Weil <sage@inktank.com>2013-05-02 00:18:12 -0400
commit79528734f3ae4699a2886f62f55e18fb34fb3651 (patch)
tree51905378486b592fc2d4037d67ef3b577fe4eaa7
parent430c28c3cb7f3dbd87de266ed52d65928957ff78 (diff)
libceph: keep source rather than message osd op array
An osd request keeps a pointer to the osd operations (ops) array that it builds in its request message. In order to allow each op in the array to have its own distinct data, we will need to keep track of each op's data, and that information does not go over the wire. As long as we're tracking the data we might as well just track the entire (source) op definition for each of the ops. And if we're doing that, we'll have no more need to keep a pointer to the wire-encoded version. This patch makes the array of source ops be kept with the osd request structure, and uses that instead of the version encoded in the message in places where that was previously used. The array will be embedded in the request structure, and the maximum number of ops we ever actually use is currently 2. So reduce CEPH_OSD_MAX_OP to 2 to reduce the size of the structure. The result of doing this sort of ripples back up, and as a result various function parameters and local variables become unnecessary. Make r_num_ops be unsigned, and move the definition of struct ceph_osd_req_op earlier to ensure it's defined where needed. It does not yet add per-op data, that's coming soon. This resolves: http://tracker.ceph.com/issues/4656 Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r--drivers/block/rbd.c42
-rw-r--r--fs/ceph/addr.c21
-rw-r--r--fs/ceph/file.c6
-rw-r--r--include/linux/ceph/osd_client.h70
-rw-r--r--net/ceph/debugfs.c4
-rw-r--r--net/ceph/osd_client.c53
6 files changed, 97 insertions, 99 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 4a4be14a9189..c12b55559f16 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1285,7 +1285,7 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
1285 */ 1285 */
1286 obj_request->xferred = osd_req->r_reply_op_len[0]; 1286 obj_request->xferred = osd_req->r_reply_op_len[0];
1287 rbd_assert(obj_request->xferred < (u64) UINT_MAX); 1287 rbd_assert(obj_request->xferred < (u64) UINT_MAX);
1288 opcode = osd_req->r_request_ops[0].op; 1288 opcode = osd_req->r_ops[0].op;
1289 switch (opcode) { 1289 switch (opcode) {
1290 case CEPH_OSD_OP_READ: 1290 case CEPH_OSD_OP_READ:
1291 rbd_osd_read_callback(obj_request); 1291 rbd_osd_read_callback(obj_request);
@@ -1312,8 +1312,7 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
1312} 1312}
1313 1313
1314static void rbd_osd_req_format_op(struct rbd_obj_request *obj_request, 1314static void rbd_osd_req_format_op(struct rbd_obj_request *obj_request,
1315 bool write_request, 1315 bool write_request)
1316 struct ceph_osd_req_op *op)
1317{ 1316{
1318 struct rbd_img_request *img_request = obj_request->img_request; 1317 struct rbd_img_request *img_request = obj_request->img_request;
1319 struct ceph_snap_context *snapc = NULL; 1318 struct ceph_snap_context *snapc = NULL;
@@ -1333,7 +1332,7 @@ static void rbd_osd_req_format_op(struct rbd_obj_request *obj_request,
1333 } 1332 }
1334 1333
1335 ceph_osdc_build_request(obj_request->osd_req, obj_request->offset, 1334 ceph_osdc_build_request(obj_request->osd_req, obj_request->offset,
1336 1, op, snapc, snap_id, mtime); 1335 snapc, snap_id, mtime);
1337} 1336}
1338 1337
1339static struct ceph_osd_request *rbd_osd_req_create( 1338static struct ceph_osd_request *rbd_osd_req_create(
@@ -1562,7 +1561,7 @@ static int rbd_img_request_fill_bio(struct rbd_img_request *img_request,
1562 while (resid) { 1561 while (resid) {
1563 const char *object_name; 1562 const char *object_name;
1564 unsigned int clone_size; 1563 unsigned int clone_size;
1565 struct ceph_osd_req_op op; 1564 struct ceph_osd_req_op *op;
1566 u64 offset; 1565 u64 offset;
1567 u64 length; 1566 u64 length;
1568 1567
@@ -1591,8 +1590,9 @@ static int rbd_img_request_fill_bio(struct rbd_img_request *img_request,
1591 if (!obj_request->osd_req) 1590 if (!obj_request->osd_req)
1592 goto out_partial; 1591 goto out_partial;
1593 1592
1594 osd_req_op_extent_init(&op, opcode, offset, length, 0, 0); 1593 op = &obj_request->osd_req->r_ops[0];
1595 rbd_osd_req_format_op(obj_request, write_request, &op); 1594 osd_req_op_extent_init(op, opcode, offset, length, 0, 0);
1595 rbd_osd_req_format_op(obj_request, write_request);
1596 1596
1597 /* status and version are initially zero-filled */ 1597 /* status and version are initially zero-filled */
1598 1598
@@ -1694,7 +1694,7 @@ static int rbd_obj_notify_ack(struct rbd_device *rbd_dev,
1694 u64 ver, u64 notify_id) 1694 u64 ver, u64 notify_id)
1695{ 1695{
1696 struct rbd_obj_request *obj_request; 1696 struct rbd_obj_request *obj_request;
1697 struct ceph_osd_req_op op; 1697 struct ceph_osd_req_op *op;
1698 struct ceph_osd_client *osdc; 1698 struct ceph_osd_client *osdc;
1699 int ret; 1699 int ret;
1700 1700
@@ -1708,8 +1708,9 @@ static int rbd_obj_notify_ack(struct rbd_device *rbd_dev,
1708 if (!obj_request->osd_req) 1708 if (!obj_request->osd_req)
1709 goto out; 1709 goto out;
1710 1710
1711 osd_req_op_watch_init(&op, CEPH_OSD_OP_NOTIFY_ACK, notify_id, ver, 0); 1711 op = &obj_request->osd_req->r_ops[0];
1712 rbd_osd_req_format_op(obj_request, false, &op); 1712 osd_req_op_watch_init(op, CEPH_OSD_OP_NOTIFY_ACK, notify_id, ver, 0);
1713 rbd_osd_req_format_op(obj_request, false);
1713 1714
1714 osdc = &rbd_dev->rbd_client->client->osdc; 1715 osdc = &rbd_dev->rbd_client->client->osdc;
1715 obj_request->callback = rbd_obj_request_put; 1716 obj_request->callback = rbd_obj_request_put;
@@ -1749,7 +1750,7 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start)
1749{ 1750{
1750 struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; 1751 struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
1751 struct rbd_obj_request *obj_request; 1752 struct rbd_obj_request *obj_request;
1752 struct ceph_osd_req_op op; 1753 struct ceph_osd_req_op *op;
1753 int ret; 1754 int ret;
1754 1755
1755 rbd_assert(start ^ !!rbd_dev->watch_event); 1756 rbd_assert(start ^ !!rbd_dev->watch_event);
@@ -1773,10 +1774,11 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start)
1773 if (!obj_request->osd_req) 1774 if (!obj_request->osd_req)
1774 goto out_cancel; 1775 goto out_cancel;
1775 1776
1776 osd_req_op_watch_init(&op, CEPH_OSD_OP_WATCH, 1777 op = &obj_request->osd_req->r_ops[0];
1778 osd_req_op_watch_init(op, CEPH_OSD_OP_WATCH,
1777 rbd_dev->watch_event->cookie, 1779 rbd_dev->watch_event->cookie,
1778 rbd_dev->header.obj_version, start); 1780 rbd_dev->header.obj_version, start);
1779 rbd_osd_req_format_op(obj_request, true, &op); 1781 rbd_osd_req_format_op(obj_request, true);
1780 1782
1781 if (start) 1783 if (start)
1782 ceph_osdc_set_request_linger(osdc, obj_request->osd_req); 1784 ceph_osdc_set_request_linger(osdc, obj_request->osd_req);
@@ -1836,7 +1838,7 @@ static int rbd_obj_method_sync(struct rbd_device *rbd_dev,
1836{ 1838{
1837 struct rbd_obj_request *obj_request; 1839 struct rbd_obj_request *obj_request;
1838 struct ceph_osd_client *osdc; 1840 struct ceph_osd_client *osdc;
1839 struct ceph_osd_req_op op; 1841 struct ceph_osd_req_op *op;
1840 struct page **pages; 1842 struct page **pages;
1841 u32 page_count; 1843 u32 page_count;
1842 int ret; 1844 int ret;
@@ -1866,9 +1868,10 @@ static int rbd_obj_method_sync(struct rbd_device *rbd_dev,
1866 if (!obj_request->osd_req) 1868 if (!obj_request->osd_req)
1867 goto out; 1869 goto out;
1868 1870
1869 osd_req_op_cls_init(&op, CEPH_OSD_OP_CALL, class_name, method_name, 1871 op = &obj_request->osd_req->r_ops[0];
1872 osd_req_op_cls_init(op, CEPH_OSD_OP_CALL, class_name, method_name,
1870 outbound, outbound_size); 1873 outbound, outbound_size);
1871 rbd_osd_req_format_op(obj_request, false, &op); 1874 rbd_osd_req_format_op(obj_request, false);
1872 1875
1873 osdc = &rbd_dev->rbd_client->client->osdc; 1876 osdc = &rbd_dev->rbd_client->client->osdc;
1874 ret = rbd_obj_request_submit(osdc, obj_request); 1877 ret = rbd_obj_request_submit(osdc, obj_request);
@@ -2046,8 +2049,8 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev,
2046 char *buf, u64 *version) 2049 char *buf, u64 *version)
2047 2050
2048{ 2051{
2049 struct ceph_osd_req_op op;
2050 struct rbd_obj_request *obj_request; 2052 struct rbd_obj_request *obj_request;
2053 struct ceph_osd_req_op *op;
2051 struct ceph_osd_client *osdc; 2054 struct ceph_osd_client *osdc;
2052 struct page **pages = NULL; 2055 struct page **pages = NULL;
2053 u32 page_count; 2056 u32 page_count;
@@ -2072,8 +2075,9 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev,
2072 if (!obj_request->osd_req) 2075 if (!obj_request->osd_req)
2073 goto out; 2076 goto out;
2074 2077
2075 osd_req_op_extent_init(&op, CEPH_OSD_OP_READ, offset, length, 0, 0); 2078 op = &obj_request->osd_req->r_ops[0];
2076 rbd_osd_req_format_op(obj_request, false, &op); 2079 osd_req_op_extent_init(op, CEPH_OSD_OP_READ, offset, length, 0, 0);
2080 rbd_osd_req_format_op(obj_request, false);
2077 2081
2078 osdc = &rbd_dev->rbd_client->client->osdc; 2082 osdc = &rbd_dev->rbd_client->client->osdc;
2079 ret = rbd_obj_request_submit(osdc, obj_request); 2083 ret = rbd_obj_request_submit(osdc, obj_request);
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 127be29a6c22..c9da074f0fe6 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -288,7 +288,6 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
288 struct page *page = list_entry(page_list->prev, struct page, lru); 288 struct page *page = list_entry(page_list->prev, struct page, lru);
289 struct ceph_vino vino; 289 struct ceph_vino vino;
290 struct ceph_osd_request *req; 290 struct ceph_osd_request *req;
291 struct ceph_osd_req_op op;
292 u64 off; 291 u64 off;
293 u64 len; 292 u64 len;
294 int i; 293 int i;
@@ -314,7 +313,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
314 off, len); 313 off, len);
315 vino = ceph_vino(inode); 314 vino = ceph_vino(inode);
316 req = ceph_osdc_new_request(osdc, &ci->i_layout, vino, off, &len, 315 req = ceph_osdc_new_request(osdc, &ci->i_layout, vino, off, &len,
317 1, &op, CEPH_OSD_OP_READ, 316 1, CEPH_OSD_OP_READ,
318 CEPH_OSD_FLAG_READ, NULL, 317 CEPH_OSD_FLAG_READ, NULL,
319 ci->i_truncate_seq, ci->i_truncate_size, 318 ci->i_truncate_seq, ci->i_truncate_size,
320 false); 319 false);
@@ -349,7 +348,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
349 req->r_callback = finish_read; 348 req->r_callback = finish_read;
350 req->r_inode = inode; 349 req->r_inode = inode;
351 350
352 ceph_osdc_build_request(req, off, 1, &op, NULL, vino.snap, NULL); 351 ceph_osdc_build_request(req, off, NULL, vino.snap, NULL);
353 352
354 dout("start_read %p starting %p %lld~%lld\n", inode, req, off, len); 353 dout("start_read %p starting %p %lld~%lld\n", inode, req, off, len);
355 ret = ceph_osdc_start_request(osdc, req, false); 354 ret = ceph_osdc_start_request(osdc, req, false);
@@ -567,7 +566,7 @@ static void writepages_finish(struct ceph_osd_request *req,
567 struct ceph_snap_context *snapc = req->r_snapc; 566 struct ceph_snap_context *snapc = req->r_snapc;
568 struct address_space *mapping = inode->i_mapping; 567 struct address_space *mapping = inode->i_mapping;
569 int rc = req->r_result; 568 int rc = req->r_result;
570 u64 bytes = le64_to_cpu(req->r_request_ops[0].extent.length); 569 u64 bytes = req->r_ops[0].extent.length;
571 struct ceph_fs_client *fsc = ceph_inode_to_client(inode); 570 struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
572 long writeback_stat; 571 long writeback_stat;
573 unsigned issued = ceph_caps_issued(ci); 572 unsigned issued = ceph_caps_issued(ci);
@@ -635,8 +634,7 @@ static void writepages_finish(struct ceph_osd_request *req,
635 634
636static struct ceph_osd_request * 635static struct ceph_osd_request *
637ceph_writepages_osd_request(struct inode *inode, u64 offset, u64 *len, 636ceph_writepages_osd_request(struct inode *inode, u64 offset, u64 *len,
638 struct ceph_snap_context *snapc, 637 struct ceph_snap_context *snapc, int num_ops)
639 int num_ops, struct ceph_osd_req_op *ops)
640{ 638{
641 struct ceph_fs_client *fsc; 639 struct ceph_fs_client *fsc;
642 struct ceph_inode_info *ci; 640 struct ceph_inode_info *ci;
@@ -648,7 +646,7 @@ ceph_writepages_osd_request(struct inode *inode, u64 offset, u64 *len,
648 /* BUG_ON(vino.snap != CEPH_NOSNAP); */ 646 /* BUG_ON(vino.snap != CEPH_NOSNAP); */
649 647
650 return ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, 648 return ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
651 vino, offset, len, num_ops, ops, CEPH_OSD_OP_WRITE, 649 vino, offset, len, num_ops, CEPH_OSD_OP_WRITE,
652 CEPH_OSD_FLAG_WRITE|CEPH_OSD_FLAG_ONDISK, 650 CEPH_OSD_FLAG_WRITE|CEPH_OSD_FLAG_ONDISK,
653 snapc, ci->i_truncate_seq, ci->i_truncate_size, true); 651 snapc, ci->i_truncate_seq, ci->i_truncate_size, true);
654} 652}
@@ -738,7 +736,6 @@ retry:
738 last_snapc = snapc; 736 last_snapc = snapc;
739 737
740 while (!done && index <= end) { 738 while (!done && index <= end) {
741 struct ceph_osd_req_op ops[2];
742 int num_ops = do_sync ? 2 : 1; 739 int num_ops = do_sync ? 2 : 1;
743 struct ceph_vino vino; 740 struct ceph_vino vino;
744 unsigned i; 741 unsigned i;
@@ -846,7 +843,7 @@ get_more_pages:
846 len = wsize; 843 len = wsize;
847 req = ceph_writepages_osd_request(inode, 844 req = ceph_writepages_osd_request(inode,
848 offset, &len, snapc, 845 offset, &len, snapc,
849 num_ops, ops); 846 num_ops);
850 847
851 if (IS_ERR(req)) { 848 if (IS_ERR(req)) {
852 rc = PTR_ERR(req); 849 rc = PTR_ERR(req);
@@ -927,11 +924,11 @@ get_more_pages:
927 924
928 /* Update the write op length in case we changed it */ 925 /* Update the write op length in case we changed it */
929 926
930 osd_req_op_extent_update(&ops[0], len); 927 osd_req_op_extent_update(&req->r_ops[0], len);
931 928
932 vino = ceph_vino(inode); 929 vino = ceph_vino(inode);
933 ceph_osdc_build_request(req, offset, num_ops, ops, 930 ceph_osdc_build_request(req, offset, snapc, vino.snap,
934 snapc, vino.snap, &inode->i_mtime); 931 &inode->i_mtime);
935 932
936 rc = ceph_osdc_start_request(&fsc->client->osdc, req, true); 933 rc = ceph_osdc_start_request(&fsc->client->osdc, req, true);
937 BUG_ON(rc); 934 BUG_ON(rc);
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index da642af14a28..a12f47642c40 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -478,7 +478,6 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
478 struct ceph_snap_context *snapc; 478 struct ceph_snap_context *snapc;
479 struct ceph_vino vino; 479 struct ceph_vino vino;
480 struct ceph_osd_request *req; 480 struct ceph_osd_request *req;
481 struct ceph_osd_req_op ops[2];
482 int num_ops = 1; 481 int num_ops = 1;
483 struct page **pages; 482 struct page **pages;
484 int num_pages; 483 int num_pages;
@@ -534,7 +533,7 @@ more:
534 snapc = ci->i_snap_realm->cached_context; 533 snapc = ci->i_snap_realm->cached_context;
535 vino = ceph_vino(inode); 534 vino = ceph_vino(inode);
536 req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, 535 req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
537 vino, pos, &len, num_ops, ops, 536 vino, pos, &len, num_ops,
538 CEPH_OSD_OP_WRITE, flags, snapc, 537 CEPH_OSD_OP_WRITE, flags, snapc,
539 ci->i_truncate_seq, ci->i_truncate_size, 538 ci->i_truncate_seq, ci->i_truncate_size,
540 false); 539 false);
@@ -579,8 +578,7 @@ more:
579 false, own_pages); 578 false, own_pages);
580 579
581 /* BUG_ON(vino.snap != CEPH_NOSNAP); */ 580 /* BUG_ON(vino.snap != CEPH_NOSNAP); */
582 ceph_osdc_build_request(req, pos, num_ops, ops, 581 ceph_osdc_build_request(req, pos, snapc, vino.snap, &mtime);
583 snapc, vino.snap, &mtime);
584 582
585 ret = ceph_osdc_start_request(&fsc->client->osdc, req, false); 583 ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
586 if (!ret) { 584 if (!ret) {
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index af60dac1f9c0..f4c1a2a22a14 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -48,7 +48,7 @@ struct ceph_osd {
48}; 48};
49 49
50 50
51#define CEPH_OSD_MAX_OP 10 51#define CEPH_OSD_MAX_OP 2
52 52
53enum ceph_osd_data_type { 53enum ceph_osd_data_type {
54 CEPH_OSD_DATA_TYPE_NONE, 54 CEPH_OSD_DATA_TYPE_NONE,
@@ -79,6 +79,34 @@ struct ceph_osd_data {
79 }; 79 };
80}; 80};
81 81
82struct ceph_osd_req_op {
83 u16 op; /* CEPH_OSD_OP_* */
84 u32 payload_len;
85 union {
86 struct {
87 u64 offset, length;
88 u64 truncate_size;
89 u32 truncate_seq;
90 } extent;
91 struct {
92 const char *class_name;
93 const char *method_name;
94 const void *indata;
95 u32 indata_len;
96 __u8 class_len;
97 __u8 method_len;
98 __u8 argc;
99 } cls;
100 struct {
101 u64 cookie;
102 u64 ver;
103 u32 prot_ver;
104 u32 timeout;
105 __u8 flag;
106 } watch;
107 };
108};
109
82/* an in-flight request */ 110/* an in-flight request */
83struct ceph_osd_request { 111struct ceph_osd_request {
84 u64 r_tid; /* unique for this client */ 112 u64 r_tid; /* unique for this client */
@@ -95,10 +123,11 @@ struct ceph_osd_request {
95 struct ceph_msg *r_request, *r_reply; 123 struct ceph_msg *r_request, *r_reply;
96 int r_flags; /* any additional flags for the osd */ 124 int r_flags; /* any additional flags for the osd */
97 u32 r_sent; /* >0 if r_request is sending/sent */ 125 u32 r_sent; /* >0 if r_request is sending/sent */
98 int r_num_ops;
99 126
100 /* encoded message content */ 127 /* request osd ops array */
101 struct ceph_osd_op *r_request_ops; 128 unsigned int r_num_ops;
129 struct ceph_osd_req_op r_ops[CEPH_OSD_MAX_OP];
130
102 /* these are updated on each send */ 131 /* these are updated on each send */
103 __le32 *r_request_osdmap_epoch; 132 __le32 *r_request_osdmap_epoch;
104 __le32 *r_request_flags; 133 __le32 *r_request_flags;
@@ -193,34 +222,6 @@ struct ceph_osd_client {
193 struct workqueue_struct *notify_wq; 222 struct workqueue_struct *notify_wq;
194}; 223};
195 224
196struct ceph_osd_req_op {
197 u16 op; /* CEPH_OSD_OP_* */
198 u32 payload_len;
199 union {
200 struct {
201 u64 offset, length;
202 u64 truncate_size;
203 u32 truncate_seq;
204 } extent;
205 struct {
206 const char *class_name;
207 const char *method_name;
208 const void *indata;
209 u32 indata_len;
210 __u8 class_len;
211 __u8 method_len;
212 __u8 argc;
213 } cls;
214 struct {
215 u64 cookie;
216 u64 ver;
217 u32 prot_ver;
218 u32 timeout;
219 __u8 flag;
220 } watch;
221 };
222};
223
224extern int ceph_osdc_init(struct ceph_osd_client *osdc, 225extern int ceph_osdc_init(struct ceph_osd_client *osdc,
225 struct ceph_client *client); 226 struct ceph_client *client);
226extern void ceph_osdc_stop(struct ceph_osd_client *osdc); 227extern void ceph_osdc_stop(struct ceph_osd_client *osdc);
@@ -249,8 +250,6 @@ extern struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *
249 gfp_t gfp_flags); 250 gfp_t gfp_flags);
250 251
251extern void ceph_osdc_build_request(struct ceph_osd_request *req, u64 off, 252extern void ceph_osdc_build_request(struct ceph_osd_request *req, u64 off,
252 unsigned int num_ops,
253 struct ceph_osd_req_op *src_ops,
254 struct ceph_snap_context *snapc, 253 struct ceph_snap_context *snapc,
255 u64 snap_id, 254 u64 snap_id,
256 struct timespec *mtime); 255 struct timespec *mtime);
@@ -259,8 +258,7 @@ extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *,
259 struct ceph_file_layout *layout, 258 struct ceph_file_layout *layout,
260 struct ceph_vino vino, 259 struct ceph_vino vino,
261 u64 offset, u64 *len, 260 u64 offset, u64 *len,
262 int num_ops, struct ceph_osd_req_op *ops, 261 int num_ops, int opcode, int flags,
263 int opcode, int flags,
264 struct ceph_snap_context *snapc, 262 struct ceph_snap_context *snapc,
265 u32 truncate_seq, u64 truncate_size, 263 u32 truncate_seq, u64 truncate_size,
266 bool use_mempool); 264 bool use_mempool);
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c
index 00d051f4894e..83661cdc0766 100644
--- a/net/ceph/debugfs.c
+++ b/net/ceph/debugfs.c
@@ -123,8 +123,8 @@ static int osdc_show(struct seq_file *s, void *pp)
123 mutex_lock(&osdc->request_mutex); 123 mutex_lock(&osdc->request_mutex);
124 for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { 124 for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
125 struct ceph_osd_request *req; 125 struct ceph_osd_request *req;
126 unsigned int i;
126 int opcode; 127 int opcode;
127 int i;
128 128
129 req = rb_entry(p, struct ceph_osd_request, r_node); 129 req = rb_entry(p, struct ceph_osd_request, r_node);
130 130
@@ -142,7 +142,7 @@ static int osdc_show(struct seq_file *s, void *pp)
142 seq_printf(s, "\t"); 142 seq_printf(s, "\t");
143 143
144 for (i = 0; i < req->r_num_ops; i++) { 144 for (i = 0; i < req->r_num_ops; i++) {
145 opcode = le16_to_cpu(req->r_request_ops[i].op); 145 opcode = req->r_ops[i].op;
146 seq_printf(s, "\t%s", ceph_osd_op_name(opcode)); 146 seq_printf(s, "\t%s", ceph_osd_op_name(opcode));
147 } 147 }
148 148
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index e197c5c0b3a2..a498d2de17a4 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -186,6 +186,9 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
186 struct ceph_msg *msg; 186 struct ceph_msg *msg;
187 size_t msg_size; 187 size_t msg_size;
188 188
189 BUILD_BUG_ON(CEPH_OSD_MAX_OP > U16_MAX);
190 BUG_ON(num_ops > CEPH_OSD_MAX_OP);
191
189 msg_size = 4 + 4 + 8 + 8 + 4+8; 192 msg_size = 4 + 4 + 8 + 8 + 4+8;
190 msg_size += 2 + 4 + 8 + 4 + 4; /* oloc */ 193 msg_size += 2 + 4 + 8 + 4 + 4; /* oloc */
191 msg_size += 1 + 8 + 4 + 4; /* pg_t */ 194 msg_size += 1 + 8 + 4 + 4; /* pg_t */
@@ -207,6 +210,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
207 210
208 req->r_osdc = osdc; 211 req->r_osdc = osdc;
209 req->r_mempool = use_mempool; 212 req->r_mempool = use_mempool;
213 req->r_num_ops = num_ops;
210 214
211 kref_init(&req->r_kref); 215 kref_init(&req->r_kref);
212 init_completion(&req->r_completion); 216 init_completion(&req->r_completion);
@@ -418,12 +422,14 @@ void osd_req_op_watch_init(struct ceph_osd_req_op *op, u16 opcode,
418EXPORT_SYMBOL(osd_req_op_watch_init); 422EXPORT_SYMBOL(osd_req_op_watch_init);
419 423
420static u64 osd_req_encode_op(struct ceph_osd_request *req, 424static u64 osd_req_encode_op(struct ceph_osd_request *req,
421 struct ceph_osd_op *dst, 425 struct ceph_osd_op *dst, unsigned int which)
422 struct ceph_osd_req_op *src)
423{ 426{
427 struct ceph_osd_req_op *src;
424 u64 out_data_len = 0; 428 u64 out_data_len = 0;
425 struct ceph_pagelist *pagelist; 429 struct ceph_pagelist *pagelist;
426 430
431 BUG_ON(which >= req->r_num_ops);
432 src = &req->r_ops[which];
427 if (WARN_ON(!osd_req_opcode_valid(src->op))) { 433 if (WARN_ON(!osd_req_opcode_valid(src->op))) {
428 pr_err("unrecognized osd opcode %d\n", src->op); 434 pr_err("unrecognized osd opcode %d\n", src->op);
429 435
@@ -487,21 +493,17 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req,
487 * build new request AND message 493 * build new request AND message
488 * 494 *
489 */ 495 */
490void ceph_osdc_build_request(struct ceph_osd_request *req, 496void ceph_osdc_build_request(struct ceph_osd_request *req, u64 off,
491 u64 off, unsigned int num_ops, 497 struct ceph_snap_context *snapc, u64 snap_id,
492 struct ceph_osd_req_op *src_ops, 498 struct timespec *mtime)
493 struct ceph_snap_context *snapc, u64 snap_id,
494 struct timespec *mtime)
495{ 499{
496 struct ceph_msg *msg = req->r_request; 500 struct ceph_msg *msg = req->r_request;
497 struct ceph_osd_req_op *src_op;
498 void *p; 501 void *p;
499 size_t msg_size; 502 size_t msg_size;
500 int flags = req->r_flags; 503 int flags = req->r_flags;
501 u64 data_len; 504 u64 data_len;
502 int i; 505 unsigned int i;
503 506
504 req->r_num_ops = num_ops;
505 req->r_snapid = snap_id; 507 req->r_snapid = snap_id;
506 req->r_snapc = ceph_get_snap_context(snapc); 508 req->r_snapc = ceph_get_snap_context(snapc);
507 509
@@ -541,12 +543,10 @@ void ceph_osdc_build_request(struct ceph_osd_request *req,
541 p += req->r_oid_len; 543 p += req->r_oid_len;
542 544
543 /* ops--can imply data */ 545 /* ops--can imply data */
544 ceph_encode_16(&p, num_ops); 546 ceph_encode_16(&p, (u16)req->r_num_ops);
545 src_op = src_ops;
546 req->r_request_ops = p;
547 data_len = 0; 547 data_len = 0;
548 for (i = 0; i < num_ops; i++, src_op++) { 548 for (i = 0; i < req->r_num_ops; i++) {
549 data_len += osd_req_encode_op(req, p, src_op); 549 data_len += osd_req_encode_op(req, p, i);
550 p += sizeof(struct ceph_osd_op); 550 p += sizeof(struct ceph_osd_op);
551 } 551 }
552 552
@@ -602,7 +602,6 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
602 struct ceph_file_layout *layout, 602 struct ceph_file_layout *layout,
603 struct ceph_vino vino, 603 struct ceph_vino vino,
604 u64 off, u64 *plen, int num_ops, 604 u64 off, u64 *plen, int num_ops,
605 struct ceph_osd_req_op *ops,
606 int opcode, int flags, 605 int opcode, int flags,
607 struct ceph_snap_context *snapc, 606 struct ceph_snap_context *snapc,
608 u32 truncate_seq, 607 u32 truncate_seq,
@@ -610,6 +609,7 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
610 bool use_mempool) 609 bool use_mempool)
611{ 610{
612 struct ceph_osd_request *req; 611 struct ceph_osd_request *req;
612 struct ceph_osd_req_op *op;
613 u64 objnum = 0; 613 u64 objnum = 0;
614 u64 objoff = 0; 614 u64 objoff = 0;
615 u64 objlen = 0; 615 u64 objlen = 0;
@@ -623,6 +623,7 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
623 GFP_NOFS); 623 GFP_NOFS);
624 if (!req) 624 if (!req)
625 return ERR_PTR(-ENOMEM); 625 return ERR_PTR(-ENOMEM);
626
626 req->r_flags = flags; 627 req->r_flags = flags;
627 628
628 /* calculate max write size */ 629 /* calculate max write size */
@@ -642,7 +643,8 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
642 truncate_size = object_size; 643 truncate_size = object_size;
643 } 644 }
644 645
645 osd_req_op_extent_init(&ops[0], opcode, objoff, objlen, 646 op = &req->r_ops[0];
647 osd_req_op_extent_init(op, opcode, objoff, objlen,
646 truncate_size, truncate_seq); 648 truncate_size, truncate_seq);
647 /* 649 /*
648 * A second op in the ops array means the caller wants to 650 * A second op in the ops array means the caller wants to
@@ -650,7 +652,7 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
650 * osd will flush data quickly. 652 * osd will flush data quickly.
651 */ 653 */
652 if (num_ops > 1) 654 if (num_ops > 1)
653 osd_req_op_init(&ops[1], CEPH_OSD_OP_STARTSYNC); 655 osd_req_op_init(++op, CEPH_OSD_OP_STARTSYNC);
654 656
655 req->r_file_layout = *layout; /* keep a copy */ 657 req->r_file_layout = *layout; /* keep a copy */
656 658
@@ -1342,7 +1344,8 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1342 struct ceph_osd_request *req; 1344 struct ceph_osd_request *req;
1343 u64 tid; 1345 u64 tid;
1344 int object_len; 1346 int object_len;
1345 int numops, payload_len, flags; 1347 unsigned int numops;
1348 int payload_len, flags;
1346 s32 result; 1349 s32 result;
1347 s32 retry_attempt; 1350 s32 retry_attempt;
1348 struct ceph_pg pg; 1351 struct ceph_pg pg;
@@ -1352,7 +1355,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
1352 u32 osdmap_epoch; 1355 u32 osdmap_epoch;
1353 int already_completed; 1356 int already_completed;
1354 u32 bytes; 1357 u32 bytes;
1355 int i; 1358 unsigned int i;
1356 1359
1357 tid = le64_to_cpu(msg->hdr.tid); 1360 tid = le64_to_cpu(msg->hdr.tid);
1358 dout("handle_reply %p tid %llu\n", msg, tid); 1361 dout("handle_reply %p tid %llu\n", msg, tid);
@@ -2116,12 +2119,11 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc,
2116 struct page **pages, int num_pages, int page_align) 2119 struct page **pages, int num_pages, int page_align)
2117{ 2120{
2118 struct ceph_osd_request *req; 2121 struct ceph_osd_request *req;
2119 struct ceph_osd_req_op op;
2120 int rc = 0; 2122 int rc = 0;
2121 2123
2122 dout("readpages on ino %llx.%llx on %llu~%llu\n", vino.ino, 2124 dout("readpages on ino %llx.%llx on %llu~%llu\n", vino.ino,
2123 vino.snap, off, *plen); 2125 vino.snap, off, *plen);
2124 req = ceph_osdc_new_request(osdc, layout, vino, off, plen, 1, &op, 2126 req = ceph_osdc_new_request(osdc, layout, vino, off, plen, 1,
2125 CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, 2127 CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ,
2126 NULL, truncate_seq, truncate_size, 2128 NULL, truncate_seq, truncate_size,
2127 false); 2129 false);
@@ -2136,7 +2138,7 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc,
2136 dout("readpages final extent is %llu~%llu (%llu bytes align %d)\n", 2138 dout("readpages final extent is %llu~%llu (%llu bytes align %d)\n",
2137 off, *plen, *plen, page_align); 2139 off, *plen, *plen, page_align);
2138 2140
2139 ceph_osdc_build_request(req, off, 1, &op, NULL, vino.snap, NULL); 2141 ceph_osdc_build_request(req, off, NULL, vino.snap, NULL);
2140 2142
2141 rc = ceph_osdc_start_request(osdc, req, false); 2143 rc = ceph_osdc_start_request(osdc, req, false);
2142 if (!rc) 2144 if (!rc)
@@ -2160,12 +2162,11 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
2160 struct page **pages, int num_pages) 2162 struct page **pages, int num_pages)
2161{ 2163{
2162 struct ceph_osd_request *req; 2164 struct ceph_osd_request *req;
2163 struct ceph_osd_req_op op;
2164 int rc = 0; 2165 int rc = 0;
2165 int page_align = off & ~PAGE_MASK; 2166 int page_align = off & ~PAGE_MASK;
2166 2167
2167 BUG_ON(vino.snap != CEPH_NOSNAP); /* snapshots aren't writeable */ 2168 BUG_ON(vino.snap != CEPH_NOSNAP); /* snapshots aren't writeable */
2168 req = ceph_osdc_new_request(osdc, layout, vino, off, &len, 1, &op, 2169 req = ceph_osdc_new_request(osdc, layout, vino, off, &len, 1,
2169 CEPH_OSD_OP_WRITE, 2170 CEPH_OSD_OP_WRITE,
2170 CEPH_OSD_FLAG_ONDISK | CEPH_OSD_FLAG_WRITE, 2171 CEPH_OSD_FLAG_ONDISK | CEPH_OSD_FLAG_WRITE,
2171 snapc, truncate_seq, truncate_size, 2172 snapc, truncate_seq, truncate_size,
@@ -2178,7 +2179,7 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
2178 false, false); 2179 false, false);
2179 dout("writepages %llu~%llu (%llu bytes)\n", off, len, len); 2180 dout("writepages %llu~%llu (%llu bytes)\n", off, len, len);
2180 2181
2181 ceph_osdc_build_request(req, off, 1, &op, snapc, CEPH_NOSNAP, mtime); 2182 ceph_osdc_build_request(req, off, snapc, CEPH_NOSNAP, mtime);
2182 2183
2183 rc = ceph_osdc_start_request(osdc, req, true); 2184 rc = ceph_osdc_start_request(osdc, req, true);
2184 if (!rc) 2185 if (!rc)