diff options
author | Josh Durgin <josh.durgin@inktank.com> | 2014-04-04 20:32:15 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@redhat.com> | 2014-10-14 13:03:35 -0400 |
commit | 3b434a2aff38029ea053ce6c8fced53b2d01f7f0 (patch) | |
tree | f4055dab80a6681ee134c49844b81a0149262950 /drivers/block/rbd.c | |
parent | 1c220881e307b62cc2f77d911219de332aa3f61e (diff) |
rbd: extract a method for adding object operations
rbd_img_request_fill() creates a ceph_osd_request and has logic for
adding the appropriate osd ops to it based on the request type and
image properties.
For layered images, the original rbd_obj_request is resent with a
copyup operation in front, using a new ceph_osd_request. The logic for
adding the original operations should be the same as when first
sending them, so move it to a helper function.
op_type only needs to be checked once, so create a helper for that as
well and call it outside the loop in rbd_img_request_fill().
Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r-- | drivers/block/rbd.c | 133 |
1 files changed, 78 insertions, 55 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 6fb93cd6957f..c07cb1dbc1c5 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1672,6 +1672,17 @@ static bool img_request_layered_test(struct rbd_img_request *img_request) | |||
1672 | return test_bit(IMG_REQ_LAYERED, &img_request->flags) != 0; | 1672 | return test_bit(IMG_REQ_LAYERED, &img_request->flags) != 0; |
1673 | } | 1673 | } |
1674 | 1674 | ||
1675 | static enum obj_operation_type | ||
1676 | rbd_img_request_op_type(struct rbd_img_request *img_request) | ||
1677 | { | ||
1678 | if (img_request_write_test(img_request)) | ||
1679 | return OBJ_OP_WRITE; | ||
1680 | else if (img_request_discard_test(img_request)) | ||
1681 | return OBJ_OP_DISCARD; | ||
1682 | else | ||
1683 | return OBJ_OP_READ; | ||
1684 | } | ||
1685 | |||
1675 | static void | 1686 | static void |
1676 | rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request) | 1687 | rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request) |
1677 | { | 1688 | { |
@@ -2308,6 +2319,68 @@ out: | |||
2308 | } | 2319 | } |
2309 | 2320 | ||
2310 | /* | 2321 | /* |
2322 | * Add individual osd ops to the given ceph_osd_request and prepare | ||
2323 | * them for submission. num_ops is the current number of | ||
2324 | * osd operations already to the object request. | ||
2325 | */ | ||
2326 | static void rbd_img_obj_request_fill(struct rbd_obj_request *obj_request, | ||
2327 | struct ceph_osd_request *osd_request, | ||
2328 | enum obj_operation_type op_type, | ||
2329 | unsigned int num_ops) | ||
2330 | { | ||
2331 | struct rbd_img_request *img_request = obj_request->img_request; | ||
2332 | struct rbd_device *rbd_dev = img_request->rbd_dev; | ||
2333 | u64 object_size = rbd_obj_bytes(&rbd_dev->header); | ||
2334 | u64 offset = obj_request->offset; | ||
2335 | u64 length = obj_request->length; | ||
2336 | u64 img_end; | ||
2337 | u16 opcode; | ||
2338 | |||
2339 | if (op_type == OBJ_OP_DISCARD) { | ||
2340 | if (!offset && (length == object_size) | ||
2341 | && (!img_request_layered_test(img_request) || | ||
2342 | (rbd_dev->parent_overlap <= | ||
2343 | obj_request->img_offset))) { | ||
2344 | opcode = CEPH_OSD_OP_DELETE; | ||
2345 | } else if ((offset + length == object_size)) { | ||
2346 | opcode = CEPH_OSD_OP_TRUNCATE; | ||
2347 | } else { | ||
2348 | down_read(&rbd_dev->header_rwsem); | ||
2349 | img_end = rbd_dev->header.image_size; | ||
2350 | up_read(&rbd_dev->header_rwsem); | ||
2351 | |||
2352 | if (obj_request->img_offset + length == img_end) | ||
2353 | opcode = CEPH_OSD_OP_TRUNCATE; | ||
2354 | else | ||
2355 | opcode = CEPH_OSD_OP_ZERO; | ||
2356 | } | ||
2357 | } else if (op_type == OBJ_OP_WRITE) { | ||
2358 | opcode = CEPH_OSD_OP_WRITE; | ||
2359 | osd_req_op_alloc_hint_init(osd_request, num_ops, | ||
2360 | object_size, object_size); | ||
2361 | num_ops++; | ||
2362 | } else { | ||
2363 | opcode = CEPH_OSD_OP_READ; | ||
2364 | } | ||
2365 | |||
2366 | osd_req_op_extent_init(osd_request, num_ops, opcode, offset, length, | ||
2367 | 0, 0); | ||
2368 | if (obj_request->type == OBJ_REQUEST_BIO) | ||
2369 | osd_req_op_extent_osd_data_bio(osd_request, num_ops, | ||
2370 | obj_request->bio_list, length); | ||
2371 | else if (obj_request->type == OBJ_REQUEST_PAGES) | ||
2372 | osd_req_op_extent_osd_data_pages(osd_request, num_ops, | ||
2373 | obj_request->pages, length, | ||
2374 | offset & ~PAGE_MASK, false, false); | ||
2375 | |||
2376 | /* Discards are also writes */ | ||
2377 | if (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD) | ||
2378 | rbd_osd_req_format_write(obj_request); | ||
2379 | else | ||
2380 | rbd_osd_req_format_read(obj_request); | ||
2381 | } | ||
2382 | |||
2383 | /* | ||
2311 | * Split up an image request into one or more object requests, each | 2384 | * Split up an image request into one or more object requests, each |
2312 | * to a different object. The "type" parameter indicates whether | 2385 | * to a different object. The "type" parameter indicates whether |
2313 | * "data_desc" is the pointer to the head of a list of bio | 2386 | * "data_desc" is the pointer to the head of a list of bio |
@@ -2326,11 +2399,8 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request, | |||
2326 | unsigned int bio_offset = 0; | 2399 | unsigned int bio_offset = 0; |
2327 | struct page **pages = NULL; | 2400 | struct page **pages = NULL; |
2328 | enum obj_operation_type op_type; | 2401 | enum obj_operation_type op_type; |
2329 | u64 object_size = rbd_obj_bytes(&rbd_dev->header); | ||
2330 | u64 img_offset; | 2402 | u64 img_offset; |
2331 | u64 img_end; | ||
2332 | u64 resid; | 2403 | u64 resid; |
2333 | u16 opcode; | ||
2334 | 2404 | ||
2335 | dout("%s: img %p type %d data_desc %p\n", __func__, img_request, | 2405 | dout("%s: img %p type %d data_desc %p\n", __func__, img_request, |
2336 | (int)type, data_desc); | 2406 | (int)type, data_desc); |
@@ -2338,6 +2408,7 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request, | |||
2338 | img_offset = img_request->offset; | 2408 | img_offset = img_request->offset; |
2339 | resid = img_request->length; | 2409 | resid = img_request->length; |
2340 | rbd_assert(resid > 0); | 2410 | rbd_assert(resid > 0); |
2411 | op_type = rbd_img_request_op_type(img_request); | ||
2341 | 2412 | ||
2342 | if (type == OBJ_REQUEST_BIO) { | 2413 | if (type == OBJ_REQUEST_BIO) { |
2343 | bio_list = data_desc; | 2414 | bio_list = data_desc; |
@@ -2352,7 +2423,6 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request, | |||
2352 | const char *object_name; | 2423 | const char *object_name; |
2353 | u64 offset; | 2424 | u64 offset; |
2354 | u64 length; | 2425 | u64 length; |
2355 | unsigned int which = 0; | ||
2356 | 2426 | ||
2357 | object_name = rbd_segment_name(rbd_dev, img_offset); | 2427 | object_name = rbd_segment_name(rbd_dev, img_offset); |
2358 | if (!object_name) | 2428 | if (!object_name) |
@@ -2395,66 +2465,19 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request, | |||
2395 | pages += page_count; | 2465 | pages += page_count; |
2396 | } | 2466 | } |
2397 | 2467 | ||
2398 | if (img_request_discard_test(img_request)) { | ||
2399 | op_type = OBJ_OP_DISCARD; | ||
2400 | if (!offset && (length == object_size) | ||
2401 | && (!img_request_layered_test(img_request) || | ||
2402 | (rbd_dev->parent_overlap <= | ||
2403 | obj_request->img_offset))) { | ||
2404 | opcode = CEPH_OSD_OP_DELETE; | ||
2405 | } else if ((offset + length == object_size)) { | ||
2406 | opcode = CEPH_OSD_OP_TRUNCATE; | ||
2407 | } else { | ||
2408 | down_read(&rbd_dev->header_rwsem); | ||
2409 | img_end = rbd_dev->header.image_size; | ||
2410 | up_read(&rbd_dev->header_rwsem); | ||
2411 | |||
2412 | if (obj_request->img_offset + length == img_end) | ||
2413 | opcode = CEPH_OSD_OP_TRUNCATE; | ||
2414 | else | ||
2415 | opcode = CEPH_OSD_OP_ZERO; | ||
2416 | } | ||
2417 | } else if (img_request_write_test(img_request)) { | ||
2418 | op_type = OBJ_OP_WRITE; | ||
2419 | opcode = CEPH_OSD_OP_WRITE; | ||
2420 | } else { | ||
2421 | op_type = OBJ_OP_READ; | ||
2422 | opcode = CEPH_OSD_OP_READ; | ||
2423 | } | ||
2424 | |||
2425 | osd_req = rbd_osd_req_create(rbd_dev, op_type, | 2468 | osd_req = rbd_osd_req_create(rbd_dev, op_type, |
2426 | (op_type == OBJ_OP_WRITE) ? 2 : 1, | 2469 | (op_type == OBJ_OP_WRITE) ? 2 : 1, |
2427 | obj_request); | 2470 | obj_request); |
2428 | if (!osd_req) | 2471 | if (!osd_req) |
2429 | goto out_unwind; | 2472 | goto out_unwind; |
2473 | |||
2430 | obj_request->osd_req = osd_req; | 2474 | obj_request->osd_req = osd_req; |
2431 | obj_request->callback = rbd_img_obj_callback; | 2475 | obj_request->callback = rbd_img_obj_callback; |
2432 | rbd_img_request_get(img_request); | 2476 | obj_request->img_offset = img_offset; |
2433 | |||
2434 | if (op_type == OBJ_OP_WRITE) { | ||
2435 | osd_req_op_alloc_hint_init(osd_req, which, | ||
2436 | rbd_obj_bytes(&rbd_dev->header), | ||
2437 | rbd_obj_bytes(&rbd_dev->header)); | ||
2438 | which++; | ||
2439 | } | ||
2440 | |||
2441 | osd_req_op_extent_init(osd_req, which, opcode, offset, length, | ||
2442 | 0, 0); | ||
2443 | if (type == OBJ_REQUEST_BIO) | ||
2444 | osd_req_op_extent_osd_data_bio(osd_req, which, | ||
2445 | obj_request->bio_list, length); | ||
2446 | else if (type == OBJ_REQUEST_PAGES) | ||
2447 | osd_req_op_extent_osd_data_pages(osd_req, which, | ||
2448 | obj_request->pages, length, | ||
2449 | offset & ~PAGE_MASK, false, false); | ||
2450 | 2477 | ||
2451 | /* Discards are also writes */ | 2478 | rbd_img_obj_request_fill(obj_request, osd_req, op_type, 0); |
2452 | if (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD) | ||
2453 | rbd_osd_req_format_write(obj_request); | ||
2454 | else | ||
2455 | rbd_osd_req_format_read(obj_request); | ||
2456 | 2479 | ||
2457 | obj_request->img_offset = img_offset; | 2480 | rbd_img_request_get(img_request); |
2458 | 2481 | ||
2459 | img_offset += length; | 2482 | img_offset += length; |
2460 | resid -= length; | 2483 | resid -= length; |