From d9050368d1fa334186417398720cc8a6098ffdec Mon Sep 17 00:00:00 2001
From: David Disseldorp <ddiss@suse.de>
Date: Wed, 21 Jun 2017 01:42:27 +0200
Subject: [PATCH 3/4] rbd: copy compare-and-write osd requests before
resubmission
Patch-mainline: Not yet, clustered LIO/RBD
References: bsc#1042210
This is similar to the osd_client request_reinit() logic used for linger
requests.
Signed-off-by: David Disseldorp <ddiss@suse.de>
Acked-by: Luis Henriques <lhenriques@suse.com>
[luis: due to commit 26f887e0a3c4 ("libceph, rbd, ceph: move
ceph_osdc_alloc_messages() calls"), call ceph_osdc_alloc_messages in
rbd_img_obj_creatrunc_callback]
---
drivers/block/rbd.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -3044,7 +3044,9 @@ static void
rbd_img_obj_creatrunc_callback(struct rbd_obj_request *obj_request)
{
struct rbd_obj_request *orig_request;
+ static struct ceph_osd_request *new_osd_req;
int result;
+ struct rbd_device *rbd_dev;
rbd_assert(!obj_request_img_data_test(obj_request));
@@ -3057,6 +3059,8 @@ rbd_img_obj_creatrunc_callback(struct rb
rbd_obj_request_put(orig_request);
rbd_assert(orig_request);
rbd_assert(orig_request->img_request);
+ rbd_dev = orig_request->img_request->rbd_dev;
+ rbd_assert(rbd_dev);
result = obj_request->result;
obj_request->result = 0;
@@ -3065,10 +3069,34 @@ rbd_img_obj_creatrunc_callback(struct rb
obj_request, orig_request, result,
obj_request->xferred, obj_request->length);
rbd_obj_request_put(obj_request);
+ obj_request = NULL;
if (result) {
orig_request->result = result;
goto out;
+ }
+
+ /*
+ * We can't resubmit the original request without reinitialisation, as
+ * the r_tid has been assigned, and reply filled.
+ */
+ new_osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_CMP_AND_WRITE, 3,
+ orig_request);
+ if (!new_osd_req) {
+ orig_request->result = -ENOMEM;
+ goto out;
+ }
+
+ rbd_osd_cmp_and_write_req_copy(new_osd_req, orig_request->osd_req);
+ ceph_osdc_put_request(orig_request->osd_req);
+ orig_request->osd_req = new_osd_req;
+
+ rbd_osd_req_format_rw(orig_request);
+
+ result = ceph_osdc_alloc_messages(orig_request->osd_req, GFP_NOIO);
+ if (result) {
+ orig_request->result = result;
+ goto out;
}
/*