summaryrefslogtreecommitdiff
path: root/drivers/block/rbd.c
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-05-06 17:40:33 -0500
committerAlex Elder <elder@inktank.com>2013-05-13 15:06:46 -0500
commit638f5abed3f7d8a7fc24087bd760fa3d99f68a39 (patch)
tree6a37c092f07923eb17f36a11c1a46b40e762aca0 /drivers/block/rbd.c
parentbbea1c1a31b1128d34b2b5b4f28276969cce14e9 (diff)
downloadlinux-next-638f5abed3f7d8a7fc24087bd760fa3d99f68a39.tar.gz
rbd: re-submit flattened write request (part 2)
Add code to rbd_img_obj_exists_callback() to detect when a clone's parent image has disappeared, and re-submit the original write request in that case. Kill off some redundant assertions. This completes the resolution for: http://tracker.ceph.com/issues/3763 Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r--drivers/block/rbd.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 5c2731859e8a..6b872f219774 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2516,6 +2516,7 @@ out_err:
static void rbd_img_obj_exists_callback(struct rbd_obj_request *obj_request)
{
struct rbd_obj_request *orig_request;
+ struct rbd_device *rbd_dev;
int result;
rbd_assert(!obj_request_img_data_test(obj_request));
@@ -2538,8 +2539,21 @@ static void rbd_img_obj_exists_callback(struct rbd_obj_request *obj_request)
obj_request->xferred, obj_request->length);
rbd_obj_request_put(obj_request);
- rbd_assert(orig_request);
- rbd_assert(orig_request->img_request);
+ /*
+ * If the overlap has become 0 (most likely because the
+ * image has been flattened) we need to free the pages
+ * and re-submit the original write request.
+ */
+ rbd_dev = orig_request->img_request->rbd_dev;
+ if (!rbd_dev->parent_overlap) {
+ struct ceph_osd_client *osdc;
+
+ rbd_obj_request_put(orig_request);
+ osdc = &rbd_dev->rbd_client->client->osdc;
+ result = rbd_obj_request_submit(osdc, orig_request);
+ if (!result)
+ return;
+ }
/*
* Our only purpose here is to determine whether the object