1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2018-2019 Mellanox Technologies LTD. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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 16 * distribution. 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. 20 * 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. 32 */ 33 34 #include "spdk/bdev.h" 35 #include "spdk/log.h" 36 #include "spdk/rpc.h" 37 #include "spdk/env.h" 38 #include "spdk/nvme.h" 39 #include "spdk/nvmf.h" 40 #include "spdk/string.h" 41 #include "spdk/util.h" 42 43 #include "spdk_internal/event.h" 44 #include "spdk_internal/log.h" 45 46 static int 47 json_write_hex_str(struct spdk_json_write_ctx *w, const void *data, size_t size) 48 { 49 static const char hex_char[16] = "0123456789ABCDEF"; 50 const uint8_t *buf = data; 51 char *str, *out; 52 int rc; 53 54 str = malloc(size * 2 + 1); 55 if (str == NULL) { 56 return -1; 57 } 58 59 out = str; 60 while (size--) { 61 unsigned byte = *buf++; 62 63 out[0] = hex_char[(byte >> 4) & 0xF]; 64 out[1] = hex_char[byte & 0xF]; 65 66 out += 2; 67 } 68 *out = '\0'; 69 70 rc = spdk_json_write_string(w, str); 71 free(str); 72 73 return rc; 74 } 75 76 static int 77 hex_nybble_to_num(char c) 78 { 79 if (c >= '0' && c <= '9') { 80 return c - '0'; 81 } 82 83 if (c >= 'a' && c <= 'f') { 84 return c - 'a' + 0xA; 85 } 86 87 if (c >= 'A' && c <= 'F') { 88 return c - 'A' + 0xA; 89 } 90 91 return -1; 92 } 93 94 static int 95 hex_byte_to_num(const char *str) 96 { 97 int hi, lo; 98 99 hi = hex_nybble_to_num(str[0]); 100 if (hi < 0) { 101 return hi; 102 } 103 104 lo = hex_nybble_to_num(str[1]); 105 if (lo < 0) { 106 return lo; 107 } 108 109 return hi * 16 + lo; 110 } 111 112 static int 113 decode_hex_string_be(const char *str, uint8_t *out, size_t size) 114 { 115 size_t i; 116 117 /* Decode a string in "ABCDEF012345" format to its binary representation */ 118 for (i = 0; i < size; i++) { 119 int num = hex_byte_to_num(str); 120 121 if (num < 0) { 122 /* Invalid hex byte or end of string */ 123 return -1; 124 } 125 126 out[i] = (uint8_t)num; 127 str += 2; 128 } 129 130 if (i != size || *str != '\0') { 131 /* Length mismatch */ 132 return -1; 133 } 134 135 return 0; 136 } 137 138 static int 139 decode_ns_nguid(const struct spdk_json_val *val, void *out) 140 { 141 char *str = NULL; 142 int rc; 143 144 rc = spdk_json_decode_string(val, &str); 145 if (rc == 0) { 146 /* 16-byte NGUID */ 147 rc = decode_hex_string_be(str, out, 16); 148 } 149 150 free(str); 151 return rc; 152 } 153 154 static int 155 decode_ns_eui64(const struct spdk_json_val *val, void *out) 156 { 157 char *str = NULL; 158 int rc; 159 160 rc = spdk_json_decode_string(val, &str); 161 if (rc == 0) { 162 /* 8-byte EUI-64 */ 163 rc = decode_hex_string_be(str, out, 8); 164 } 165 166 free(str); 167 return rc; 168 } 169 170 static int 171 decode_ns_uuid(const struct spdk_json_val *val, void *out) 172 { 173 char *str = NULL; 174 int rc; 175 176 rc = spdk_json_decode_string(val, &str); 177 if (rc == 0) { 178 rc = spdk_uuid_parse(out, str); 179 } 180 181 free(str); 182 return rc; 183 } 184 185 struct rpc_get_subsystem { 186 char *tgt_name; 187 }; 188 189 static const struct spdk_json_object_decoder rpc_get_subsystem_decoders[] = { 190 {"tgt_name", offsetof(struct rpc_get_subsystem, tgt_name), spdk_json_decode_string, true}, 191 }; 192 193 static void 194 dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *subsystem) 195 { 196 struct spdk_nvmf_host *host; 197 struct spdk_nvmf_listener *listener; 198 199 spdk_json_write_object_begin(w); 200 201 spdk_json_write_named_string(w, "nqn", spdk_nvmf_subsystem_get_nqn(subsystem)); 202 spdk_json_write_name(w, "subtype"); 203 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) { 204 spdk_json_write_string(w, "NVMe"); 205 } else { 206 spdk_json_write_string(w, "Discovery"); 207 } 208 209 spdk_json_write_named_array_begin(w, "listen_addresses"); 210 211 for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL; 212 listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) { 213 const struct spdk_nvme_transport_id *trid; 214 const char *trtype; 215 const char *adrfam; 216 217 trid = spdk_nvmf_listener_get_trid(listener); 218 219 spdk_json_write_object_begin(w); 220 trtype = spdk_nvme_transport_id_trtype_str(trid->trtype); 221 if (trtype == NULL) { 222 trtype = "unknown"; 223 } 224 adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam); 225 if (adrfam == NULL) { 226 adrfam = "unknown"; 227 } 228 /* NOTE: "transport" is kept for compatibility; new code should use "trtype" */ 229 spdk_json_write_named_string(w, "transport", trtype); 230 spdk_json_write_named_string(w, "trtype", trtype); 231 spdk_json_write_named_string(w, "adrfam", adrfam); 232 spdk_json_write_named_string(w, "traddr", trid->traddr); 233 spdk_json_write_named_string(w, "trsvcid", trid->trsvcid); 234 spdk_json_write_object_end(w); 235 } 236 spdk_json_write_array_end(w); 237 238 spdk_json_write_named_bool(w, "allow_any_host", 239 spdk_nvmf_subsystem_get_allow_any_host(subsystem)); 240 241 spdk_json_write_named_array_begin(w, "hosts"); 242 243 for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL; 244 host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) { 245 spdk_json_write_object_begin(w); 246 spdk_json_write_named_string(w, "nqn", spdk_nvmf_host_get_nqn(host)); 247 spdk_json_write_object_end(w); 248 } 249 spdk_json_write_array_end(w); 250 251 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) { 252 struct spdk_nvmf_ns *ns; 253 struct spdk_nvmf_ns_opts ns_opts; 254 uint32_t max_namespaces; 255 256 spdk_json_write_named_string(w, "serial_number", spdk_nvmf_subsystem_get_sn(subsystem)); 257 258 spdk_json_write_named_string(w, "model_number", spdk_nvmf_subsystem_get_mn(subsystem)); 259 260 max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem); 261 if (max_namespaces != 0) { 262 spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces); 263 } 264 265 spdk_json_write_named_array_begin(w, "namespaces"); 266 for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL; 267 ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) { 268 spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts)); 269 spdk_json_write_object_begin(w); 270 spdk_json_write_named_int32(w, "nsid", spdk_nvmf_ns_get_id(ns)); 271 spdk_json_write_named_string(w, "bdev_name", 272 spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); 273 /* NOTE: "name" is kept for compatibility only - new code should use bdev_name. */ 274 spdk_json_write_named_string(w, "name", 275 spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); 276 277 if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) { 278 spdk_json_write_name(w, "nguid"); 279 json_write_hex_str(w, ns_opts.nguid, sizeof(ns_opts.nguid)); 280 } 281 282 if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) { 283 spdk_json_write_name(w, "eui64"); 284 json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64)); 285 } 286 287 if (!spdk_mem_all_zero(&ns_opts.uuid, sizeof(ns_opts.uuid))) { 288 char uuid_str[SPDK_UUID_STRING_LEN]; 289 290 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid); 291 spdk_json_write_named_string(w, "uuid", uuid_str); 292 } 293 294 spdk_json_write_object_end(w); 295 } 296 spdk_json_write_array_end(w); 297 } 298 spdk_json_write_object_end(w); 299 } 300 301 static void 302 spdk_rpc_nvmf_get_subsystems(struct spdk_jsonrpc_request *request, 303 const struct spdk_json_val *params) 304 { 305 struct rpc_get_subsystem req = { 0 }; 306 struct spdk_json_write_ctx *w; 307 struct spdk_nvmf_subsystem *subsystem; 308 struct spdk_nvmf_tgt *tgt; 309 310 if (params) { 311 if (spdk_json_decode_object(params, rpc_get_subsystem_decoders, 312 SPDK_COUNTOF(rpc_get_subsystem_decoders), 313 &req)) { 314 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 315 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 316 return; 317 } 318 } 319 320 tgt = spdk_nvmf_get_tgt(req.tgt_name); 321 if (!tgt) { 322 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 323 "Unable to find a target."); 324 free(req.tgt_name); 325 return; 326 } 327 328 w = spdk_jsonrpc_begin_result(request); 329 spdk_json_write_array_begin(w); 330 subsystem = spdk_nvmf_subsystem_get_first(tgt); 331 while (subsystem) { 332 dump_nvmf_subsystem(w, subsystem); 333 subsystem = spdk_nvmf_subsystem_get_next(subsystem); 334 } 335 spdk_json_write_array_end(w); 336 spdk_jsonrpc_end_result(request, w); 337 free(req.tgt_name); 338 } 339 SPDK_RPC_REGISTER("nvmf_get_subsystems", spdk_rpc_nvmf_get_subsystems, SPDK_RPC_RUNTIME) 340 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(nvmf_get_subsystems, get_nvmf_subsystems) 341 342 struct rpc_subsystem_create { 343 char *nqn; 344 char *serial_number; 345 char *model_number; 346 char *tgt_name; 347 uint32_t max_namespaces; 348 bool allow_any_host; 349 }; 350 351 static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = { 352 {"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string}, 353 {"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true}, 354 {"model_number", offsetof(struct rpc_subsystem_create, model_number), spdk_json_decode_string, true}, 355 {"tgt_name", offsetof(struct rpc_subsystem_create, tgt_name), spdk_json_decode_string, true}, 356 {"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true}, 357 {"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true}, 358 }; 359 360 static void 361 spdk_rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem, 362 void *cb_arg, int status) 363 { 364 struct spdk_jsonrpc_request *request = cb_arg; 365 struct spdk_json_write_ctx *w; 366 367 w = spdk_jsonrpc_begin_result(request); 368 spdk_json_write_bool(w, true); 369 spdk_jsonrpc_end_result(request, w); 370 } 371 372 static void 373 spdk_rpc_nvmf_create_subsystem(struct spdk_jsonrpc_request *request, 374 const struct spdk_json_val *params) 375 { 376 struct rpc_subsystem_create *req; 377 struct spdk_nvmf_subsystem *subsystem; 378 struct spdk_nvmf_tgt *tgt; 379 380 req = calloc(1, sizeof(*req)); 381 if (!req) { 382 goto invalid; 383 } 384 385 if (spdk_json_decode_object(params, rpc_subsystem_create_decoders, 386 SPDK_COUNTOF(rpc_subsystem_create_decoders), 387 req)) { 388 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 389 goto invalid; 390 } 391 392 tgt = spdk_nvmf_get_tgt(req->tgt_name); 393 if (!tgt) { 394 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 395 "Unable to find a target."); 396 goto invalid_custom_response; 397 } 398 399 subsystem = spdk_nvmf_subsystem_create(tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME, 400 req->max_namespaces); 401 if (!subsystem) { 402 goto invalid; 403 } 404 405 if (req->serial_number) { 406 if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) { 407 SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number); 408 goto invalid; 409 } 410 } 411 412 if (req->model_number) { 413 if (spdk_nvmf_subsystem_set_mn(subsystem, req->model_number)) { 414 SPDK_ERRLOG("Subsystem %s: invalid model number '%s'\n", req->nqn, req->model_number); 415 goto invalid; 416 } 417 } 418 419 spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host); 420 421 free(req->nqn); 422 free(req->tgt_name); 423 free(req->serial_number); 424 free(req->model_number); 425 free(req); 426 427 spdk_nvmf_subsystem_start(subsystem, 428 spdk_rpc_nvmf_subsystem_started, 429 request); 430 431 return; 432 433 invalid: 434 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 435 invalid_custom_response: 436 if (req) { 437 free(req->nqn); 438 free(req->tgt_name); 439 free(req->serial_number); 440 free(req->model_number); 441 } 442 free(req); 443 } 444 SPDK_RPC_REGISTER("nvmf_create_subsystem", spdk_rpc_nvmf_create_subsystem, SPDK_RPC_RUNTIME) 445 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(nvmf_create_subsystem, nvmf_subsystem_create) 446 447 struct rpc_delete_subsystem { 448 char *nqn; 449 char *tgt_name; 450 }; 451 452 static void 453 free_rpc_delete_subsystem(struct rpc_delete_subsystem *r) 454 { 455 free(r->nqn); 456 free(r->tgt_name); 457 } 458 459 static void 460 spdk_rpc_nvmf_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem, 461 void *cb_arg, int status) 462 { 463 struct spdk_jsonrpc_request *request = cb_arg; 464 struct spdk_json_write_ctx *w; 465 466 spdk_nvmf_subsystem_destroy(subsystem); 467 468 w = spdk_jsonrpc_begin_result(request); 469 spdk_json_write_bool(w, true); 470 spdk_jsonrpc_end_result(request, w); 471 } 472 473 static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = { 474 {"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string}, 475 {"tgt_name", offsetof(struct rpc_delete_subsystem, tgt_name), spdk_json_decode_string, true}, 476 }; 477 478 static void 479 spdk_rpc_nvmf_delete_subsystem(struct spdk_jsonrpc_request *request, 480 const struct spdk_json_val *params) 481 { 482 struct rpc_delete_subsystem req = { 0 }; 483 struct spdk_nvmf_subsystem *subsystem; 484 struct spdk_nvmf_tgt *tgt; 485 486 if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders, 487 SPDK_COUNTOF(rpc_delete_subsystem_decoders), 488 &req)) { 489 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 490 goto invalid; 491 } 492 493 if (req.nqn == NULL) { 494 SPDK_ERRLOG("missing name param\n"); 495 goto invalid; 496 } 497 498 tgt = spdk_nvmf_get_tgt(req.tgt_name); 499 if (!tgt) { 500 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 501 "Unable to find a target."); 502 goto invalid_custom_response; 503 } 504 505 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn); 506 if (!subsystem) { 507 goto invalid; 508 } 509 510 free_rpc_delete_subsystem(&req); 511 512 spdk_nvmf_subsystem_stop(subsystem, 513 spdk_rpc_nvmf_subsystem_stopped, 514 request); 515 516 return; 517 518 invalid: 519 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 520 invalid_custom_response: 521 free_rpc_delete_subsystem(&req); 522 } 523 SPDK_RPC_REGISTER("nvmf_delete_subsystem", spdk_rpc_nvmf_delete_subsystem, SPDK_RPC_RUNTIME) 524 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(nvmf_delete_subsystem, delete_nvmf_subsystem) 525 526 struct rpc_listen_address { 527 char *transport; 528 char *adrfam; 529 char *traddr; 530 char *trsvcid; 531 }; 532 533 #define RPC_MAX_LISTEN_ADDRESSES 255 534 #define RPC_MAX_NAMESPACES 255 535 536 struct rpc_listen_addresses { 537 size_t num_listen_address; 538 struct rpc_listen_address addresses[RPC_MAX_LISTEN_ADDRESSES]; 539 }; 540 541 static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = { 542 /* NOTE: "transport" is kept for compatibility; new code should use "trtype" */ 543 {"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true}, 544 {"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true}, 545 {"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true}, 546 {"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string}, 547 {"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string}, 548 }; 549 550 static int 551 decode_rpc_listen_address(const struct spdk_json_val *val, void *out) 552 { 553 struct rpc_listen_address *req = (struct rpc_listen_address *)out; 554 if (spdk_json_decode_object(val, rpc_listen_address_decoders, 555 SPDK_COUNTOF(rpc_listen_address_decoders), 556 req)) { 557 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 558 return -1; 559 } 560 return 0; 561 } 562 563 static void 564 free_rpc_listen_address(struct rpc_listen_address *r) 565 { 566 free(r->transport); 567 free(r->adrfam); 568 free(r->traddr); 569 free(r->trsvcid); 570 } 571 572 enum nvmf_rpc_listen_op { 573 NVMF_RPC_LISTEN_ADD, 574 NVMF_RPC_LISTEN_REMOVE, 575 }; 576 577 struct nvmf_rpc_listener_ctx { 578 char *nqn; 579 char *tgt_name; 580 struct spdk_nvmf_tgt *tgt; 581 struct spdk_nvmf_subsystem *subsystem; 582 struct rpc_listen_address address; 583 584 struct spdk_jsonrpc_request *request; 585 struct spdk_nvme_transport_id trid; 586 enum nvmf_rpc_listen_op op; 587 bool response_sent; 588 }; 589 590 static const struct spdk_json_object_decoder nvmf_rpc_listener_decoder[] = { 591 {"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string}, 592 {"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address}, 593 {"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true}, 594 }; 595 596 static void 597 nvmf_rpc_listener_ctx_free(struct nvmf_rpc_listener_ctx *ctx) 598 { 599 free(ctx->nqn); 600 free(ctx->tgt_name); 601 free_rpc_listen_address(&ctx->address); 602 free(ctx); 603 } 604 605 static void 606 nvmf_rpc_listen_resumed(struct spdk_nvmf_subsystem *subsystem, 607 void *cb_arg, int status) 608 { 609 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 610 struct spdk_jsonrpc_request *request; 611 struct spdk_json_write_ctx *w; 612 613 request = ctx->request; 614 if (ctx->response_sent) { 615 /* If an error occurred, the response has already been sent. */ 616 nvmf_rpc_listener_ctx_free(ctx); 617 return; 618 } 619 620 nvmf_rpc_listener_ctx_free(ctx); 621 622 w = spdk_jsonrpc_begin_result(request); 623 spdk_json_write_bool(w, true); 624 spdk_jsonrpc_end_result(request, w); 625 } 626 627 static void 628 nvmf_rpc_tgt_listen(void *cb_arg, int status) 629 { 630 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 631 632 if (status) { 633 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 634 "Invalid parameters"); 635 ctx->response_sent = true; 636 } else { 637 if (spdk_nvmf_subsystem_add_listener(ctx->subsystem, &ctx->trid)) { 638 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 639 "Invalid parameters"); 640 ctx->response_sent = true; 641 } 642 } 643 644 if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) { 645 if (!ctx->response_sent) { 646 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 647 } 648 nvmf_rpc_listener_ctx_free(ctx); 649 /* Can't really do anything to recover here - subsystem will remain paused. */ 650 } 651 } 652 653 static void 654 nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem, 655 void *cb_arg, int status) 656 { 657 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 658 659 if (ctx->op == NVMF_RPC_LISTEN_ADD) { 660 spdk_nvmf_tgt_listen(ctx->tgt, &ctx->trid, nvmf_rpc_tgt_listen, ctx); 661 return; 662 } else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) { 663 if (spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid)) { 664 SPDK_ERRLOG("Unable to remove listener.\n"); 665 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 666 "Invalid parameters"); 667 ctx->response_sent = true; 668 } 669 } else { 670 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 671 "Invalid parameters"); 672 ctx->response_sent = true; 673 } 674 675 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) { 676 if (!ctx->response_sent) { 677 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 678 } 679 nvmf_rpc_listener_ctx_free(ctx); 680 /* Can't really do anything to recover here - subsystem will remain paused. */ 681 } 682 } 683 684 static int 685 rpc_listen_address_to_trid(const struct rpc_listen_address *address, 686 struct spdk_nvme_transport_id *trid) 687 { 688 size_t len; 689 690 memset(trid, 0, sizeof(*trid)); 691 692 if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) { 693 SPDK_ERRLOG("Invalid transport type: %s\n", address->transport); 694 return -EINVAL; 695 } 696 697 if (address->adrfam) { 698 if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) { 699 SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam); 700 return -EINVAL; 701 } 702 } else { 703 trid->adrfam = SPDK_NVMF_ADRFAM_IPV4; 704 } 705 706 len = strlen(address->traddr); 707 if (len > sizeof(trid->traddr) - 1) { 708 SPDK_ERRLOG("Transport address longer than %zu characters: %s\n", 709 sizeof(trid->traddr) - 1, address->traddr); 710 return -EINVAL; 711 } 712 memcpy(trid->traddr, address->traddr, len + 1); 713 714 len = strlen(address->trsvcid); 715 if (len > sizeof(trid->trsvcid) - 1) { 716 SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n", 717 sizeof(trid->trsvcid) - 1, address->trsvcid); 718 return -EINVAL; 719 } 720 memcpy(trid->trsvcid, address->trsvcid, len + 1); 721 722 return 0; 723 } 724 725 static void 726 spdk_rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request, 727 const struct spdk_json_val *params) 728 { 729 struct nvmf_rpc_listener_ctx *ctx; 730 struct spdk_nvmf_subsystem *subsystem; 731 struct spdk_nvmf_tgt *tgt; 732 733 ctx = calloc(1, sizeof(*ctx)); 734 if (!ctx) { 735 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 736 return; 737 } 738 739 ctx->request = request; 740 741 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder, 742 SPDK_COUNTOF(nvmf_rpc_listener_decoder), 743 ctx)) { 744 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 745 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 746 nvmf_rpc_listener_ctx_free(ctx); 747 return; 748 } 749 750 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 751 if (!tgt) { 752 SPDK_ERRLOG("Unable to find a target object.\n"); 753 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 754 "Unable to find a target."); 755 nvmf_rpc_listener_ctx_free(ctx); 756 return; 757 } 758 ctx->tgt = tgt; 759 760 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 761 if (!subsystem) { 762 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 763 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 764 nvmf_rpc_listener_ctx_free(ctx); 765 return; 766 } 767 768 ctx->subsystem = subsystem; 769 770 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 771 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 772 "Invalid parameters"); 773 nvmf_rpc_listener_ctx_free(ctx); 774 return; 775 } 776 777 ctx->op = NVMF_RPC_LISTEN_ADD; 778 779 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) { 780 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 781 nvmf_rpc_listener_ctx_free(ctx); 782 return; 783 } 784 } 785 SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", spdk_rpc_nvmf_subsystem_add_listener, 786 SPDK_RPC_RUNTIME); 787 788 static void 789 spdk_rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request, 790 const struct spdk_json_val *params) 791 { 792 struct nvmf_rpc_listener_ctx *ctx; 793 struct spdk_nvmf_subsystem *subsystem; 794 struct spdk_nvmf_tgt *tgt; 795 796 ctx = calloc(1, sizeof(*ctx)); 797 if (!ctx) { 798 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 799 return; 800 } 801 802 ctx->request = request; 803 804 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder, 805 SPDK_COUNTOF(nvmf_rpc_listener_decoder), 806 ctx)) { 807 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 808 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 809 nvmf_rpc_listener_ctx_free(ctx); 810 return; 811 } 812 813 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 814 if (!tgt) { 815 SPDK_ERRLOG("Unable to find a target object.\n"); 816 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 817 "Unable to find a target."); 818 nvmf_rpc_listener_ctx_free(ctx); 819 return; 820 } 821 ctx->tgt = tgt; 822 823 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 824 if (!subsystem) { 825 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 826 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 827 nvmf_rpc_listener_ctx_free(ctx); 828 return; 829 } 830 831 ctx->subsystem = subsystem; 832 833 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 834 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 835 "Invalid parameters"); 836 nvmf_rpc_listener_ctx_free(ctx); 837 return; 838 } 839 840 ctx->op = NVMF_RPC_LISTEN_REMOVE; 841 842 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) { 843 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 844 nvmf_rpc_listener_ctx_free(ctx); 845 return; 846 } 847 848 } 849 SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", spdk_rpc_nvmf_subsystem_remove_listener, 850 SPDK_RPC_RUNTIME); 851 852 struct spdk_nvmf_ns_params { 853 char *bdev_name; 854 char *ptpl_file; 855 uint32_t nsid; 856 char nguid[16]; 857 char eui64[8]; 858 struct spdk_uuid uuid; 859 }; 860 861 struct rpc_namespaces { 862 size_t num_ns; 863 struct spdk_nvmf_ns_params ns_params[RPC_MAX_NAMESPACES]; 864 }; 865 866 867 static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = { 868 {"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true}, 869 {"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string}, 870 {"ptpl_file", offsetof(struct spdk_nvmf_ns_params, ptpl_file), spdk_json_decode_string, true}, 871 {"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true}, 872 {"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true}, 873 {"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true}, 874 }; 875 876 static int 877 decode_rpc_ns_params(const struct spdk_json_val *val, void *out) 878 { 879 struct spdk_nvmf_ns_params *ns_params = out; 880 881 return spdk_json_decode_object(val, rpc_ns_params_decoders, 882 SPDK_COUNTOF(rpc_ns_params_decoders), 883 ns_params); 884 } 885 886 struct nvmf_rpc_ns_ctx { 887 char *nqn; 888 char *tgt_name; 889 struct spdk_nvmf_ns_params ns_params; 890 891 struct spdk_jsonrpc_request *request; 892 bool response_sent; 893 }; 894 895 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = { 896 {"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string}, 897 {"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params}, 898 {"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true}, 899 }; 900 901 static void 902 nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx) 903 { 904 free(ctx->nqn); 905 free(ctx->tgt_name); 906 free(ctx->ns_params.bdev_name); 907 free(ctx->ns_params.ptpl_file); 908 free(ctx); 909 } 910 911 static void 912 nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 913 void *cb_arg, int status) 914 { 915 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 916 struct spdk_jsonrpc_request *request = ctx->request; 917 uint32_t nsid = ctx->ns_params.nsid; 918 bool response_sent = ctx->response_sent; 919 struct spdk_json_write_ctx *w; 920 921 nvmf_rpc_ns_ctx_free(ctx); 922 923 if (response_sent) { 924 return; 925 } 926 927 w = spdk_jsonrpc_begin_result(request); 928 spdk_json_write_uint32(w, nsid); 929 spdk_jsonrpc_end_result(request, w); 930 } 931 932 static void 933 nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem, 934 void *cb_arg, int status) 935 { 936 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 937 struct spdk_nvmf_ns_opts ns_opts; 938 struct spdk_bdev *bdev; 939 940 bdev = spdk_bdev_get_by_name(ctx->ns_params.bdev_name); 941 if (!bdev) { 942 SPDK_ERRLOG("No bdev with name %s\n", ctx->ns_params.bdev_name); 943 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 944 "Invalid parameters"); 945 ctx->response_sent = true; 946 goto resume; 947 } 948 949 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 950 ns_opts.nsid = ctx->ns_params.nsid; 951 952 SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch"); 953 memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid)); 954 955 SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch"); 956 memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64)); 957 958 if (!spdk_mem_all_zero(&ctx->ns_params.uuid, sizeof(ctx->ns_params.uuid))) { 959 ns_opts.uuid = ctx->ns_params.uuid; 960 } 961 962 ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns(subsystem, bdev, &ns_opts, sizeof(ns_opts), 963 ctx->ns_params.ptpl_file); 964 if (ctx->ns_params.nsid == 0) { 965 SPDK_ERRLOG("Unable to add namespace\n"); 966 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 967 "Invalid parameters"); 968 ctx->response_sent = true; 969 goto resume; 970 } 971 972 resume: 973 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) { 974 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 975 nvmf_rpc_ns_ctx_free(ctx); 976 return; 977 } 978 } 979 980 static void 981 spdk_rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request, 982 const struct spdk_json_val *params) 983 { 984 struct nvmf_rpc_ns_ctx *ctx; 985 struct spdk_nvmf_subsystem *subsystem; 986 struct spdk_nvmf_tgt *tgt; 987 988 ctx = calloc(1, sizeof(*ctx)); 989 if (!ctx) { 990 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 991 return; 992 } 993 994 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ns_decoder, 995 SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder), 996 ctx)) { 997 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 998 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 999 nvmf_rpc_ns_ctx_free(ctx); 1000 return; 1001 } 1002 1003 ctx->request = request; 1004 ctx->response_sent = false; 1005 1006 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1007 if (!tgt) { 1008 SPDK_ERRLOG("Unable to find a target object.\n"); 1009 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1010 "Unable to find a target."); 1011 nvmf_rpc_ns_ctx_free(ctx); 1012 return; 1013 } 1014 1015 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1016 if (!subsystem) { 1017 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1018 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1019 nvmf_rpc_ns_ctx_free(ctx); 1020 return; 1021 } 1022 1023 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_ns_paused, ctx)) { 1024 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1025 nvmf_rpc_ns_ctx_free(ctx); 1026 return; 1027 } 1028 } 1029 SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", spdk_rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME) 1030 1031 struct nvmf_rpc_remove_ns_ctx { 1032 char *nqn; 1033 char *tgt_name; 1034 uint32_t nsid; 1035 1036 struct spdk_jsonrpc_request *request; 1037 bool response_sent; 1038 }; 1039 1040 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = { 1041 {"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string}, 1042 {"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32}, 1043 {"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1044 }; 1045 1046 static void 1047 nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx) 1048 { 1049 free(ctx->nqn); 1050 free(ctx->tgt_name); 1051 free(ctx); 1052 } 1053 1054 static void 1055 nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1056 void *cb_arg, int status) 1057 { 1058 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1059 struct spdk_jsonrpc_request *request = ctx->request; 1060 bool response_sent = ctx->response_sent; 1061 struct spdk_json_write_ctx *w; 1062 1063 nvmf_rpc_remove_ns_ctx_free(ctx); 1064 1065 if (response_sent) { 1066 return; 1067 } 1068 1069 w = spdk_jsonrpc_begin_result(request); 1070 spdk_json_write_bool(w, true); 1071 spdk_jsonrpc_end_result(request, w); 1072 } 1073 1074 static void 1075 nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1076 void *cb_arg, int status) 1077 { 1078 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1079 int ret; 1080 1081 ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid); 1082 if (ret < 0) { 1083 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid); 1084 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1085 "Invalid parameters"); 1086 ctx->response_sent = true; 1087 } 1088 1089 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) { 1090 if (!ctx->response_sent) { 1091 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1092 } 1093 nvmf_rpc_remove_ns_ctx_free(ctx); 1094 return; 1095 } 1096 } 1097 1098 static void 1099 spdk_rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request, 1100 const struct spdk_json_val *params) 1101 { 1102 struct nvmf_rpc_remove_ns_ctx *ctx; 1103 struct spdk_nvmf_subsystem *subsystem; 1104 struct spdk_nvmf_tgt *tgt; 1105 1106 ctx = calloc(1, sizeof(*ctx)); 1107 if (!ctx) { 1108 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1109 return; 1110 } 1111 1112 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder, 1113 SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder), 1114 ctx)) { 1115 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1116 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1117 nvmf_rpc_remove_ns_ctx_free(ctx); 1118 return; 1119 } 1120 1121 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1122 if (!tgt) { 1123 SPDK_ERRLOG("Unable to find a target object.\n"); 1124 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1125 "Unable to find a target."); 1126 nvmf_rpc_remove_ns_ctx_free(ctx); 1127 return; 1128 } 1129 1130 ctx->request = request; 1131 ctx->response_sent = false; 1132 1133 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1134 if (!subsystem) { 1135 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1136 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1137 nvmf_rpc_remove_ns_ctx_free(ctx); 1138 return; 1139 } 1140 1141 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_remove_ns_paused, ctx)) { 1142 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1143 nvmf_rpc_remove_ns_ctx_free(ctx); 1144 return; 1145 } 1146 } 1147 SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", spdk_rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME) 1148 1149 enum nvmf_rpc_host_op { 1150 NVMF_RPC_HOST_ADD, 1151 NVMF_RPC_HOST_REMOVE, 1152 NVMF_RPC_HOST_ALLOW_ANY, 1153 }; 1154 1155 struct nvmf_rpc_host_ctx { 1156 struct spdk_jsonrpc_request *request; 1157 1158 char *nqn; 1159 char *host; 1160 char *tgt_name; 1161 1162 enum nvmf_rpc_host_op op; 1163 1164 bool allow_any_host; 1165 1166 bool response_sent; 1167 }; 1168 1169 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = { 1170 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1171 {"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string}, 1172 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1173 }; 1174 1175 static void 1176 nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx) 1177 { 1178 free(ctx->nqn); 1179 free(ctx->host); 1180 free(ctx->tgt_name); 1181 free(ctx); 1182 } 1183 1184 static void 1185 nvmf_rpc_host_resumed(struct spdk_nvmf_subsystem *subsystem, 1186 void *cb_arg, int status) 1187 { 1188 struct nvmf_rpc_host_ctx *ctx = cb_arg; 1189 struct spdk_jsonrpc_request *request; 1190 struct spdk_json_write_ctx *w; 1191 bool response_sent = ctx->response_sent; 1192 1193 request = ctx->request; 1194 nvmf_rpc_host_ctx_free(ctx); 1195 1196 if (response_sent) { 1197 return; 1198 } 1199 1200 w = spdk_jsonrpc_begin_result(request); 1201 spdk_json_write_bool(w, true); 1202 spdk_jsonrpc_end_result(request, w); 1203 } 1204 1205 static void 1206 nvmf_rpc_host_paused(struct spdk_nvmf_subsystem *subsystem, 1207 void *cb_arg, int status) 1208 { 1209 struct nvmf_rpc_host_ctx *ctx = cb_arg; 1210 int rc = -1; 1211 1212 switch (ctx->op) { 1213 case NVMF_RPC_HOST_ADD: 1214 rc = spdk_nvmf_subsystem_add_host(subsystem, ctx->host); 1215 break; 1216 case NVMF_RPC_HOST_REMOVE: 1217 rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host); 1218 break; 1219 case NVMF_RPC_HOST_ALLOW_ANY: 1220 rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx->allow_any_host); 1221 break; 1222 } 1223 1224 if (rc != 0) { 1225 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1226 ctx->response_sent = true; 1227 } 1228 1229 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_host_resumed, ctx)) { 1230 if (!ctx->response_sent) { 1231 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1232 } 1233 nvmf_rpc_host_ctx_free(ctx); 1234 return; 1235 } 1236 } 1237 1238 static void 1239 spdk_rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request, 1240 const struct spdk_json_val *params) 1241 { 1242 struct nvmf_rpc_host_ctx *ctx; 1243 struct spdk_nvmf_subsystem *subsystem; 1244 struct spdk_nvmf_tgt *tgt; 1245 1246 ctx = calloc(1, sizeof(*ctx)); 1247 if (!ctx) { 1248 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1249 return; 1250 } 1251 1252 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 1253 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1254 ctx)) { 1255 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1256 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1257 nvmf_rpc_host_ctx_free(ctx); 1258 return; 1259 } 1260 1261 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1262 if (!tgt) { 1263 SPDK_ERRLOG("Unable to find a target object.\n"); 1264 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1265 "Unable to find a target."); 1266 nvmf_rpc_host_ctx_free(ctx); 1267 return; 1268 } 1269 1270 ctx->request = request; 1271 ctx->op = NVMF_RPC_HOST_ADD; 1272 ctx->response_sent = false; 1273 1274 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1275 if (!subsystem) { 1276 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1277 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1278 nvmf_rpc_host_ctx_free(ctx); 1279 return; 1280 } 1281 1282 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) { 1283 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1284 nvmf_rpc_host_ctx_free(ctx); 1285 return; 1286 } 1287 } 1288 SPDK_RPC_REGISTER("nvmf_subsystem_add_host", spdk_rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME) 1289 1290 static void 1291 spdk_rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request, 1292 const struct spdk_json_val *params) 1293 { 1294 struct nvmf_rpc_host_ctx *ctx; 1295 struct spdk_nvmf_subsystem *subsystem; 1296 struct spdk_nvmf_tgt *tgt; 1297 1298 ctx = calloc(1, sizeof(*ctx)); 1299 if (!ctx) { 1300 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1301 return; 1302 } 1303 1304 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 1305 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1306 ctx)) { 1307 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1308 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1309 nvmf_rpc_host_ctx_free(ctx); 1310 return; 1311 } 1312 1313 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1314 if (!tgt) { 1315 SPDK_ERRLOG("Unable to find a target object.\n"); 1316 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1317 "Unable to find a target."); 1318 nvmf_rpc_host_ctx_free(ctx); 1319 return; 1320 } 1321 1322 ctx->request = request; 1323 ctx->op = NVMF_RPC_HOST_REMOVE; 1324 ctx->response_sent = false; 1325 1326 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1327 if (!subsystem) { 1328 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1329 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1330 nvmf_rpc_host_ctx_free(ctx); 1331 return; 1332 } 1333 1334 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) { 1335 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1336 nvmf_rpc_host_ctx_free(ctx); 1337 return; 1338 } 1339 } 1340 SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", spdk_rpc_nvmf_subsystem_remove_host, 1341 SPDK_RPC_RUNTIME) 1342 1343 1344 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = { 1345 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1346 {"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool}, 1347 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1348 }; 1349 1350 static void 1351 spdk_rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request, 1352 const struct spdk_json_val *params) 1353 { 1354 struct nvmf_rpc_host_ctx *ctx; 1355 struct spdk_nvmf_subsystem *subsystem; 1356 struct spdk_nvmf_tgt *tgt; 1357 1358 ctx = calloc(1, sizeof(*ctx)); 1359 if (!ctx) { 1360 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1361 return; 1362 } 1363 1364 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder, 1365 SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder), 1366 ctx)) { 1367 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1368 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1369 nvmf_rpc_host_ctx_free(ctx); 1370 return; 1371 } 1372 1373 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1374 if (!tgt) { 1375 SPDK_ERRLOG("Unable to find a target object.\n"); 1376 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1377 "Unable to find a target."); 1378 nvmf_rpc_host_ctx_free(ctx); 1379 return; 1380 } 1381 1382 ctx->request = request; 1383 ctx->op = NVMF_RPC_HOST_ALLOW_ANY; 1384 ctx->response_sent = false; 1385 1386 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1387 if (!subsystem) { 1388 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1389 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1390 nvmf_rpc_host_ctx_free(ctx); 1391 return; 1392 } 1393 1394 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) { 1395 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1396 nvmf_rpc_host_ctx_free(ctx); 1397 return; 1398 } 1399 } 1400 SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", spdk_rpc_nvmf_subsystem_allow_any_host, 1401 SPDK_RPC_RUNTIME) 1402 1403 struct nvmf_rpc_target_ctx { 1404 char *name; 1405 uint32_t max_subsystems; 1406 }; 1407 1408 static const struct spdk_json_object_decoder nvmf_rpc_create_target_decoder[] = { 1409 {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 1410 {"max_subsystems", offsetof(struct nvmf_rpc_target_ctx, max_subsystems), spdk_json_decode_uint32, true}, 1411 }; 1412 1413 static void 1414 spdk_rpc_nvmf_create_target(struct spdk_jsonrpc_request *request, 1415 const struct spdk_json_val *params) 1416 { 1417 struct spdk_nvmf_target_opts opts; 1418 struct nvmf_rpc_target_ctx ctx = {0}; 1419 struct spdk_nvmf_tgt *tgt; 1420 struct spdk_json_write_ctx *w; 1421 1422 /* Decode parameters the first time to get the transport type */ 1423 if (spdk_json_decode_object(params, nvmf_rpc_create_target_decoder, 1424 SPDK_COUNTOF(nvmf_rpc_create_target_decoder), 1425 &ctx)) { 1426 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1427 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1428 free(ctx.name); 1429 return; 1430 } 1431 1432 snprintf(opts.name, NVMF_TGT_NAME_MAX_LENGTH, "%s", ctx.name); 1433 opts.max_subsystems = ctx.max_subsystems; 1434 1435 if (spdk_nvmf_get_tgt(opts.name) != NULL) { 1436 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1437 "Target already exists."); 1438 free(ctx.name); 1439 return; 1440 } 1441 1442 tgt = spdk_nvmf_tgt_create(&opts); 1443 1444 if (tgt == NULL) { 1445 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1446 "Unable to create the requested target."); 1447 free(ctx.name); 1448 return; 1449 } 1450 1451 w = spdk_jsonrpc_begin_result(request); 1452 spdk_json_write_string(w, spdk_nvmf_tgt_get_name(tgt)); 1453 spdk_jsonrpc_end_result(request, w); 1454 free(ctx.name); 1455 } 1456 SPDK_RPC_REGISTER("nvmf_create_target", spdk_rpc_nvmf_create_target, SPDK_RPC_RUNTIME); 1457 1458 static const struct spdk_json_object_decoder nvmf_rpc_destroy_target_decoder[] = { 1459 {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 1460 }; 1461 1462 static void 1463 nvmf_rpc_destroy_target_done(void *ctx, int status) 1464 { 1465 struct spdk_jsonrpc_request *request = ctx; 1466 struct spdk_json_write_ctx *w; 1467 1468 w = spdk_jsonrpc_begin_result(request); 1469 spdk_json_write_bool(w, true); 1470 spdk_jsonrpc_end_result(request, w); 1471 } 1472 1473 static void 1474 spdk_rpc_nvmf_delete_target(struct spdk_jsonrpc_request *request, 1475 const struct spdk_json_val *params) 1476 { 1477 struct nvmf_rpc_target_ctx ctx = {0}; 1478 struct spdk_nvmf_tgt *tgt; 1479 1480 /* Decode parameters the first time to get the transport type */ 1481 if (spdk_json_decode_object(params, nvmf_rpc_destroy_target_decoder, 1482 SPDK_COUNTOF(nvmf_rpc_destroy_target_decoder), 1483 &ctx)) { 1484 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1485 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1486 free(ctx.name); 1487 return; 1488 } 1489 1490 tgt = spdk_nvmf_get_tgt(ctx.name); 1491 1492 if (tgt == NULL) { 1493 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1494 "The specified target doesn't exist, cannot delete it."); 1495 free(ctx.name); 1496 return; 1497 } 1498 1499 spdk_nvmf_tgt_destroy(tgt, nvmf_rpc_destroy_target_done, request); 1500 free(ctx.name); 1501 } 1502 SPDK_RPC_REGISTER("nvmf_delete_target", spdk_rpc_nvmf_delete_target, SPDK_RPC_RUNTIME); 1503 1504 static void 1505 spdk_rpc_nvmf_get_targets(struct spdk_jsonrpc_request *request, 1506 const struct spdk_json_val *params) 1507 { 1508 struct spdk_json_write_ctx *w; 1509 struct spdk_nvmf_tgt *tgt; 1510 const char *name; 1511 1512 if (params != NULL) { 1513 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1514 "nvmf_get_targets has no parameters."); 1515 return; 1516 } 1517 1518 w = spdk_jsonrpc_begin_result(request); 1519 spdk_json_write_array_begin(w); 1520 1521 tgt = spdk_nvmf_get_first_tgt(); 1522 1523 while (tgt != NULL) { 1524 name = spdk_nvmf_tgt_get_name(tgt); 1525 spdk_json_write_string(w, name); 1526 tgt = spdk_nvmf_get_next_tgt(tgt); 1527 } 1528 1529 spdk_json_write_array_end(w); 1530 spdk_jsonrpc_end_result(request, w); 1531 } 1532 SPDK_RPC_REGISTER("nvmf_get_targets", spdk_rpc_nvmf_get_targets, SPDK_RPC_RUNTIME); 1533 1534 struct nvmf_rpc_create_transport_ctx { 1535 char *trtype; 1536 char *tgt_name; 1537 struct spdk_nvmf_transport_opts opts; 1538 struct spdk_jsonrpc_request *request; 1539 }; 1540 1541 static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = { 1542 { "trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string}, 1543 { 1544 "max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth), 1545 spdk_json_decode_uint16, true 1546 }, 1547 { 1548 "max_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr), 1549 spdk_json_decode_uint16, true 1550 }, 1551 { 1552 "in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size), 1553 spdk_json_decode_uint32, true 1554 }, 1555 { 1556 "max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size), 1557 spdk_json_decode_uint32, true 1558 }, 1559 { 1560 "io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size), 1561 spdk_json_decode_uint32, true 1562 }, 1563 { 1564 "max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth), 1565 spdk_json_decode_uint32, true 1566 }, 1567 { 1568 "num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers), 1569 spdk_json_decode_uint32, true 1570 }, 1571 { 1572 "buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size), 1573 spdk_json_decode_uint32, true 1574 }, 1575 { 1576 "max_srq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_srq_depth), 1577 spdk_json_decode_uint32, true 1578 }, 1579 { 1580 "no_srq", offsetof(struct nvmf_rpc_create_transport_ctx, opts.no_srq), 1581 spdk_json_decode_bool, true 1582 }, 1583 { 1584 "c2h_success", offsetof(struct nvmf_rpc_create_transport_ctx, opts.c2h_success), 1585 spdk_json_decode_bool, true 1586 }, 1587 { 1588 "dif_insert_or_strip", offsetof(struct nvmf_rpc_create_transport_ctx, opts.dif_insert_or_strip), 1589 spdk_json_decode_bool, true 1590 }, 1591 { 1592 "sock_priority", offsetof(struct nvmf_rpc_create_transport_ctx, opts.sock_priority), 1593 spdk_json_decode_uint32, true 1594 }, 1595 { 1596 "tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name), 1597 spdk_json_decode_string, true 1598 }, 1599 }; 1600 1601 static void 1602 nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx) 1603 { 1604 free(ctx->trtype); 1605 free(ctx->tgt_name); 1606 free(ctx); 1607 } 1608 1609 static void 1610 nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status) 1611 { 1612 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 1613 struct spdk_jsonrpc_request *request; 1614 struct spdk_json_write_ctx *w; 1615 1616 request = ctx->request; 1617 nvmf_rpc_create_transport_ctx_free(ctx); 1618 1619 if (status) { 1620 SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status); 1621 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1622 "Failed to add transport to tgt.(%d)\n", 1623 status); 1624 return; 1625 } 1626 1627 w = spdk_jsonrpc_begin_result(request); 1628 spdk_json_write_bool(w, true); 1629 spdk_jsonrpc_end_result(request, w); 1630 } 1631 1632 static void 1633 spdk_rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request, 1634 const struct spdk_json_val *params) 1635 { 1636 struct nvmf_rpc_create_transport_ctx *ctx; 1637 enum spdk_nvme_transport_type trtype; 1638 struct spdk_nvmf_transport *transport; 1639 struct spdk_nvmf_tgt *tgt; 1640 1641 ctx = calloc(1, sizeof(*ctx)); 1642 if (!ctx) { 1643 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1644 return; 1645 } 1646 1647 /* Decode parameters the first time to get the transport type */ 1648 if (spdk_json_decode_object(params, nvmf_rpc_create_transport_decoder, 1649 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 1650 ctx)) { 1651 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1652 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1653 nvmf_rpc_create_transport_ctx_free(ctx); 1654 return; 1655 } 1656 1657 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1658 if (!tgt) { 1659 SPDK_ERRLOG("Unable to find a target object.\n"); 1660 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1661 "Unable to find a target."); 1662 nvmf_rpc_create_transport_ctx_free(ctx); 1663 return; 1664 } 1665 1666 if (spdk_nvme_transport_id_parse_trtype(&trtype, ctx->trtype)) { 1667 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype); 1668 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1669 "Invalid transport type '%s'\n", ctx->trtype); 1670 nvmf_rpc_create_transport_ctx_free(ctx); 1671 return; 1672 } 1673 1674 /* Initialize all the transport options (based on transport type) and decode the 1675 * parameters again to update any options passed in rpc create transport call. 1676 */ 1677 if (!spdk_nvmf_transport_opts_init(trtype, &ctx->opts)) { 1678 /* This can happen if user specifies PCIE transport type which isn't valid for 1679 * NVMe-oF. 1680 */ 1681 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype); 1682 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1683 "Invalid transport type '%s'\n", ctx->trtype); 1684 nvmf_rpc_create_transport_ctx_free(ctx); 1685 return; 1686 } 1687 1688 if (spdk_json_decode_object(params, nvmf_rpc_create_transport_decoder, 1689 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 1690 ctx)) { 1691 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1692 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1693 nvmf_rpc_create_transport_ctx_free(ctx); 1694 return; 1695 } 1696 1697 if (spdk_nvmf_tgt_get_transport(tgt, trtype)) { 1698 SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype); 1699 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1700 "Transport type '%s' already exists\n", ctx->trtype); 1701 nvmf_rpc_create_transport_ctx_free(ctx); 1702 return; 1703 } 1704 1705 transport = spdk_nvmf_transport_create(trtype, &ctx->opts); 1706 1707 if (!transport) { 1708 SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype); 1709 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1710 "Transport type '%s' create failed\n", ctx->trtype); 1711 nvmf_rpc_create_transport_ctx_free(ctx); 1712 return; 1713 } 1714 1715 /* add transport to target */ 1716 ctx->request = request; 1717 spdk_nvmf_tgt_add_transport(tgt, transport, nvmf_rpc_tgt_add_transport_done, ctx); 1718 } 1719 SPDK_RPC_REGISTER("nvmf_create_transport", spdk_rpc_nvmf_create_transport, SPDK_RPC_RUNTIME) 1720 1721 static void 1722 dump_nvmf_transport(struct spdk_json_write_ctx *w, struct spdk_nvmf_transport *transport) 1723 { 1724 const struct spdk_nvmf_transport_opts *opts = spdk_nvmf_get_transport_opts(transport); 1725 spdk_nvme_transport_type_t type = spdk_nvmf_get_transport_type(transport); 1726 1727 spdk_json_write_object_begin(w); 1728 1729 spdk_json_write_named_string(w, "trtype", spdk_nvme_transport_id_trtype_str(type)); 1730 spdk_json_write_named_uint32(w, "max_queue_depth", opts->max_queue_depth); 1731 spdk_json_write_named_uint32(w, "max_qpairs_per_ctrlr", opts->max_qpairs_per_ctrlr); 1732 spdk_json_write_named_uint32(w, "in_capsule_data_size", opts->in_capsule_data_size); 1733 spdk_json_write_named_uint32(w, "max_io_size", opts->max_io_size); 1734 spdk_json_write_named_uint32(w, "io_unit_size", opts->io_unit_size); 1735 spdk_json_write_named_uint32(w, "max_aq_depth", opts->max_aq_depth); 1736 spdk_json_write_named_uint32(w, "num_shared_buffers", opts->num_shared_buffers); 1737 spdk_json_write_named_uint32(w, "buf_cache_size", opts->buf_cache_size); 1738 spdk_json_write_named_bool(w, "dif_insert_or_strip", opts->dif_insert_or_strip); 1739 if (type == SPDK_NVME_TRANSPORT_RDMA) { 1740 spdk_json_write_named_uint32(w, "max_srq_depth", opts->max_srq_depth); 1741 spdk_json_write_named_bool(w, "no_srq", opts->no_srq); 1742 } else if (type == SPDK_NVME_TRANSPORT_TCP) { 1743 spdk_json_write_named_bool(w, "c2h_success", opts->c2h_success); 1744 spdk_json_write_named_uint32(w, "sock_priority", opts->sock_priority); 1745 } 1746 1747 spdk_json_write_object_end(w); 1748 } 1749 1750 struct rpc_get_transport { 1751 char *tgt_name; 1752 }; 1753 1754 static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = { 1755 {"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true}, 1756 }; 1757 1758 static void 1759 spdk_rpc_nvmf_get_transports(struct spdk_jsonrpc_request *request, 1760 const struct spdk_json_val *params) 1761 { 1762 struct rpc_get_transport req = { 0 }; 1763 struct spdk_json_write_ctx *w; 1764 struct spdk_nvmf_transport *transport; 1765 struct spdk_nvmf_tgt *tgt; 1766 1767 if (params) { 1768 if (spdk_json_decode_object(params, rpc_get_transport_decoders, 1769 SPDK_COUNTOF(rpc_get_transport_decoders), 1770 &req)) { 1771 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1772 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1773 return; 1774 } 1775 } 1776 1777 tgt = spdk_nvmf_get_tgt(req.tgt_name); 1778 if (!tgt) { 1779 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1780 "Unable to find a target."); 1781 free(req.tgt_name); 1782 return; 1783 } 1784 1785 w = spdk_jsonrpc_begin_result(request); 1786 spdk_json_write_array_begin(w); 1787 transport = spdk_nvmf_transport_get_first(tgt); 1788 while (transport) { 1789 dump_nvmf_transport(w, transport); 1790 transport = spdk_nvmf_transport_get_next(transport); 1791 } 1792 spdk_json_write_array_end(w); 1793 spdk_jsonrpc_end_result(request, w); 1794 free(req.tgt_name); 1795 } 1796 SPDK_RPC_REGISTER("nvmf_get_transports", spdk_rpc_nvmf_get_transports, SPDK_RPC_RUNTIME) 1797 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(nvmf_get_transports, get_nvmf_transports) 1798 1799 struct rpc_nvmf_get_stats_ctx { 1800 char *tgt_name; 1801 struct spdk_nvmf_tgt *tgt; 1802 struct spdk_jsonrpc_request *request; 1803 struct spdk_json_write_ctx *w; 1804 }; 1805 1806 static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = { 1807 {"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true}, 1808 }; 1809 1810 static void 1811 free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx) 1812 { 1813 free(ctx->tgt_name); 1814 free(ctx); 1815 } 1816 1817 static void 1818 rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status) 1819 { 1820 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1821 1822 spdk_json_write_array_end(ctx->w); 1823 spdk_json_write_object_end(ctx->w); 1824 spdk_jsonrpc_end_result(ctx->request, ctx->w); 1825 free_get_stats_ctx(ctx); 1826 } 1827 1828 static void 1829 write_nvmf_transport_stats(struct spdk_json_write_ctx *w, 1830 struct spdk_nvmf_transport_poll_group_stat *stat) 1831 { 1832 uint64_t i; 1833 1834 spdk_json_write_object_begin(w); 1835 spdk_json_write_named_string(w, "trtype", 1836 spdk_nvme_transport_id_trtype_str(stat->trtype)); 1837 switch (stat->trtype) { 1838 case SPDK_NVME_TRANSPORT_RDMA: 1839 spdk_json_write_named_uint64(w, "pending_data_buffer", stat->rdma.pending_data_buffer); 1840 spdk_json_write_named_array_begin(w, "devices"); 1841 for (i = 0; i < stat->rdma.num_devices; ++i) { 1842 spdk_json_write_object_begin(w); 1843 spdk_json_write_named_string(w, "name", stat->rdma.devices[i].name); 1844 spdk_json_write_named_uint64(w, "polls", stat->rdma.devices[i].polls); 1845 spdk_json_write_named_uint64(w, "completions", stat->rdma.devices[i].completions); 1846 spdk_json_write_named_uint64(w, "requests", 1847 stat->rdma.devices[i].requests); 1848 spdk_json_write_named_uint64(w, "request_latency", 1849 stat->rdma.devices[i].request_latency); 1850 spdk_json_write_named_uint64(w, "pending_free_request", 1851 stat->rdma.devices[i].pending_free_request); 1852 spdk_json_write_named_uint64(w, "pending_rdma_read", 1853 stat->rdma.devices[i].pending_rdma_read); 1854 spdk_json_write_named_uint64(w, "pending_rdma_write", 1855 stat->rdma.devices[i].pending_rdma_write); 1856 spdk_json_write_object_end(w); 1857 } 1858 spdk_json_write_array_end(w); 1859 break; 1860 default: 1861 break; 1862 } 1863 spdk_json_write_object_end(w); 1864 } 1865 1866 static void 1867 rpc_nvmf_get_stats(struct spdk_io_channel_iter *i) 1868 { 1869 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1870 struct spdk_nvmf_transport *transport; 1871 struct spdk_nvmf_poll_group_stat stat; 1872 struct spdk_nvmf_transport_poll_group_stat *trstat; 1873 int rc; 1874 1875 if (0 == spdk_nvmf_poll_group_get_stat(ctx->tgt, &stat)) { 1876 spdk_json_write_object_begin(ctx->w); 1877 spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(spdk_get_thread())); 1878 spdk_json_write_named_uint32(ctx->w, "admin_qpairs", stat.admin_qpairs); 1879 spdk_json_write_named_uint32(ctx->w, "io_qpairs", stat.io_qpairs); 1880 spdk_json_write_named_uint64(ctx->w, "pending_bdev_io", stat.pending_bdev_io); 1881 1882 spdk_json_write_named_array_begin(ctx->w, "transports"); 1883 transport = spdk_nvmf_transport_get_first(ctx->tgt); 1884 while (transport) { 1885 rc = spdk_nvmf_transport_poll_group_get_stat(ctx->tgt, transport, &trstat); 1886 if (0 == rc) { 1887 write_nvmf_transport_stats(ctx->w, trstat); 1888 spdk_nvmf_transport_poll_group_free_stat(transport, trstat); 1889 } else if (-ENOTSUP != rc) { 1890 SPDK_ERRLOG("Failed to get poll group statistics for transport %s, errno %d\n", 1891 spdk_nvme_transport_id_trtype_str(spdk_nvmf_get_transport_type(transport)), 1892 rc); 1893 } 1894 transport = spdk_nvmf_transport_get_next(transport); 1895 } 1896 spdk_json_write_array_end(ctx->w); 1897 spdk_json_write_object_end(ctx->w); 1898 } 1899 1900 spdk_for_each_channel_continue(i, 0); 1901 } 1902 1903 1904 static void 1905 spdk_rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request, 1906 const struct spdk_json_val *params) 1907 { 1908 struct rpc_nvmf_get_stats_ctx *ctx; 1909 1910 ctx = calloc(1, sizeof(*ctx)); 1911 if (!ctx) { 1912 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1913 "Memory allocation error"); 1914 return; 1915 } 1916 ctx->request = request; 1917 1918 if (params) { 1919 if (spdk_json_decode_object(params, rpc_get_stats_decoders, 1920 SPDK_COUNTOF(rpc_get_stats_decoders), 1921 ctx)) { 1922 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1923 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1924 free_get_stats_ctx(ctx); 1925 return; 1926 } 1927 } 1928 1929 ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1930 if (!ctx->tgt) { 1931 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1932 "Unable to find a target."); 1933 free_get_stats_ctx(ctx); 1934 return; 1935 } 1936 1937 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 1938 if (NULL == ctx->w) { 1939 free_get_stats_ctx(ctx); 1940 return; 1941 } 1942 1943 spdk_json_write_object_begin(ctx->w); 1944 spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz()); 1945 spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 1946 1947 spdk_for_each_channel(ctx->tgt, 1948 rpc_nvmf_get_stats, 1949 ctx, 1950 rpc_nvmf_get_stats_done); 1951 } 1952 1953 SPDK_RPC_REGISTER("nvmf_get_stats", spdk_rpc_nvmf_get_stats, SPDK_RPC_RUNTIME) 1954