diff options
| author | Josh Durgin <josh.durgin@inktank.com> | 2014-04-07 19:49:21 -0400 |
|---|---|---|
| committer | Ilya Dryomov <idryomov@redhat.com> | 2014-10-14 13:03:36 -0400 |
| commit | d3246fb0da5d70838469c01d5b6b11163b49cd86 (patch) | |
| tree | 1770ff1c699df0469a02d5cabd7060afa810b9e2 /drivers/block | |
| parent | 3b434a2aff38029ea053ce6c8fced53b2d01f7f0 (diff) | |
rbd: use helpers to handle discard for layered images correctly
Only allocate two osd ops for discard requests, since the
preallocation hint is only added for regular writes. Use
rbd_img_obj_request_fill() to recreate the original write or discard
osd operations, isolating that logic to one place, and change the
assert in rbd_osd_req_create_copyup() to accept discard requests as
well.
Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block')
| -rw-r--r-- | drivers/block/rbd.c | 54 |
1 files changed, 22 insertions, 32 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index c07cb1dbc1c5..e1dcd36ae072 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
| @@ -1934,9 +1934,10 @@ static struct ceph_osd_request *rbd_osd_req_create( | |||
| 1934 | } | 1934 | } |
| 1935 | 1935 | ||
| 1936 | /* | 1936 | /* |
| 1937 | * Create a copyup osd request based on the information in the | 1937 | * Create a copyup osd request based on the information in the object |
| 1938 | * object request supplied. A copyup request has three osd ops, | 1938 | * request supplied. A copyup request has two or three osd ops, a |
| 1939 | * a copyup method call, a hint op, and a write op. | 1939 | * copyup method call, potentially a hint op, and a write or truncate |
| 1940 | * or zero op. | ||
| 1940 | */ | 1941 | */ |
| 1941 | static struct ceph_osd_request * | 1942 | static struct ceph_osd_request * |
| 1942 | rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request) | 1943 | rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request) |
| @@ -1946,18 +1947,24 @@ rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request) | |||
| 1946 | struct rbd_device *rbd_dev; | 1947 | struct rbd_device *rbd_dev; |
| 1947 | struct ceph_osd_client *osdc; | 1948 | struct ceph_osd_client *osdc; |
| 1948 | struct ceph_osd_request *osd_req; | 1949 | struct ceph_osd_request *osd_req; |
| 1950 | int num_osd_ops = 3; | ||
| 1949 | 1951 | ||
| 1950 | rbd_assert(obj_request_img_data_test(obj_request)); | 1952 | rbd_assert(obj_request_img_data_test(obj_request)); |
| 1951 | img_request = obj_request->img_request; | 1953 | img_request = obj_request->img_request; |
| 1952 | rbd_assert(img_request); | 1954 | rbd_assert(img_request); |
| 1953 | rbd_assert(img_request_write_test(img_request)); | 1955 | rbd_assert(img_request_write_test(img_request) || |
| 1956 | img_request_discard_test(img_request)); | ||
| 1954 | 1957 | ||
| 1955 | /* Allocate and initialize the request, for the three ops */ | 1958 | if (img_request_discard_test(img_request)) |
| 1959 | num_osd_ops = 2; | ||
| 1960 | |||
| 1961 | /* Allocate and initialize the request, for all the ops */ | ||
| 1956 | 1962 | ||
| 1957 | snapc = img_request->snapc; | 1963 | snapc = img_request->snapc; |
| 1958 | rbd_dev = img_request->rbd_dev; | 1964 | rbd_dev = img_request->rbd_dev; |
| 1959 | osdc = &rbd_dev->rbd_client->client->osdc; | 1965 | osdc = &rbd_dev->rbd_client->client->osdc; |
| 1960 | osd_req = ceph_osdc_alloc_request(osdc, snapc, 3, false, GFP_ATOMIC); | 1966 | osd_req = ceph_osdc_alloc_request(osdc, snapc, num_osd_ops, |
| 1967 | false, GFP_ATOMIC); | ||
| 1961 | if (!osd_req) | 1968 | if (!osd_req) |
| 1962 | return NULL; /* ENOMEM */ | 1969 | return NULL; /* ENOMEM */ |
| 1963 | 1970 | ||
| @@ -2337,10 +2344,9 @@ static void rbd_img_obj_request_fill(struct rbd_obj_request *obj_request, | |||
| 2337 | u16 opcode; | 2344 | u16 opcode; |
| 2338 | 2345 | ||
| 2339 | if (op_type == OBJ_OP_DISCARD) { | 2346 | if (op_type == OBJ_OP_DISCARD) { |
| 2340 | if (!offset && (length == object_size) | 2347 | if (!offset && length == object_size && |
| 2341 | && (!img_request_layered_test(img_request) || | 2348 | (!img_request_layered_test(img_request) || |
| 2342 | (rbd_dev->parent_overlap <= | 2349 | !obj_request_overlaps_parent(obj_request))) { |
| 2343 | obj_request->img_offset))) { | ||
| 2344 | opcode = CEPH_OSD_OP_DELETE; | 2350 | opcode = CEPH_OSD_OP_DELETE; |
| 2345 | } else if ((offset + length == object_size)) { | 2351 | } else if ((offset + length == object_size)) { |
| 2346 | opcode = CEPH_OSD_OP_TRUNCATE; | 2352 | opcode = CEPH_OSD_OP_TRUNCATE; |
| @@ -2500,7 +2506,8 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request) | |||
| 2500 | struct page **pages; | 2506 | struct page **pages; |
| 2501 | u32 page_count; | 2507 | u32 page_count; |
| 2502 | 2508 | ||
| 2503 | rbd_assert(obj_request->type == OBJ_REQUEST_BIO); | 2509 | rbd_assert(obj_request->type == OBJ_REQUEST_BIO || |
| 2510 | obj_request->type == OBJ_REQUEST_NODATA); | ||
| 2504 | rbd_assert(obj_request_img_data_test(obj_request)); | 2511 | rbd_assert(obj_request_img_data_test(obj_request)); |
| 2505 | img_request = obj_request->img_request; | 2512 | img_request = obj_request->img_request; |
| 2506 | rbd_assert(img_request); | 2513 | rbd_assert(img_request); |
| @@ -2538,11 +2545,10 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) | |||
| 2538 | struct ceph_osd_client *osdc; | 2545 | struct ceph_osd_client *osdc; |
| 2539 | struct rbd_device *rbd_dev; | 2546 | struct rbd_device *rbd_dev; |
| 2540 | struct page **pages; | 2547 | struct page **pages; |
| 2548 | enum obj_operation_type op_type; | ||
| 2541 | u32 page_count; | 2549 | u32 page_count; |
| 2542 | int img_result; | 2550 | int img_result; |
| 2543 | u64 parent_length; | 2551 | u64 parent_length; |
| 2544 | u64 offset; | ||
| 2545 | u64 length; | ||
| 2546 | 2552 | ||
| 2547 | rbd_assert(img_request_child_test(img_request)); | 2553 | rbd_assert(img_request_child_test(img_request)); |
| 2548 | 2554 | ||
| @@ -2606,26 +2612,10 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) | |||
| 2606 | osd_req_op_cls_request_data_pages(osd_req, 0, pages, parent_length, 0, | 2612 | osd_req_op_cls_request_data_pages(osd_req, 0, pages, parent_length, 0, |
| 2607 | false, false); | 2613 | false, false); |
| 2608 | 2614 | ||
| 2609 | /* Then the hint op */ | 2615 | /* Add the other op(s) */ |
| 2610 | |||
| 2611 | osd_req_op_alloc_hint_init(osd_req, 1, rbd_obj_bytes(&rbd_dev->header), | ||
| 2612 | rbd_obj_bytes(&rbd_dev->header)); | ||
| 2613 | |||
| 2614 | /* And the original write request op */ | ||
| 2615 | |||
| 2616 | offset = orig_request->offset; | ||
| 2617 | length = orig_request->length; | ||
| 2618 | osd_req_op_extent_init(osd_req, 2, CEPH_OSD_OP_WRITE, | ||
| 2619 | offset, length, 0, 0); | ||
| 2620 | if (orig_request->type == OBJ_REQUEST_BIO) | ||
| 2621 | osd_req_op_extent_osd_data_bio(osd_req, 2, | ||
| 2622 | orig_request->bio_list, length); | ||
| 2623 | else | ||
| 2624 | osd_req_op_extent_osd_data_pages(osd_req, 2, | ||
| 2625 | orig_request->pages, length, | ||
| 2626 | offset & ~PAGE_MASK, false, false); | ||
| 2627 | 2616 | ||
| 2628 | rbd_osd_req_format_write(orig_request); | 2617 | op_type = rbd_img_request_op_type(orig_request->img_request); |
| 2618 | rbd_img_obj_request_fill(orig_request, osd_req, op_type, 1); | ||
| 2629 | 2619 | ||
| 2630 | /* All set, send it off. */ | 2620 | /* All set, send it off. */ |
| 2631 | 2621 | ||
