diff options
| -rw-r--r-- | drivers/block/rbd.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 4edcb6d85f01..5c2731859e8a 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
| @@ -2319,7 +2319,7 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) | |||
| 2319 | struct rbd_device *rbd_dev; | 2319 | struct rbd_device *rbd_dev; |
| 2320 | struct page **pages; | 2320 | struct page **pages; |
| 2321 | u32 page_count; | 2321 | u32 page_count; |
| 2322 | int result; | 2322 | int img_result; |
| 2323 | u64 parent_length; | 2323 | u64 parent_length; |
| 2324 | u64 offset; | 2324 | u64 offset; |
| 2325 | u64 length; | 2325 | u64 length; |
| @@ -2338,7 +2338,7 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) | |||
| 2338 | orig_request = img_request->obj_request; | 2338 | orig_request = img_request->obj_request; |
| 2339 | rbd_assert(orig_request != NULL); | 2339 | rbd_assert(orig_request != NULL); |
| 2340 | rbd_assert(obj_request_type_valid(orig_request->type)); | 2340 | rbd_assert(obj_request_type_valid(orig_request->type)); |
| 2341 | result = img_request->result; | 2341 | img_result = img_request->result; |
| 2342 | parent_length = img_request->length; | 2342 | parent_length = img_request->length; |
| 2343 | rbd_assert(parent_length == img_request->xferred); | 2343 | rbd_assert(parent_length == img_request->xferred); |
| 2344 | rbd_img_request_put(img_request); | 2344 | rbd_img_request_put(img_request); |
| @@ -2347,7 +2347,22 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) | |||
| 2347 | rbd_dev = orig_request->img_request->rbd_dev; | 2347 | rbd_dev = orig_request->img_request->rbd_dev; |
| 2348 | rbd_assert(rbd_dev); | 2348 | rbd_assert(rbd_dev); |
| 2349 | 2349 | ||
| 2350 | if (result) | 2350 | /* |
| 2351 | * If the overlap has become 0 (most likely because the | ||
| 2352 | * image has been flattened) we need to free the pages | ||
| 2353 | * and re-submit the original write request. | ||
| 2354 | */ | ||
| 2355 | if (!rbd_dev->parent_overlap) { | ||
| 2356 | struct ceph_osd_client *osdc; | ||
| 2357 | |||
| 2358 | ceph_release_page_vector(pages, page_count); | ||
| 2359 | osdc = &rbd_dev->rbd_client->client->osdc; | ||
| 2360 | img_result = rbd_obj_request_submit(osdc, orig_request); | ||
| 2361 | if (!img_result) | ||
| 2362 | return; | ||
| 2363 | } | ||
| 2364 | |||
| 2365 | if (img_result) | ||
| 2351 | goto out_err; | 2366 | goto out_err; |
| 2352 | 2367 | ||
| 2353 | /* | 2368 | /* |
| @@ -2356,7 +2371,7 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) | |||
| 2356 | * request. Allocate the new copyup osd request for the | 2371 | * request. Allocate the new copyup osd request for the |
| 2357 | * original request, and release the old one. | 2372 | * original request, and release the old one. |
| 2358 | */ | 2373 | */ |
| 2359 | result = -ENOMEM; | 2374 | img_result = -ENOMEM; |
| 2360 | osd_req = rbd_osd_req_create_copyup(orig_request); | 2375 | osd_req = rbd_osd_req_create_copyup(orig_request); |
| 2361 | if (!osd_req) | 2376 | if (!osd_req) |
| 2362 | goto out_err; | 2377 | goto out_err; |
| @@ -2391,13 +2406,13 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) | |||
| 2391 | 2406 | ||
| 2392 | orig_request->callback = rbd_img_obj_copyup_callback; | 2407 | orig_request->callback = rbd_img_obj_copyup_callback; |
| 2393 | osdc = &rbd_dev->rbd_client->client->osdc; | 2408 | osdc = &rbd_dev->rbd_client->client->osdc; |
| 2394 | result = rbd_obj_request_submit(osdc, orig_request); | 2409 | img_result = rbd_obj_request_submit(osdc, orig_request); |
| 2395 | if (!result) | 2410 | if (!img_result) |
| 2396 | return; | 2411 | return; |
| 2397 | out_err: | 2412 | out_err: |
| 2398 | /* Record the error code and complete the request */ | 2413 | /* Record the error code and complete the request */ |
| 2399 | 2414 | ||
| 2400 | orig_request->result = result; | 2415 | orig_request->result = img_result; |
| 2401 | orig_request->xferred = 0; | 2416 | orig_request->xferred = 0; |
| 2402 | obj_request_done_set(orig_request); | 2417 | obj_request_done_set(orig_request); |
| 2403 | rbd_obj_request_complete(orig_request); | 2418 | rbd_obj_request_complete(orig_request); |
