aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2016-02-09 11:50:15 -0500
committerIlya Dryomov <idryomov@gmail.com>2016-03-25 13:51:43 -0400
commit3f1af42ad0fad8a12242233dd0d9fc42f5e83415 (patch)
treeeabe7d5ed3f48fb23c2caa777a4436df67103b29 /net
parent9e767adbd3961760af5d56efe45fa8217cce7db6 (diff)
libceph: enable large, variable-sized OSD requests
Turn r_ops into a flexible array member to enable large, consisting of up to 16 ops, OSD requests. The use case is scattered writeback in cephfs and, as far as the kernel client is concerned, 16 is just a made up number. r_ops had size 3 for copyup+hint+write, but copyup is really a special case - it can only happen once. ceph_osd_request_cache is therefore stuffed with num_ops=2 requests, anything bigger than that is allocated with kmalloc(). req_mempool is backed by ceph_osd_request_cache, which means either num_ops=1 or num_ops=2 for use_mempool=true - all existing users (ceph_writepages_start(), ceph_osdc_writepages()) are fine with that. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'net')
-rw-r--r--net/ceph/osd_client.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index f93d0e893f3f..ccd4e031fa3f 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -338,9 +338,10 @@ static void ceph_osdc_release_request(struct kref *kref)
338 ceph_put_snap_context(req->r_snapc); 338 ceph_put_snap_context(req->r_snapc);
339 if (req->r_mempool) 339 if (req->r_mempool)
340 mempool_free(req, req->r_osdc->req_mempool); 340 mempool_free(req, req->r_osdc->req_mempool);
341 else 341 else if (req->r_num_ops <= CEPH_OSD_SLAB_OPS)
342 kmem_cache_free(ceph_osd_request_cache, req); 342 kmem_cache_free(ceph_osd_request_cache, req);
343 343 else
344 kfree(req);
344} 345}
345 346
346void ceph_osdc_get_request(struct ceph_osd_request *req) 347void ceph_osdc_get_request(struct ceph_osd_request *req)
@@ -369,18 +370,22 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
369 struct ceph_msg *msg; 370 struct ceph_msg *msg;
370 size_t msg_size; 371 size_t msg_size;
371 372
372 BUILD_BUG_ON(CEPH_OSD_MAX_OP > U16_MAX);
373 BUG_ON(num_ops > CEPH_OSD_MAX_OP);
374
375 if (use_mempool) { 373 if (use_mempool) {
374 BUG_ON(num_ops > CEPH_OSD_SLAB_OPS);
376 req = mempool_alloc(osdc->req_mempool, gfp_flags); 375 req = mempool_alloc(osdc->req_mempool, gfp_flags);
377 memset(req, 0, sizeof(*req)); 376 } else if (num_ops <= CEPH_OSD_SLAB_OPS) {
377 req = kmem_cache_alloc(ceph_osd_request_cache, gfp_flags);
378 } else { 378 } else {
379 req = kmem_cache_zalloc(ceph_osd_request_cache, gfp_flags); 379 BUG_ON(num_ops > CEPH_OSD_MAX_OPS);
380 req = kmalloc(sizeof(*req) + num_ops * sizeof(req->r_ops[0]),
381 gfp_flags);
380 } 382 }
381 if (req == NULL) 383 if (unlikely(!req))
382 return NULL; 384 return NULL;
383 385
386 /* req only, each op is zeroed in _osd_req_op_init() */
387 memset(req, 0, sizeof(*req));
388
384 req->r_osdc = osdc; 389 req->r_osdc = osdc;
385 req->r_mempool = use_mempool; 390 req->r_mempool = use_mempool;
386 req->r_num_ops = num_ops; 391 req->r_num_ops = num_ops;
@@ -398,12 +403,19 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
398 req->r_base_oloc.pool = -1; 403 req->r_base_oloc.pool = -1;
399 req->r_target_oloc.pool = -1; 404 req->r_target_oloc.pool = -1;
400 405
406 msg_size = OSD_OPREPLY_FRONT_LEN;
407 if (num_ops > CEPH_OSD_SLAB_OPS) {
408 /* ceph_osd_op and rval */
409 msg_size += (num_ops - CEPH_OSD_SLAB_OPS) *
410 (sizeof(struct ceph_osd_op) + 4);
411 }
412
401 /* create reply message */ 413 /* create reply message */
402 if (use_mempool) 414 if (use_mempool)
403 msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0); 415 msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0);
404 else 416 else
405 msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, 417 msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, msg_size,
406 OSD_OPREPLY_FRONT_LEN, gfp_flags, true); 418 gfp_flags, true);
407 if (!msg) { 419 if (!msg) {
408 ceph_osdc_put_request(req); 420 ceph_osdc_put_request(req);
409 return NULL; 421 return NULL;
@@ -1811,7 +1823,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg)
1811 1823
1812 ceph_decode_need(&p, end, 4, bad_put); 1824 ceph_decode_need(&p, end, 4, bad_put);
1813 numops = ceph_decode_32(&p); 1825 numops = ceph_decode_32(&p);
1814 if (numops > CEPH_OSD_MAX_OP) 1826 if (numops > CEPH_OSD_MAX_OPS)
1815 goto bad_put; 1827 goto bad_put;
1816 if (numops != req->r_num_ops) 1828 if (numops != req->r_num_ops)
1817 goto bad_put; 1829 goto bad_put;
@@ -2784,11 +2796,12 @@ EXPORT_SYMBOL(ceph_osdc_writepages);
2784 2796
2785int ceph_osdc_setup(void) 2797int ceph_osdc_setup(void)
2786{ 2798{
2799 size_t size = sizeof(struct ceph_osd_request) +
2800 CEPH_OSD_SLAB_OPS * sizeof(struct ceph_osd_req_op);
2801
2787 BUG_ON(ceph_osd_request_cache); 2802 BUG_ON(ceph_osd_request_cache);
2788 ceph_osd_request_cache = kmem_cache_create("ceph_osd_request", 2803 ceph_osd_request_cache = kmem_cache_create("ceph_osd_request", size,
2789 sizeof (struct ceph_osd_request), 2804 0, 0, NULL);
2790 __alignof__(struct ceph_osd_request),
2791 0, NULL);
2792 2805
2793 return ceph_osd_request_cache ? 0 : -ENOMEM; 2806 return ceph_osd_request_cache ? 0 : -ENOMEM;
2794} 2807}