}
}
-static struct ceph_osd_req_op *rbd_osd_req_op_create(u16 opcode, ...)
-{
- struct ceph_osd_req_op *op;
- va_list args;
- size_t size;
-
- op = kzalloc(sizeof (*op), GFP_NOIO);
- if (!op)
- return NULL;
- op->op = opcode;
- va_start(args, opcode);
- switch (opcode) {
- case CEPH_OSD_OP_READ:
- case CEPH_OSD_OP_WRITE:
- /* rbd_osd_req_op_create(READ, offset, length) */
- /* rbd_osd_req_op_create(WRITE, offset, length) */
- op->extent.offset = va_arg(args, u64);
- op->extent.length = va_arg(args, u64);
- if (opcode == CEPH_OSD_OP_WRITE)
- op->payload_len = op->extent.length;
- break;
- case CEPH_OSD_OP_STAT:
- break;
- case CEPH_OSD_OP_CALL:
- /* rbd_osd_req_op_create(CALL, class, method, data, datalen) */
- op->cls.class_name = va_arg(args, char *);
- size = strlen(op->cls.class_name);
- rbd_assert(size <= (size_t) U8_MAX);
- op->cls.class_len = size;
- op->payload_len = size;
-
- op->cls.method_name = va_arg(args, char *);
- size = strlen(op->cls.method_name);
- rbd_assert(size <= (size_t) U8_MAX);
- op->cls.method_len = size;
- op->payload_len += size;
-
- op->cls.argc = 0;
- op->cls.indata = va_arg(args, void *);
- size = va_arg(args, size_t);
- rbd_assert(size <= (size_t) U32_MAX);
- op->cls.indata_len = (u32) size;
- op->payload_len += size;
- break;
- case CEPH_OSD_OP_NOTIFY_ACK:
- case CEPH_OSD_OP_WATCH:
- /* rbd_osd_req_op_create(NOTIFY_ACK, cookie, version) */
- /* rbd_osd_req_op_create(WATCH, cookie, version, flag) */
- op->watch.cookie = va_arg(args, u64);
- op->watch.ver = va_arg(args, u64);
- op->watch.ver = cpu_to_le64(op->watch.ver);
- if (opcode == CEPH_OSD_OP_WATCH && va_arg(args, int))
- op->watch.flag = (u8) 1;
- break;
- default:
- rbd_warn(NULL, "unsupported opcode %hu\n", opcode);
- kfree(op);
- op = NULL;
- break;
- }
- va_end(args);
-
- return op;
-}
-
-static void rbd_osd_req_op_destroy(struct ceph_osd_req_op *op)
-{
- kfree(op);
-}
-
static int rbd_obj_request_submit(struct ceph_osd_client *osdc,
struct rbd_obj_request *obj_request)
{
while (resid) {
const char *object_name;
unsigned int clone_size;
- struct ceph_osd_req_op *op;
+ struct ceph_osd_req_op op;
u64 offset;
u64 length;
* request. Note that the contents of the op are
* copied by rbd_osd_req_create().
*/
- op = rbd_osd_req_op_create(opcode, offset, length);
- if (!op)
- goto out_partial;
+ osd_req_op_extent_init(&op, opcode, offset, length, 0, 0);
obj_request->osd_req = rbd_osd_req_create(rbd_dev,
img_request->write_request,
- obj_request, op);
- rbd_osd_req_op_destroy(op);
+ obj_request, &op);
if (!obj_request->osd_req)
goto out_partial;
/* status and version are initially zero-filled */
u64 ver, u64 notify_id)
{
struct rbd_obj_request *obj_request;
- struct ceph_osd_req_op *op;
+ struct ceph_osd_req_op op;
struct ceph_osd_client *osdc;
int ret;
return -ENOMEM;
ret = -ENOMEM;
- op = rbd_osd_req_op_create(CEPH_OSD_OP_NOTIFY_ACK, notify_id, ver);
- if (!op)
- goto out;
+ osd_req_op_watch_init(&op, CEPH_OSD_OP_NOTIFY_ACK, notify_id, ver, 0);
obj_request->osd_req = rbd_osd_req_create(rbd_dev, false,
- obj_request, op);
- rbd_osd_req_op_destroy(op);
+ obj_request, &op);
if (!obj_request->osd_req)
goto out;
{
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
struct rbd_obj_request *obj_request;
- struct ceph_osd_req_op *op;
+ struct ceph_osd_req_op op;
int ret;
rbd_assert(start ^ !!rbd_dev->watch_event);
if (!obj_request)
goto out_cancel;
- op = rbd_osd_req_op_create(CEPH_OSD_OP_WATCH,
+ osd_req_op_watch_init(&op, CEPH_OSD_OP_WATCH,
rbd_dev->watch_event->cookie,
rbd_dev->header.obj_version, start);
- if (!op)
- goto out_cancel;
obj_request->osd_req = rbd_osd_req_create(rbd_dev, true,
- obj_request, op);
- rbd_osd_req_op_destroy(op);
+ obj_request, &op);
if (!obj_request->osd_req)
goto out_cancel;
{
struct rbd_obj_request *obj_request;
struct ceph_osd_client *osdc;
- struct ceph_osd_req_op *op;
+ struct ceph_osd_req_op op;
struct page **pages;
u32 page_count;
int ret;
obj_request->pages = pages;
obj_request->page_count = page_count;
- op = rbd_osd_req_op_create(CEPH_OSD_OP_CALL, class_name,
- method_name, outbound, outbound_size);
- if (!op)
- goto out;
+ osd_req_op_cls_init(&op, CEPH_OSD_OP_CALL, class_name, method_name,
+ outbound, outbound_size);
obj_request->osd_req = rbd_osd_req_create(rbd_dev, false,
- obj_request, op);
- rbd_osd_req_op_destroy(op);
+ obj_request, &op);
if (!obj_request->osd_req)
goto out;
char *buf, u64 *version)
{
- struct ceph_osd_req_op *op;
+ struct ceph_osd_req_op op;
struct rbd_obj_request *obj_request;
struct ceph_osd_client *osdc;
struct page **pages = NULL;
obj_request->pages = pages;
obj_request->page_count = page_count;
- op = rbd_osd_req_op_create(CEPH_OSD_OP_READ, offset, length);
- if (!op)
- goto out;
+ osd_req_op_extent_init(&op, CEPH_OSD_OP_READ, offset, length, 0, 0);
obj_request->osd_req = rbd_osd_req_create(rbd_dev, false,
- obj_request, op);
- rbd_osd_req_op_destroy(op);
+ obj_request, &op);
if (!obj_request->osd_req)
goto out;
}
}
+/*
+ * This is an osd op init function for opcodes that have no data or
+ * other information associated with them. It also serves as a
+ * common init routine for all the other init functions, below.
+ */
+void osd_req_op_init(struct ceph_osd_req_op *op, u16 opcode)
+{
+ BUG_ON(!osd_req_opcode_valid(opcode));
+
+ memset(op, 0, sizeof (*op));
+
+ op->op = opcode;
+}
+
+void osd_req_op_extent_init(struct ceph_osd_req_op *op, u16 opcode,
+ u64 offset, u64 length,
+ u64 truncate_size, u32 truncate_seq)
+{
+ size_t payload_len = 0;
+
+ BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE);
+
+ osd_req_op_init(op, opcode);
+
+ 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)
+ payload_len += length;
+
+ op->payload_len = payload_len;
+}
+EXPORT_SYMBOL(osd_req_op_extent_init);
+
+void osd_req_op_cls_init(struct ceph_osd_req_op *op, u16 opcode,
+ const char *class, const char *method,
+ const void *request_data, size_t request_data_size)
+{
+ size_t payload_len = 0;
+ size_t size;
+
+ BUG_ON(opcode != CEPH_OSD_OP_CALL);
+
+ osd_req_op_init(op, opcode);
+
+ op->cls.class_name = class;
+ size = strlen(class);
+ BUG_ON(size > (size_t) U8_MAX);
+ op->cls.class_len = size;
+ payload_len += size;
+
+ op->cls.method_name = method;
+ size = strlen(method);
+ BUG_ON(size > (size_t) U8_MAX);
+ op->cls.method_len = size;
+ payload_len += size;
+
+ op->cls.indata = request_data;
+ BUG_ON(request_data_size > (size_t) U32_MAX);
+ op->cls.indata_len = (u32) request_data_size;
+ payload_len += request_data_size;
+
+ op->cls.argc = 0; /* currently unused */
+
+ op->payload_len = payload_len;
+}
+EXPORT_SYMBOL(osd_req_op_cls_init);
+
+void osd_req_op_watch_init(struct ceph_osd_req_op *op, u16 opcode,
+ u64 cookie, u64 version, int flag)
+{
+ BUG_ON(opcode != CEPH_OSD_OP_NOTIFY_ACK && opcode != CEPH_OSD_OP_WATCH);
+
+ osd_req_op_init(op, opcode);
+
+ op->watch.cookie = cookie;
+ /* op->watch.ver = version; */ /* XXX 3847 */
+ op->watch.ver = cpu_to_le64(version);
+ if (opcode == CEPH_OSD_OP_WATCH && flag)
+ op->watch.flag = (u8) 1;
+}
+EXPORT_SYMBOL(osd_req_op_watch_init);
+
static u64 osd_req_encode_op(struct ceph_osd_request *req,
struct ceph_osd_op *dst,
struct ceph_osd_req_op *src)