4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "spdk/stdinc.h"
35 #include "spdk/string.h"
37 #include "spdk/util.h"
38 #include "spdk/bdev_module.h"
39 #include "spdk_internal/log.h"
41 #include "bdev_nvme.h"
43 #include "spdk/base64.h"
45 enum spdk_nvme_rpc_type
{
50 struct rpc_bdev_nvme_send_cmd_req
{
58 struct spdk_nvme_cmd
*cmdbuf
;
63 struct rpc_bdev_nvme_send_cmd_resp
{
69 struct rpc_bdev_nvme_send_cmd_ctx
{
70 struct spdk_jsonrpc_request
*jsonrpc_request
;
71 struct rpc_bdev_nvme_send_cmd_req req
;
72 struct rpc_bdev_nvme_send_cmd_resp resp
;
73 struct nvme_bdev_ctrlr
*nvme_bdev_ctrlr
;
74 struct spdk_io_channel
*ctrlr_io_ch
;
78 free_rpc_bdev_nvme_send_cmd_ctx(struct rpc_bdev_nvme_send_cmd_ctx
*ctx
)
83 free(ctx
->req
.cmdbuf
);
84 spdk_free(ctx
->req
.data
);
85 spdk_free(ctx
->req
.md
);
86 free(ctx
->resp
.cpl_text
);
87 free(ctx
->resp
.data_text
);
88 free(ctx
->resp
.md_text
);
93 rpc_bdev_nvme_send_cmd_resp_construct(struct rpc_bdev_nvme_send_cmd_resp
*resp
,
94 struct rpc_bdev_nvme_send_cmd_req
*req
,
95 const struct spdk_nvme_cpl
*cpl
)
97 resp
->cpl_text
= malloc(spdk_base64_get_encoded_strlen(sizeof(*cpl
)) + 1);
98 if (!resp
->cpl_text
) {
101 spdk_base64_urlsafe_encode(resp
->cpl_text
, cpl
, sizeof(*cpl
));
103 if (req
->data_direction
== SPDK_NVME_DATA_CONTROLLER_TO_HOST
) {
105 resp
->data_text
= malloc(spdk_base64_get_encoded_strlen(req
->data_len
) + 1);
106 if (!resp
->data_text
) {
109 spdk_base64_urlsafe_encode(resp
->data_text
, req
->data
, req
->data_len
);
112 resp
->md_text
= malloc(spdk_base64_get_encoded_strlen(req
->md_len
) + 1);
113 if (!resp
->md_text
) {
116 spdk_base64_urlsafe_encode(resp
->md_text
, req
->md
, req
->md_len
);
124 rpc_bdev_nvme_send_cmd_complete(struct rpc_bdev_nvme_send_cmd_ctx
*ctx
,
125 const struct spdk_nvme_cpl
*cpl
)
127 struct spdk_jsonrpc_request
*request
= ctx
->jsonrpc_request
;
128 struct spdk_json_write_ctx
*w
;
131 ret
= rpc_bdev_nvme_send_cmd_resp_construct(&ctx
->resp
, &ctx
->req
, cpl
);
133 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
134 spdk_strerror(-ret
));
138 w
= spdk_jsonrpc_begin_result(request
);
139 spdk_json_write_object_begin(w
);
140 spdk_json_write_named_string(w
, "cpl", ctx
->resp
.cpl_text
);
142 if (ctx
->resp
.data_text
) {
143 spdk_json_write_named_string(w
, "data", ctx
->resp
.data_text
);
146 if (ctx
->resp
.md_text
) {
147 spdk_json_write_named_string(w
, "metadata", ctx
->resp
.md_text
);
150 spdk_json_write_object_end(w
);
151 spdk_jsonrpc_end_result(request
, w
);
154 free_rpc_bdev_nvme_send_cmd_ctx(ctx
);
159 nvme_rpc_bdev_nvme_cb(void *ref
, const struct spdk_nvme_cpl
*cpl
)
161 struct rpc_bdev_nvme_send_cmd_ctx
*ctx
= (struct rpc_bdev_nvme_send_cmd_ctx
*)ref
;
163 if (ctx
->ctrlr_io_ch
) {
164 spdk_put_io_channel(ctx
->ctrlr_io_ch
);
165 ctx
->ctrlr_io_ch
= NULL
;
168 rpc_bdev_nvme_send_cmd_complete(ctx
, cpl
);
172 nvme_rpc_admin_cmd_bdev_nvme(struct rpc_bdev_nvme_send_cmd_ctx
*ctx
, struct spdk_nvme_cmd
*cmd
,
173 void *buf
, uint32_t nbytes
, uint32_t timeout_ms
)
175 struct nvme_bdev_ctrlr
*_nvme_ctrlr
= ctx
->nvme_bdev_ctrlr
;
178 ret
= spdk_nvme_ctrlr_cmd_admin_raw(_nvme_ctrlr
->ctrlr
, cmd
, buf
,
179 nbytes
, nvme_rpc_bdev_nvme_cb
, ctx
);
185 nvme_rpc_io_cmd_bdev_nvme(struct rpc_bdev_nvme_send_cmd_ctx
*ctx
, struct spdk_nvme_cmd
*cmd
,
186 void *buf
, uint32_t nbytes
, void *md_buf
, uint32_t md_len
,
189 struct nvme_bdev_ctrlr
*_nvme_ctrlr
= ctx
->nvme_bdev_ctrlr
;
190 struct spdk_nvme_qpair
*io_qpair
;
193 ctx
->ctrlr_io_ch
= spdk_get_io_channel(_nvme_ctrlr
->ctrlr
);
194 io_qpair
= bdev_nvme_get_io_qpair(ctx
->ctrlr_io_ch
);
196 ret
= spdk_nvme_ctrlr_cmd_io_raw_with_md(_nvme_ctrlr
->ctrlr
, io_qpair
,
197 cmd
, buf
, nbytes
, md_buf
, nvme_rpc_bdev_nvme_cb
, ctx
);
199 spdk_put_io_channel(ctx
->ctrlr_io_ch
);
207 rpc_bdev_nvme_send_cmd_exec(struct rpc_bdev_nvme_send_cmd_ctx
*ctx
)
209 struct rpc_bdev_nvme_send_cmd_req
*req
= &ctx
->req
;
212 switch (req
->cmd_type
) {
214 ret
= nvme_rpc_admin_cmd_bdev_nvme(ctx
, req
->cmdbuf
, req
->data
,
215 req
->data_len
, req
->timeout_ms
);
218 ret
= nvme_rpc_io_cmd_bdev_nvme(ctx
, req
->cmdbuf
, req
->data
,
219 req
->data_len
, req
->md
, req
->md_len
, req
->timeout_ms
);
227 rpc_decode_cmd_type(const struct spdk_json_val
*val
, void *out
)
231 if (spdk_json_strequal(val
, "admin") == true) {
232 *cmd_type
= NVME_ADMIN_CMD
;
233 } else if (spdk_json_strequal(val
, "io") == true) {
234 *cmd_type
= NVME_IO_CMD
;
236 SPDK_NOTICELOG("Invalid parameter value: cmd_type\n");
244 rpc_decode_data_direction(const struct spdk_json_val
*val
, void *out
)
246 int *data_direction
= out
;
248 if (spdk_json_strequal(val
, "h2c") == true) {
249 *data_direction
= SPDK_NVME_DATA_HOST_TO_CONTROLLER
;
250 } else if (spdk_json_strequal(val
, "c2h") == true) {
251 *data_direction
= SPDK_NVME_DATA_CONTROLLER_TO_HOST
;
253 SPDK_NOTICELOG("Invalid parameter value: data_direction\n");
261 rpc_decode_cmdbuf(const struct spdk_json_val
*val
, void *out
)
264 size_t text_strlen
, raw_len
;
265 struct spdk_nvme_cmd
*cmdbuf
, **_cmdbuf
= out
;
268 rc
= spdk_json_decode_string(val
, &text
);
270 return val
->type
== SPDK_JSON_VAL_STRING
? -ENOMEM
: -EINVAL
;
273 text_strlen
= strlen(text
);
274 raw_len
= spdk_base64_get_decoded_len(text_strlen
);
275 cmdbuf
= malloc(raw_len
);
281 rc
= spdk_base64_urlsafe_decode(cmdbuf
, &raw_len
, text
);
286 if (raw_len
!= sizeof(*cmdbuf
)) {
300 rpc_decode_data(const struct spdk_json_val
*val
, void *out
)
302 struct rpc_bdev_nvme_send_cmd_req
*req
= (struct rpc_bdev_nvme_send_cmd_req
*)out
;
307 rc
= spdk_json_decode_string(val
, &text
);
309 return val
->type
== SPDK_JSON_VAL_STRING
? -ENOMEM
: -EINVAL
;
311 text_strlen
= strlen(text
);
314 /* data_len is decoded by param "data_len" */
315 if (req
->data_len
!= spdk_base64_get_decoded_len(text_strlen
)) {
320 req
->data_len
= spdk_base64_get_decoded_len(text_strlen
);
321 req
->data
= spdk_malloc(req
->data_len
> 0x1000 ? req
->data_len
: 0x1000, 0x1000,
322 NULL
, SPDK_ENV_LCORE_ID_ANY
, SPDK_MALLOC_DMA
);
329 rc
= spdk_base64_urlsafe_decode(req
->data
, (size_t *)&req
->data_len
, text
);
337 rpc_decode_data_len(const struct spdk_json_val
*val
, void *out
)
339 struct rpc_bdev_nvme_send_cmd_req
*req
= (struct rpc_bdev_nvme_send_cmd_req
*)out
;
343 rc
= spdk_json_decode_uint32(val
, &data_len
);
349 /* data_len is decoded by param "data" */
350 if (req
->data_len
!= data_len
) {
354 req
->data_len
= data_len
;
355 req
->data
= spdk_malloc(req
->data_len
> 0x1000 ? req
->data_len
: 0x1000, 0x1000,
356 NULL
, SPDK_ENV_LCORE_ID_ANY
, SPDK_MALLOC_DMA
);
366 rpc_decode_metadata(const struct spdk_json_val
*val
, void *out
)
368 struct rpc_bdev_nvme_send_cmd_req
*req
= (struct rpc_bdev_nvme_send_cmd_req
*)out
;
373 rc
= spdk_json_decode_string(val
, &text
);
375 return rc
= val
->type
== SPDK_JSON_VAL_STRING
? -ENOMEM
: -EINVAL
;
377 text_strlen
= strlen(text
);
380 /* md_len is decoded by param "metadata_len" */
381 if (req
->md_len
!= spdk_base64_get_decoded_len(text_strlen
)) {
386 req
->md_len
= spdk_base64_get_decoded_len(text_strlen
);
387 req
->md
= spdk_malloc(req
->md_len
, 0x1000, NULL
,
388 SPDK_ENV_LCORE_ID_ANY
, SPDK_MALLOC_DMA
);
395 rc
= spdk_base64_urlsafe_decode(req
->md
, (size_t *)&req
->md_len
, text
);
403 rpc_decode_metadata_len(const struct spdk_json_val
*val
, void *out
)
405 struct rpc_bdev_nvme_send_cmd_req
*req
= (struct rpc_bdev_nvme_send_cmd_req
*)out
;
409 rc
= spdk_json_decode_uint32(val
, &md_len
);
415 /* md_len is decoded by param "metadata" */
416 if (req
->md_len
!= md_len
) {
420 req
->md_len
= md_len
;
421 req
->md
= spdk_malloc(req
->md_len
, 0x1000, NULL
,
422 SPDK_ENV_LCORE_ID_ANY
, SPDK_MALLOC_DMA
);
431 static const struct spdk_json_object_decoder rpc_bdev_nvme_send_cmd_req_decoders
[] = {
432 {"name", offsetof(struct rpc_bdev_nvme_send_cmd_req
, name
), spdk_json_decode_string
},
433 {"cmd_type", offsetof(struct rpc_bdev_nvme_send_cmd_req
, cmd_type
), rpc_decode_cmd_type
},
434 {"data_direction", offsetof(struct rpc_bdev_nvme_send_cmd_req
, data_direction
), rpc_decode_data_direction
},
435 {"cmdbuf", offsetof(struct rpc_bdev_nvme_send_cmd_req
, cmdbuf
), rpc_decode_cmdbuf
},
436 {"timeout_ms", offsetof(struct rpc_bdev_nvme_send_cmd_req
, timeout_ms
), spdk_json_decode_uint32
, true},
437 {"data_len", 0, rpc_decode_data_len
, true},
438 {"metadata_len", 0, rpc_decode_metadata_len
, true},
439 {"data", 0, rpc_decode_data
, true},
440 {"metadata", 0, rpc_decode_metadata
, true},
444 rpc_bdev_nvme_send_cmd(struct spdk_jsonrpc_request
*request
,
445 const struct spdk_json_val
*params
)
447 struct rpc_bdev_nvme_send_cmd_ctx
*ctx
;
450 ctx
= calloc(1, sizeof(*ctx
));
452 SPDK_ERRLOG("Failed at Malloc ctx\n");
453 error_code
= SPDK_JSONRPC_ERROR_INTERNAL_ERROR
;
458 if (spdk_json_decode_object(params
, rpc_bdev_nvme_send_cmd_req_decoders
,
459 SPDK_COUNTOF(rpc_bdev_nvme_send_cmd_req_decoders
),
461 SPDK_ERRLOG("spdk_json_decode_object failed\n");
462 error_code
= SPDK_JSONRPC_ERROR_INVALID_PARAMS
;
467 ctx
->nvme_bdev_ctrlr
= nvme_bdev_ctrlr_get_by_name(ctx
->req
.name
);
468 if (ctx
->nvme_bdev_ctrlr
== NULL
) {
469 SPDK_ERRLOG("Failed at device lookup\n");
470 error_code
= SPDK_JSONRPC_ERROR_INVALID_PARAMS
;
475 ctx
->jsonrpc_request
= request
;
477 ret
= rpc_bdev_nvme_send_cmd_exec(ctx
);
479 SPDK_NOTICELOG("Failed at rpc_bdev_nvme_send_cmd_exec\n");
480 error_code
= SPDK_JSONRPC_ERROR_INTERNAL_ERROR
;
487 spdk_jsonrpc_send_error_response(request
, error_code
, spdk_strerror(-ret
));
488 free_rpc_bdev_nvme_send_cmd_ctx(ctx
);
491 SPDK_RPC_REGISTER("bdev_nvme_send_cmd", rpc_bdev_nvme_send_cmd
, SPDK_RPC_RUNTIME
)
492 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_send_cmd
, send_nvme_cmd
)