diff options
| -rw-r--r-- | drivers/block/rbd.c | 76 |
1 files changed, 43 insertions, 33 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index f9cad40d95af..aa95227fdee2 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
| @@ -236,7 +236,8 @@ enum obj_operation_type { | |||
| 236 | enum rbd_obj_write_state { | 236 | enum rbd_obj_write_state { |
| 237 | RBD_OBJ_WRITE_FLAT = 1, | 237 | RBD_OBJ_WRITE_FLAT = 1, |
| 238 | RBD_OBJ_WRITE_GUARD, | 238 | RBD_OBJ_WRITE_GUARD, |
| 239 | RBD_OBJ_WRITE_COPYUP, | 239 | RBD_OBJ_WRITE_READ_FROM_PARENT, |
| 240 | RBD_OBJ_WRITE_COPYUP_OPS, | ||
| 240 | }; | 241 | }; |
| 241 | 242 | ||
| 242 | struct rbd_obj_request { | 243 | struct rbd_obj_request { |
| @@ -2458,10 +2459,13 @@ static bool is_zero_bvecs(struct bio_vec *bvecs, u32 bytes) | |||
| 2458 | return true; | 2459 | return true; |
| 2459 | } | 2460 | } |
| 2460 | 2461 | ||
| 2461 | static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes) | 2462 | #define MODS_ONLY U32_MAX |
| 2463 | |||
| 2464 | static int rbd_obj_issue_copyup_ops(struct rbd_obj_request *obj_req, u32 bytes) | ||
| 2462 | { | 2465 | { |
| 2463 | struct rbd_img_request *img_req = obj_req->img_request; | 2466 | struct rbd_img_request *img_req = obj_req->img_request; |
| 2464 | unsigned int num_osd_ops = 1; | 2467 | unsigned int num_osd_ops = (bytes != MODS_ONLY); |
| 2468 | unsigned int which = 0; | ||
| 2465 | int ret; | 2469 | int ret; |
| 2466 | 2470 | ||
| 2467 | dout("%s obj_req %p bytes %u\n", __func__, obj_req, bytes); | 2471 | dout("%s obj_req %p bytes %u\n", __func__, obj_req, bytes); |
| @@ -2483,31 +2487,25 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes) | |||
| 2483 | if (!obj_req->osd_req) | 2487 | if (!obj_req->osd_req) |
| 2484 | return -ENOMEM; | 2488 | return -ENOMEM; |
| 2485 | 2489 | ||
| 2486 | ret = osd_req_op_cls_init(obj_req->osd_req, 0, "rbd", "copyup"); | 2490 | if (bytes != MODS_ONLY) { |
| 2487 | if (ret) | 2491 | ret = osd_req_op_cls_init(obj_req->osd_req, which, "rbd", |
| 2488 | return ret; | 2492 | "copyup"); |
| 2493 | if (ret) | ||
| 2494 | return ret; | ||
| 2489 | 2495 | ||
| 2490 | /* | 2496 | osd_req_op_cls_request_data_bvecs(obj_req->osd_req, which++, |
| 2491 | * Only send non-zero copyup data to save some I/O and network | 2497 | obj_req->copyup_bvecs, |
| 2492 | * bandwidth -- zero copyup data is equivalent to the object not | 2498 | obj_req->copyup_bvec_count, |
| 2493 | * existing. | 2499 | bytes); |
| 2494 | */ | ||
| 2495 | if (is_zero_bvecs(obj_req->copyup_bvecs, bytes)) { | ||
| 2496 | dout("%s obj_req %p detected zeroes\n", __func__, obj_req); | ||
| 2497 | bytes = 0; | ||
| 2498 | } | 2500 | } |
| 2499 | osd_req_op_cls_request_data_bvecs(obj_req->osd_req, 0, | ||
| 2500 | obj_req->copyup_bvecs, | ||
| 2501 | obj_req->copyup_bvec_count, | ||
| 2502 | bytes); | ||
| 2503 | 2501 | ||
| 2504 | switch (img_req->op_type) { | 2502 | switch (img_req->op_type) { |
| 2505 | case OBJ_OP_WRITE: | 2503 | case OBJ_OP_WRITE: |
| 2506 | __rbd_obj_setup_write(obj_req, 1); | 2504 | __rbd_obj_setup_write(obj_req, which); |
| 2507 | break; | 2505 | break; |
| 2508 | case OBJ_OP_ZEROOUT: | 2506 | case OBJ_OP_ZEROOUT: |
| 2509 | rbd_assert(!rbd_obj_is_entire(obj_req)); | 2507 | rbd_assert(!rbd_obj_is_entire(obj_req)); |
| 2510 | __rbd_obj_setup_zeroout(obj_req, 1); | 2508 | __rbd_obj_setup_zeroout(obj_req, which); |
| 2511 | break; | 2509 | break; |
| 2512 | default: | 2510 | default: |
| 2513 | rbd_assert(0); | 2511 | rbd_assert(0); |
| @@ -2521,6 +2519,22 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes) | |||
| 2521 | return 0; | 2519 | return 0; |
| 2522 | } | 2520 | } |
| 2523 | 2521 | ||
| 2522 | static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes) | ||
| 2523 | { | ||
| 2524 | /* | ||
| 2525 | * Only send non-zero copyup data to save some I/O and network | ||
| 2526 | * bandwidth -- zero copyup data is equivalent to the object not | ||
| 2527 | * existing. | ||
| 2528 | */ | ||
| 2529 | if (is_zero_bvecs(obj_req->copyup_bvecs, bytes)) { | ||
| 2530 | dout("%s obj_req %p detected zeroes\n", __func__, obj_req); | ||
| 2531 | bytes = 0; | ||
| 2532 | } | ||
| 2533 | |||
| 2534 | obj_req->write_state = RBD_OBJ_WRITE_COPYUP_OPS; | ||
| 2535 | return rbd_obj_issue_copyup_ops(obj_req, bytes); | ||
| 2536 | } | ||
| 2537 | |||
| 2524 | static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap) | 2538 | static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap) |
| 2525 | { | 2539 | { |
| 2526 | u32 i; | 2540 | u32 i; |
| @@ -2560,22 +2574,19 @@ static int rbd_obj_handle_write_guard(struct rbd_obj_request *obj_req) | |||
| 2560 | if (!obj_req->num_img_extents) { | 2574 | if (!obj_req->num_img_extents) { |
| 2561 | /* | 2575 | /* |
| 2562 | * The overlap has become 0 (most likely because the | 2576 | * The overlap has become 0 (most likely because the |
| 2563 | * image has been flattened). Use rbd_obj_issue_copyup() | 2577 | * image has been flattened). Re-submit the original write |
| 2564 | * to re-submit the original write request -- the copyup | 2578 | * request -- pass MODS_ONLY since the copyup isn't needed |
| 2565 | * operation itself will be a no-op, since someone must | 2579 | * anymore. |
| 2566 | * have populated the child object while we weren't | ||
| 2567 | * looking. Move to WRITE_FLAT state as we'll be done | ||
| 2568 | * with the operation once the null copyup completes. | ||
| 2569 | */ | 2580 | */ |
| 2570 | obj_req->write_state = RBD_OBJ_WRITE_FLAT; | 2581 | obj_req->write_state = RBD_OBJ_WRITE_COPYUP_OPS; |
| 2571 | return rbd_obj_issue_copyup(obj_req, 0); | 2582 | return rbd_obj_issue_copyup_ops(obj_req, MODS_ONLY); |
| 2572 | } | 2583 | } |
| 2573 | 2584 | ||
| 2574 | ret = setup_copyup_bvecs(obj_req, rbd_obj_img_extents_bytes(obj_req)); | 2585 | ret = setup_copyup_bvecs(obj_req, rbd_obj_img_extents_bytes(obj_req)); |
| 2575 | if (ret) | 2586 | if (ret) |
| 2576 | return ret; | 2587 | return ret; |
| 2577 | 2588 | ||
| 2578 | obj_req->write_state = RBD_OBJ_WRITE_COPYUP; | 2589 | obj_req->write_state = RBD_OBJ_WRITE_READ_FROM_PARENT; |
| 2579 | return rbd_obj_read_from_parent(obj_req); | 2590 | return rbd_obj_read_from_parent(obj_req); |
| 2580 | } | 2591 | } |
| 2581 | 2592 | ||
| @@ -2583,7 +2594,6 @@ static bool rbd_obj_handle_write(struct rbd_obj_request *obj_req) | |||
| 2583 | { | 2594 | { |
| 2584 | int ret; | 2595 | int ret; |
| 2585 | 2596 | ||
| 2586 | again: | ||
| 2587 | switch (obj_req->write_state) { | 2597 | switch (obj_req->write_state) { |
| 2588 | case RBD_OBJ_WRITE_GUARD: | 2598 | case RBD_OBJ_WRITE_GUARD: |
| 2589 | rbd_assert(!obj_req->xferred); | 2599 | rbd_assert(!obj_req->xferred); |
| @@ -2602,6 +2612,7 @@ again: | |||
| 2602 | } | 2612 | } |
| 2603 | /* fall through */ | 2613 | /* fall through */ |
| 2604 | case RBD_OBJ_WRITE_FLAT: | 2614 | case RBD_OBJ_WRITE_FLAT: |
| 2615 | case RBD_OBJ_WRITE_COPYUP_OPS: | ||
| 2605 | if (!obj_req->result) | 2616 | if (!obj_req->result) |
| 2606 | /* | 2617 | /* |
| 2607 | * There is no such thing as a successful short | 2618 | * There is no such thing as a successful short |
| @@ -2609,10 +2620,9 @@ again: | |||
| 2609 | */ | 2620 | */ |
| 2610 | obj_req->xferred = obj_req->ex.oe_len; | 2621 | obj_req->xferred = obj_req->ex.oe_len; |
| 2611 | return true; | 2622 | return true; |
| 2612 | case RBD_OBJ_WRITE_COPYUP: | 2623 | case RBD_OBJ_WRITE_READ_FROM_PARENT: |
| 2613 | obj_req->write_state = RBD_OBJ_WRITE_GUARD; | ||
| 2614 | if (obj_req->result) | 2624 | if (obj_req->result) |
| 2615 | goto again; | 2625 | return true; |
| 2616 | 2626 | ||
| 2617 | rbd_assert(obj_req->xferred); | 2627 | rbd_assert(obj_req->xferred); |
| 2618 | ret = rbd_obj_issue_copyup(obj_req, obj_req->xferred); | 2628 | ret = rbd_obj_issue_copyup(obj_req, obj_req->xferred); |
