Blob Blame History Raw
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
@@ -2829,7 +2829,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));
 
@@ -2842,6 +2844,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;
@@ -2850,10 +2854,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;
 	}
 
 	/*