Blob Blame History Raw
From ed123390035ceef82490d4a4d45ada878fb7423f Mon Sep 17 00:00:00 2001
From: Mike Christie <michaelc@cs.wisc.edu>
Date: Wed, 29 Jul 2015 04:23:47 -0500
Subject: [PATCH] rbd: add support for writesame requests
References: fate#318836
Patch-mainline: Not yet, SES2 clustered LIO/RBD

This adds support for ceph writesame requests.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Acked-by: David Disseldorp <ddiss@suse.de>
Signed-off-by: Luis Henriques <lhenriques@suse.com>
[luis: rebased on top of a1fbb5e7bbb5 ("rbd: start enums at 1 instead of 0")]
---
 drivers/block/rbd.c |   59 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 51 insertions(+), 8 deletions(-)

--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -220,6 +220,7 @@ enum obj_operation_type {
 	OBJ_OP_WRITE,
 	OBJ_OP_DISCARD,
 	OBJ_OP_CMP_AND_WRITE,
+	OBJ_OP_WRITESAME,
 };
 
 enum obj_req_flags {
@@ -293,6 +294,7 @@ enum img_req_flags {
 	IMG_REQ_LAYERED,	/* ENOENT handling: normal = 0, layered = 1 */
 	IMG_REQ_DISCARD,	/* discard: normal = 0, discard request = 1 */
 	IMG_REQ_CMP_AND_WRITE,	/* normal = 0, compare and write request = 1 */
+	IMG_REQ_WRITESAME,	/* normal = 0, write same = 1 */
 };
 
 struct rbd_img_request {
@@ -858,6 +860,7 @@ static int obj_num_ops(enum obj_operatio
 {
 	switch (op_type) {
 	case OBJ_OP_WRITE:
+	case OBJ_OP_WRITESAME:
 		return 2;
 	case OBJ_OP_CMP_AND_WRITE:
 		return 3;
@@ -1553,6 +1556,17 @@ static bool img_request_write_test(struc
 	return test_bit(IMG_REQ_WRITE, &img_request->flags) != 0;
 }
 
+static void img_request_writesame_set(struct rbd_img_request *img_request)
+{
+	set_bit(IMG_REQ_WRITESAME, &img_request->flags);
+	smp_mb();
+}
+
+static bool img_request_writesame_test(struct rbd_img_request *img_request)
+{
+	smp_mb();
+	return test_bit(IMG_REQ_WRITESAME, &img_request->flags) != 0;
+}
 /*
  * Set the discard flag when the img_request is an discard request
  */
@@ -1619,6 +1633,7 @@ static bool img_request_cmp_and_write_te
 static bool img_request_is_write_type_test(struct rbd_img_request *img_request)
 {
 	return img_request_write_test(img_request) ||
+	       img_request_writesame_test(img_request) ||
 	       img_request_discard_test(img_request) ||
 	       img_request_cmp_and_write_test(img_request);
 }
@@ -1632,6 +1647,8 @@ rbd_img_request_op_type(struct rbd_img_r
 		return OBJ_OP_DISCARD;
 	else if (img_request_cmp_and_write_test(img_request))
 		return OBJ_OP_CMP_AND_WRITE;
+	else if (img_request_writesame_test(img_request))
+		return OBJ_OP_WRITESAME;
 	else
 		return OBJ_OP_READ;
 }
@@ -1813,7 +1830,8 @@ static void rbd_osd_req_callback(struct
 		break;
 	case CEPH_OSD_OP_SETALLOCHINT:
 		if (osd_req->r_ops[1].op == CEPH_OSD_OP_WRITE ||
-		    osd_req->r_ops[1].op == CEPH_OSD_OP_WRITEFULL)
+		    osd_req->r_ops[1].op == CEPH_OSD_OP_WRITEFULL ||
+		    osd_req->r_ops[1].op == CEPH_OSD_OP_WRITESAME)
 			rbd_osd_write_callback(obj_request);
 		else if (osd_req->r_ops[1].op == CEPH_OSD_OP_CMPEXT)
 			rbd_osd_cmpext_callback(obj_request, osd_req);
@@ -1822,6 +1840,7 @@ static void rbd_osd_req_callback(struct
 		break;
 	case CEPH_OSD_OP_WRITE:
 	case CEPH_OSD_OP_WRITEFULL:
+	case CEPH_OSD_OP_WRITESAME:
 		rbd_osd_write_callback(obj_request);
 		break;
 	case CEPH_OSD_OP_CMPEXT:
@@ -1921,7 +1940,8 @@ static struct ceph_osd_request *rbd_osd_
 
 	if (obj_request_img_data_test(obj_request) &&
 		(op_type == OBJ_OP_DISCARD || op_type == OBJ_OP_WRITE ||
-		 op_type == OBJ_OP_CMP_AND_WRITE)) {
+		 op_type == OBJ_OP_CMP_AND_WRITE ||
+		 op_type == OBJ_OP_WRITESAME)) {
 		struct rbd_img_request *img_request = obj_request->img_request;
 		if (op_type == OBJ_OP_WRITE) {
 			rbd_assert(img_request_write_test(img_request));
@@ -1929,6 +1949,8 @@ static struct ceph_osd_request *rbd_osd_
 			rbd_assert(img_request_discard_test(img_request));
 		} else if (op_type == OBJ_OP_CMP_AND_WRITE) {
 			rbd_assert(img_request_cmp_and_write_test(img_request));
+		} else if (op_type == OBJ_OP_WRITESAME) {
+			rbd_assert(img_request_writesame_test(img_request));
 		}
 		snapc = img_request->snapc;
 	}
@@ -1937,7 +1959,7 @@ static struct ceph_osd_request *rbd_osd_
 
 	return __rbd_osd_req_create(rbd_dev, snapc, num_ops,
 	    (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD ||
-	     op_type == OBJ_OP_CMP_AND_WRITE) ?
+	     op_type == OBJ_OP_CMP_AND_WRITE || op_type == OBJ_OP_WRITESAME) ?
 	    CEPH_OSD_FLAG_WRITE : CEPH_OSD_FLAG_READ, obj_request);
 }
 
@@ -2116,6 +2138,9 @@ static struct rbd_img_request *rbd_img_r
 	} else if (op_type == OBJ_OP_WRITE) {
 		img_request_write_set(img_request);
 		img_request->snapc = snapc;
+	} else if (op_type == OBJ_OP_WRITESAME) {
+		img_request_writesame_set(img_request);
+		img_request->snapc = snapc;
 	} else if (op_type == OBJ_OP_CMP_AND_WRITE) {
 		img_request_cmp_and_write_set(img_request);
 		img_request->snapc = snapc;
@@ -2331,12 +2356,21 @@ static void rbd_img_obj_request_fill(str
 		osd_req_op_alloc_hint_init(osd_request, num_ops,
 					object_size, object_size);
 		num_ops++;
+	} else if (op_type == OBJ_OP_WRITESAME) {
+		opcode = CEPH_OSD_OP_WRITESAME;
+		osd_req_op_alloc_hint_init(osd_request, num_ops,
+					   object_size, object_size);
+		num_ops++;
 	} else {
 		opcode = CEPH_OSD_OP_READ;
 	}
 
 	if (opcode == CEPH_OSD_OP_DELETE)
 		osd_req_op_init(osd_request, num_ops, opcode, 0);
+	else if (opcode == CEPH_OSD_OP_WRITESAME)
+		osd_req_op_writesame_init(osd_request, num_ops, opcode,
+					  offset, length, min_t(u64, length,
+					  obj_request->sg->length));
 	else
 		osd_req_op_extent_init(osd_request, num_ops, opcode,
 				       offset, length, 0, 0);
@@ -2347,13 +2381,22 @@ static void rbd_img_obj_request_fill(str
 	else if (obj_request->type == OBJ_REQUEST_BVECS)
 		osd_req_op_extent_osd_data_bvec_pos(osd_request, num_ops,
 					&obj_request->bvec_pos);
-	else if (obj_request->type == OBJ_REQUEST_SG)
-		osd_req_op_extent_osd_data_sg(osd_request, num_ops,
-					obj_request->sg,
-					obj_request->init_sg_offset, length);
+	else if (obj_request->type == OBJ_REQUEST_SG) {
+		if (op_type == OBJ_OP_WRITESAME)
+			osd_req_op_writesame_osd_data_sg(osd_request, num_ops,
+						obj_request->sg,
+						obj_request->init_sg_offset,
+						min_t(u64, length,
+						obj_request->sg->length));
+		else
+			osd_req_op_extent_osd_data_sg(osd_request, num_ops,
+						obj_request->sg,
+						obj_request->init_sg_offset,
+						length);
+	}
 
 	/* Discards are also writes */
-	if (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD)
+	if (img_request_is_write_type_test(img_request))
 		rbd_osd_req_format_write(obj_request);
 	else
 		rbd_osd_req_format_read(obj_request);