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

This adds support for the CMPEXT request. The request will compare
extent.length bytes and compare them to extent.length bytes at
extent.offset on disk. If there is a miscompare the osd will return
-MAX_ERRNO - offset_of_miscompare.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Acked-by: David Disseldorp <ddiss@suse.de>
[ddiss@suse.de: reworked to use new API, which isn't bidirectional.]
Acked-by: Luis Henriques <lhenriques@suse.com>
[luis: updated get_num_data_items() introduced by commit 0d9c1ab3be4c
 ("libceph: preallocate message data items")]
[luis: rebased atop 26f887e0a3c4 ("libceph, rbd, ceph: move
 ceph_osdc_alloc_messages() calls")]
---
 include/linux/ceph/rados.h |    3 +++
 net/ceph/osd_client.c      |   18 +++++++++++++-----
 2 files changed, 16 insertions(+), 5 deletions(-)

--- a/include/linux/ceph/rados.h
+++ b/include/linux/ceph/rados.h
@@ -269,6 +269,9 @@ extern const char *ceph_osd_state_name(i
 	/* hints */							    \
 	f(SETALLOCHINT,	__CEPH_OSD_OP(WR, DATA, 35),	"set-alloc-hint")   \
 									    \
+	/* ESX/SCSI */							    \
+	f(CMPEXT,       __CEPH_OSD_OP(RD, DATA, 32),    "cmpext")	    \
+									    \
 	/** multi **/							    \
 	f(CLONERANGE,	__CEPH_OSD_OP(WR, MULTI, 1),	"clonerange")	    \
 	f(ASSERT_SRC_VERSION, __CEPH_OSD_OP(RD, MULTI, 2), "assert-src-version") \
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -407,6 +407,7 @@ static void osd_req_op_data_release(stru
 	case CEPH_OSD_OP_READ:
 	case CEPH_OSD_OP_WRITE:
 	case CEPH_OSD_OP_WRITEFULL:
+	case CEPH_OSD_OP_CMPEXT:
 		ceph_osd_data_release(&op->extent.osd_data);
 		break;
 	case CEPH_OSD_OP_CALL:
@@ -724,6 +725,7 @@ static void get_num_data_items(struct ce
 		case CEPH_OSD_OP_SETXATTR:
 		case CEPH_OSD_OP_CMPXATTR:
 		case CEPH_OSD_OP_NOTIFY_ACK:
+		case CEPH_OSD_OP_CMPEXT:
 			*num_request_data_items += 1;
 			break;
 
@@ -805,13 +807,14 @@ void osd_req_op_extent_init(struct ceph_
 
 	BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE &&
 	       opcode != CEPH_OSD_OP_WRITEFULL && opcode != CEPH_OSD_OP_ZERO &&
-	       opcode != CEPH_OSD_OP_TRUNCATE);
+	       opcode != CEPH_OSD_OP_TRUNCATE && opcode != CEPH_OSD_OP_CMPEXT);
 
 	op->extent.offset = offset;
 	op->extent.length = length;
 	op->extent.truncate_size = truncate_size;
 	op->extent.truncate_seq = truncate_seq;
-	if (opcode == CEPH_OSD_OP_WRITE || opcode == CEPH_OSD_OP_WRITEFULL)
+	if (opcode == CEPH_OSD_OP_WRITE || opcode == CEPH_OSD_OP_WRITEFULL
+						|| opcode == CEPH_OSD_OP_CMPEXT)
 		payload_len += length;
 
 	op->indata_len = payload_len;
@@ -833,7 +836,8 @@ void osd_req_op_extent_update(struct cep
 	BUG_ON(length > previous);
 
 	op->extent.length = length;
-	if (op->op == CEPH_OSD_OP_WRITE || op->op == CEPH_OSD_OP_WRITEFULL)
+	if (op->op == CEPH_OSD_OP_WRITE || op->op == CEPH_OSD_OP_WRITEFULL
+						|| op->op == CEPH_OSD_OP_CMPEXT)
 		op->indata_len -= previous - length;
 }
 EXPORT_SYMBOL(osd_req_op_extent_update);
@@ -855,7 +859,8 @@ void osd_req_op_extent_dup_last(struct c
 	op->extent.offset += offset_inc;
 	op->extent.length -= offset_inc;
 
-	if (op->op == CEPH_OSD_OP_WRITE || op->op == CEPH_OSD_OP_WRITEFULL)
+	if (op->op == CEPH_OSD_OP_WRITE || op->op == CEPH_OSD_OP_WRITEFULL
+						|| op->op == CEPH_OSD_OP_CMPEXT)
 		op->indata_len -= offset_inc;
 }
 EXPORT_SYMBOL(osd_req_op_extent_dup_last);
@@ -1007,6 +1012,7 @@ static u32 osd_req_encode_op(struct ceph
 	case CEPH_OSD_OP_WRITEFULL:
 	case CEPH_OSD_OP_ZERO:
 	case CEPH_OSD_OP_TRUNCATE:
+	case CEPH_OSD_OP_CMPEXT:
 		dst->extent.offset = cpu_to_le64(src->extent.offset);
 		dst->extent.length = cpu_to_le64(src->extent.length);
 		dst->extent.truncate_size =
@@ -1090,7 +1096,8 @@ struct ceph_osd_request *ceph_osdc_new_r
 
 	BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE &&
 	       opcode != CEPH_OSD_OP_ZERO && opcode != CEPH_OSD_OP_TRUNCATE &&
-	       opcode != CEPH_OSD_OP_CREATE && opcode != CEPH_OSD_OP_DELETE);
+	       opcode != CEPH_OSD_OP_CREATE && opcode != CEPH_OSD_OP_DELETE &&
+	       opcode != CEPH_OSD_OP_CMPEXT);
 
 	req = ceph_osdc_alloc_request(osdc, snapc, num_ops, use_mempool,
 					GFP_NOFS);
@@ -1966,6 +1973,7 @@ static void setup_request_data(struct ce
 		/* request */
 		case CEPH_OSD_OP_WRITE:
 		case CEPH_OSD_OP_WRITEFULL:
+		case CEPH_OSD_OP_CMPEXT:
 			WARN_ON(op->indata_len != op->extent.length);
 			ceph_osdc_msg_data_add(request_msg,
 					       &op->extent.osd_data);