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
-EILSEQ, the offset in the buffer where it occurred, and the buffer.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Acked-by: David Disseldorp <ddiss@suse.de>
---
include/linux/ceph/rados.h | 2 ++
net/ceph/osd_client.c | 23 ++++++++++++++++++++---
2 files changed, 22 insertions(+), 3 deletions(-)
--- a/include/linux/ceph/rados.h
+++ b/include/linux/ceph/rados.h
@@ -212,6 +212,8 @@ extern const char *ceph_osd_state_name(i
/* sync */ \
f(SYNC_READ, __CEPH_OSD_OP(RD, DATA, 11), "sync_read") \
\
+ f(CMPEXT, __CEPH_OSD_OP(RD, DATA, 31), "cmpext") \
+ \
/* write */ \
f(WRITE, __CEPH_OSD_OP(WR, DATA, 1), "write") \
f(WRITEFULL, __CEPH_OSD_OP(WR, DATA, 2), "writefull") \
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -194,6 +194,7 @@ void osd_req_op_extent_osd_data_pages(st
case CEPH_OSD_OP_READ:
case CEPH_OSD_OP_ZERO:
case CEPH_OSD_OP_TRUNCATE:
+ case CEPH_OSD_OP_CMPEXT:
ceph_osd_data_pages_init(&op->extent.response_data, pages,
length, alignment, pages_from_pool,
own_pages);
@@ -269,6 +270,7 @@ void osd_req_op_extent_osd_data_sg(struc
sgl, init_sg_offset, length);
break;
case CEPH_OSD_OP_WRITE:
+ case CEPH_OSD_OP_CMPEXT:
ceph_osd_data_sg_init(&op->extent.request_data,
sgl, init_sg_offset, length);
break;
@@ -372,6 +374,10 @@ static void osd_req_op_data_release(stru
case CEPH_OSD_OP_WRITEFULL:
ceph_osd_data_release(&op->extent.request_data);
break;
+ case CEPH_OSD_OP_CMPEXT:
+ ceph_osd_data_release(&op->extent.response_data);
+ ceph_osd_data_release(&op->extent.request_data);
+ break;
case CEPH_OSD_OP_CALL:
ceph_osd_data_release(&op->cls.request_info);
ceph_osd_data_release(&op->cls.request_data);
@@ -571,13 +577,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->payload_len = payload_len;
@@ -762,6 +769,7 @@ static u64 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 =
@@ -774,6 +782,14 @@ static u64 osd_req_encode_op(struct ceph
ceph_osdc_msg_data_add(req->r_request, osd_data);
request_data_len = src->extent.length;
+ } else if (src->op == CEPH_OSD_OP_CMPEXT) {
+ osd_data = &src->extent.request_data;
+ ceph_osdc_msg_data_add(req->r_request, osd_data);
+
+ osd_data = &src->extent.response_data;
+ ceph_osdc_msg_data_add(req->r_reply, osd_data);
+
+ request_data_len = src->extent.length;
} else {
osd_data = &src->extent.response_data;
ceph_osdc_msg_data_add(req->r_reply, osd_data);
@@ -871,7 +887,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);