1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2016 Intel Corporation. All rights reserved. 3 * Copyright (c) 2018-2021 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 */ 6 7 #include "spdk/bdev.h" 8 #include "spdk/log.h" 9 #include "spdk/rpc.h" 10 #include "spdk/env.h" 11 #include "spdk/nvme.h" 12 #include "spdk/nvmf.h" 13 #include "spdk/string.h" 14 #include "spdk/util.h" 15 #include "spdk/bit_array.h" 16 17 #include "spdk_internal/assert.h" 18 19 #include "nvmf_internal.h" 20 21 static bool g_logged_deprecated_nvmf_get_subsystems = false; 22 23 static int 24 json_write_hex_str(struct spdk_json_write_ctx *w, const void *data, size_t size) 25 { 26 static const char hex_char[16] = "0123456789ABCDEF"; 27 const uint8_t *buf = data; 28 char *str, *out; 29 int rc; 30 31 str = malloc(size * 2 + 1); 32 if (str == NULL) { 33 return -1; 34 } 35 36 out = str; 37 while (size--) { 38 unsigned byte = *buf++; 39 40 out[0] = hex_char[(byte >> 4) & 0xF]; 41 out[1] = hex_char[byte & 0xF]; 42 43 out += 2; 44 } 45 *out = '\0'; 46 47 rc = spdk_json_write_string(w, str); 48 free(str); 49 50 return rc; 51 } 52 53 static int 54 hex_nybble_to_num(char c) 55 { 56 if (c >= '0' && c <= '9') { 57 return c - '0'; 58 } 59 60 if (c >= 'a' && c <= 'f') { 61 return c - 'a' + 0xA; 62 } 63 64 if (c >= 'A' && c <= 'F') { 65 return c - 'A' + 0xA; 66 } 67 68 return -1; 69 } 70 71 static int 72 hex_byte_to_num(const char *str) 73 { 74 int hi, lo; 75 76 hi = hex_nybble_to_num(str[0]); 77 if (hi < 0) { 78 return hi; 79 } 80 81 lo = hex_nybble_to_num(str[1]); 82 if (lo < 0) { 83 return lo; 84 } 85 86 return hi * 16 + lo; 87 } 88 89 static int 90 decode_hex_string_be(const char *str, uint8_t *out, size_t size) 91 { 92 size_t i; 93 94 /* Decode a string in "ABCDEF012345" format to its binary representation */ 95 for (i = 0; i < size; i++) { 96 int num = hex_byte_to_num(str); 97 98 if (num < 0) { 99 /* Invalid hex byte or end of string */ 100 return -1; 101 } 102 103 out[i] = (uint8_t)num; 104 str += 2; 105 } 106 107 if (i != size || *str != '\0') { 108 /* Length mismatch */ 109 return -1; 110 } 111 112 return 0; 113 } 114 115 static int 116 decode_ns_nguid(const struct spdk_json_val *val, void *out) 117 { 118 char *str = NULL; 119 int rc; 120 121 rc = spdk_json_decode_string(val, &str); 122 if (rc == 0) { 123 /* 16-byte NGUID */ 124 rc = decode_hex_string_be(str, out, 16); 125 } 126 127 free(str); 128 return rc; 129 } 130 131 static int 132 decode_ns_eui64(const struct spdk_json_val *val, void *out) 133 { 134 char *str = NULL; 135 int rc; 136 137 rc = spdk_json_decode_string(val, &str); 138 if (rc == 0) { 139 /* 8-byte EUI-64 */ 140 rc = decode_hex_string_be(str, out, 8); 141 } 142 143 free(str); 144 return rc; 145 } 146 147 struct rpc_get_subsystem { 148 char *nqn; 149 char *tgt_name; 150 }; 151 152 static const struct spdk_json_object_decoder rpc_get_subsystem_decoders[] = { 153 {"nqn", offsetof(struct rpc_get_subsystem, nqn), spdk_json_decode_string, true}, 154 {"tgt_name", offsetof(struct rpc_get_subsystem, tgt_name), spdk_json_decode_string, true}, 155 }; 156 157 static void 158 dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *subsystem) 159 { 160 struct spdk_nvmf_host *host; 161 struct spdk_nvmf_subsystem_listener *listener; 162 163 spdk_json_write_object_begin(w); 164 165 spdk_json_write_named_string(w, "nqn", spdk_nvmf_subsystem_get_nqn(subsystem)); 166 spdk_json_write_name(w, "subtype"); 167 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) { 168 spdk_json_write_string(w, "NVMe"); 169 } else { 170 spdk_json_write_string(w, "Discovery"); 171 } 172 173 spdk_json_write_named_array_begin(w, "listen_addresses"); 174 175 for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL; 176 listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) { 177 const struct spdk_nvme_transport_id *trid; 178 179 trid = spdk_nvmf_subsystem_listener_get_trid(listener); 180 181 spdk_json_write_object_begin(w); 182 183 /* NOTE: "transport" is kept for compatibility; new code should use "trtype". */ 184 /* TODO: Remove after SPDK v23.09 release. */ 185 spdk_json_write_named_string(w, "transport", trid->trstring); 186 nvmf_transport_listen_dump_trid(trid, w); 187 spdk_json_write_object_end(w); 188 } 189 spdk_json_write_array_end(w); 190 191 spdk_json_write_named_bool(w, "allow_any_host", 192 spdk_nvmf_subsystem_get_allow_any_host(subsystem)); 193 194 spdk_json_write_named_array_begin(w, "hosts"); 195 196 for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL; 197 host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) { 198 spdk_json_write_object_begin(w); 199 spdk_json_write_named_string(w, "nqn", spdk_nvmf_host_get_nqn(host)); 200 spdk_json_write_object_end(w); 201 } 202 spdk_json_write_array_end(w); 203 204 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) { 205 struct spdk_nvmf_ns *ns; 206 struct spdk_nvmf_ns_opts ns_opts; 207 uint32_t max_namespaces; 208 209 spdk_json_write_named_string(w, "serial_number", spdk_nvmf_subsystem_get_sn(subsystem)); 210 211 spdk_json_write_named_string(w, "model_number", spdk_nvmf_subsystem_get_mn(subsystem)); 212 213 max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem); 214 if (max_namespaces != 0) { 215 spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces); 216 } 217 218 spdk_json_write_named_uint32(w, "min_cntlid", spdk_nvmf_subsystem_get_min_cntlid(subsystem)); 219 spdk_json_write_named_uint32(w, "max_cntlid", spdk_nvmf_subsystem_get_max_cntlid(subsystem)); 220 221 spdk_json_write_named_array_begin(w, "namespaces"); 222 for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL; 223 ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) { 224 spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts)); 225 spdk_json_write_object_begin(w); 226 spdk_json_write_named_int32(w, "nsid", spdk_nvmf_ns_get_id(ns)); 227 spdk_json_write_named_string(w, "bdev_name", 228 spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); 229 /* NOTE: "name" is kept for compatibility only - new code should use bdev_name. */ 230 spdk_json_write_named_string(w, "name", 231 spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); 232 233 if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) { 234 spdk_json_write_name(w, "nguid"); 235 json_write_hex_str(w, ns_opts.nguid, sizeof(ns_opts.nguid)); 236 } 237 238 if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) { 239 spdk_json_write_name(w, "eui64"); 240 json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64)); 241 } 242 243 if (!spdk_uuid_is_null(&ns_opts.uuid)) { 244 spdk_json_write_named_uuid(w, "uuid", &ns_opts.uuid); 245 } 246 247 if (nvmf_subsystem_get_ana_reporting(subsystem)) { 248 spdk_json_write_named_uint32(w, "anagrpid", ns_opts.anagrpid); 249 } 250 251 spdk_json_write_object_end(w); 252 } 253 spdk_json_write_array_end(w); 254 } 255 spdk_json_write_object_end(w); 256 } 257 258 SPDK_LOG_DEPRECATION_REGISTER(rpc_nvmf_get_subsystems, 259 "listener.transport is deprecated in favor of trtype", 260 "v24.01", 0); 261 262 static void 263 rpc_nvmf_get_subsystems(struct spdk_jsonrpc_request *request, 264 const struct spdk_json_val *params) 265 { 266 struct rpc_get_subsystem req = { 0 }; 267 struct spdk_json_write_ctx *w; 268 struct spdk_nvmf_subsystem *subsystem = NULL; 269 struct spdk_nvmf_tgt *tgt; 270 271 /* Log only once */ 272 if (!g_logged_deprecated_nvmf_get_subsystems) { 273 SPDK_LOG_DEPRECATED(rpc_nvmf_get_subsystems); 274 g_logged_deprecated_nvmf_get_subsystems = true; 275 } 276 277 if (params) { 278 if (spdk_json_decode_object(params, rpc_get_subsystem_decoders, 279 SPDK_COUNTOF(rpc_get_subsystem_decoders), 280 &req)) { 281 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 282 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 283 return; 284 } 285 } 286 287 tgt = spdk_nvmf_get_tgt(req.tgt_name); 288 if (!tgt) { 289 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 290 "Unable to find a target."); 291 free(req.tgt_name); 292 free(req.nqn); 293 return; 294 } 295 296 if (req.nqn) { 297 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn); 298 if (!subsystem) { 299 SPDK_ERRLOG("subsystem '%s' does not exist\n", req.nqn); 300 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 301 free(req.tgt_name); 302 free(req.nqn); 303 return; 304 } 305 } 306 307 w = spdk_jsonrpc_begin_result(request); 308 spdk_json_write_array_begin(w); 309 310 if (subsystem) { 311 dump_nvmf_subsystem(w, subsystem); 312 } else { 313 for (subsystem = spdk_nvmf_subsystem_get_first(tgt); subsystem != NULL; 314 subsystem = spdk_nvmf_subsystem_get_next(subsystem)) { 315 dump_nvmf_subsystem(w, subsystem); 316 } 317 } 318 319 spdk_json_write_array_end(w); 320 spdk_jsonrpc_end_result(request, w); 321 free(req.tgt_name); 322 free(req.nqn); 323 } 324 SPDK_RPC_REGISTER("nvmf_get_subsystems", rpc_nvmf_get_subsystems, SPDK_RPC_RUNTIME) 325 326 struct rpc_subsystem_create { 327 char *nqn; 328 char *serial_number; 329 char *model_number; 330 char *tgt_name; 331 uint32_t max_namespaces; 332 bool allow_any_host; 333 bool ana_reporting; 334 uint16_t min_cntlid; 335 uint16_t max_cntlid; 336 }; 337 338 static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = { 339 {"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string}, 340 {"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true}, 341 {"model_number", offsetof(struct rpc_subsystem_create, model_number), spdk_json_decode_string, true}, 342 {"tgt_name", offsetof(struct rpc_subsystem_create, tgt_name), spdk_json_decode_string, true}, 343 {"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true}, 344 {"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true}, 345 {"ana_reporting", offsetof(struct rpc_subsystem_create, ana_reporting), spdk_json_decode_bool, true}, 346 {"min_cntlid", offsetof(struct rpc_subsystem_create, min_cntlid), spdk_json_decode_uint16, true}, 347 {"max_cntlid", offsetof(struct rpc_subsystem_create, max_cntlid), spdk_json_decode_uint16, true}, 348 }; 349 350 static void 351 rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem, 352 void *cb_arg, int status) 353 { 354 struct spdk_jsonrpc_request *request = cb_arg; 355 356 if (!status) { 357 spdk_jsonrpc_send_bool_response(request, true); 358 } else { 359 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 360 "Subsystem %s start failed", 361 subsystem->subnqn); 362 spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 363 } 364 } 365 366 static void 367 rpc_nvmf_create_subsystem(struct spdk_jsonrpc_request *request, 368 const struct spdk_json_val *params) 369 { 370 struct rpc_subsystem_create *req; 371 struct spdk_nvmf_subsystem *subsystem = NULL; 372 struct spdk_nvmf_tgt *tgt; 373 int rc = -1; 374 375 req = calloc(1, sizeof(*req)); 376 if (!req) { 377 SPDK_ERRLOG("Memory allocation failed\n"); 378 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 379 "Memory allocation failed"); 380 return; 381 } 382 req->min_cntlid = NVMF_MIN_CNTLID; 383 req->max_cntlid = NVMF_MAX_CNTLID; 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 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 390 goto cleanup; 391 } 392 393 tgt = spdk_nvmf_get_tgt(req->tgt_name); 394 if (!tgt) { 395 SPDK_ERRLOG("Unable to find target %s\n", req->tgt_name); 396 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 397 "Unable to find target %s", req->tgt_name); 398 goto cleanup; 399 } 400 401 subsystem = spdk_nvmf_subsystem_create(tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME, 402 req->max_namespaces); 403 if (!subsystem) { 404 SPDK_ERRLOG("Unable to create subsystem %s\n", req->nqn); 405 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 406 "Unable to create subsystem %s", req->nqn); 407 goto cleanup; 408 } 409 410 if (req->serial_number) { 411 if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) { 412 SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number); 413 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 414 "Invalid SN %s", req->serial_number); 415 goto cleanup; 416 } 417 } 418 419 if (req->model_number) { 420 if (spdk_nvmf_subsystem_set_mn(subsystem, req->model_number)) { 421 SPDK_ERRLOG("Subsystem %s: invalid model number '%s'\n", req->nqn, req->model_number); 422 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 423 "Invalid MN %s", req->model_number); 424 goto cleanup; 425 } 426 } 427 428 spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host); 429 430 spdk_nvmf_subsystem_set_ana_reporting(subsystem, req->ana_reporting); 431 432 if (nvmf_subsystem_set_cntlid_range(subsystem, req->min_cntlid, req->max_cntlid)) { 433 SPDK_ERRLOG("Subsystem %s: invalid cntlid range [%u-%u]\n", req->nqn, req->min_cntlid, 434 req->max_cntlid); 435 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 436 "Invalid cntlid range [%u-%u]", req->min_cntlid, req->max_cntlid); 437 goto cleanup; 438 } 439 440 rc = spdk_nvmf_subsystem_start(subsystem, 441 rpc_nvmf_subsystem_started, 442 request); 443 if (rc) { 444 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 445 "Failed to start subsystem"); 446 } 447 448 cleanup: 449 free(req->nqn); 450 free(req->tgt_name); 451 free(req->serial_number); 452 free(req->model_number); 453 free(req); 454 455 if (rc && subsystem) { 456 spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 457 } 458 } 459 SPDK_RPC_REGISTER("nvmf_create_subsystem", rpc_nvmf_create_subsystem, SPDK_RPC_RUNTIME) 460 461 struct rpc_delete_subsystem { 462 char *nqn; 463 char *tgt_name; 464 }; 465 466 static void 467 free_rpc_delete_subsystem(struct rpc_delete_subsystem *r) 468 { 469 free(r->nqn); 470 free(r->tgt_name); 471 } 472 473 static void 474 rpc_nvmf_subsystem_destroy_complete_cb(void *cb_arg) 475 { 476 struct spdk_jsonrpc_request *request = cb_arg; 477 478 spdk_jsonrpc_send_bool_response(request, true); 479 } 480 481 static void 482 rpc_nvmf_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem, 483 void *cb_arg, int status) 484 { 485 struct spdk_jsonrpc_request *request = cb_arg; 486 int rc; 487 488 nvmf_subsystem_remove_all_listeners(subsystem, true); 489 rc = spdk_nvmf_subsystem_destroy(subsystem, rpc_nvmf_subsystem_destroy_complete_cb, request); 490 if (rc) { 491 if (rc == -EINPROGRESS) { 492 /* response will be sent in completion callback */ 493 return; 494 } else { 495 SPDK_ERRLOG("Subsystem destruction failed, rc %d\n", rc); 496 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 497 "Subsystem destruction failed, rc %d", rc); 498 return; 499 } 500 } 501 spdk_jsonrpc_send_bool_response(request, true); 502 } 503 504 static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = { 505 {"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string}, 506 {"tgt_name", offsetof(struct rpc_delete_subsystem, tgt_name), spdk_json_decode_string, true}, 507 }; 508 509 static void 510 rpc_nvmf_delete_subsystem(struct spdk_jsonrpc_request *request, 511 const struct spdk_json_val *params) 512 { 513 struct rpc_delete_subsystem req = { 0 }; 514 struct spdk_nvmf_subsystem *subsystem; 515 struct spdk_nvmf_tgt *tgt; 516 int rc; 517 518 if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders, 519 SPDK_COUNTOF(rpc_delete_subsystem_decoders), 520 &req)) { 521 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 522 goto invalid; 523 } 524 525 if (req.nqn == NULL) { 526 SPDK_ERRLOG("missing name param\n"); 527 goto invalid; 528 } 529 530 tgt = spdk_nvmf_get_tgt(req.tgt_name); 531 if (!tgt) { 532 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 533 "Unable to find a target."); 534 goto invalid_custom_response; 535 } 536 537 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn); 538 if (!subsystem) { 539 goto invalid; 540 } 541 542 free_rpc_delete_subsystem(&req); 543 544 rc = spdk_nvmf_subsystem_stop(subsystem, 545 rpc_nvmf_subsystem_stopped, 546 request); 547 if (rc == -EBUSY) { 548 SPDK_ERRLOG("Subsystem currently in another state change try again later.\n"); 549 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 550 "Subsystem currently in another state change try again later."); 551 } else if (rc != 0) { 552 SPDK_ERRLOG("Unable to change state on subsystem. rc=%d\n", rc); 553 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 554 "Unable to change state on subsystem. rc=%d", rc); 555 } 556 557 return; 558 559 invalid: 560 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 561 invalid_custom_response: 562 free_rpc_delete_subsystem(&req); 563 } 564 SPDK_RPC_REGISTER("nvmf_delete_subsystem", rpc_nvmf_delete_subsystem, SPDK_RPC_RUNTIME) 565 566 struct rpc_listen_address { 567 char *transport; 568 char *adrfam; 569 char *traddr; 570 char *trsvcid; 571 }; 572 573 static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = { 574 /* NOTE: "transport" is kept for compatibility; new code should use "trtype" */ 575 {"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true}, 576 {"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true}, 577 {"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true}, 578 {"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string}, 579 {"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string, true}, 580 }; 581 582 static int 583 decode_rpc_listen_address(const struct spdk_json_val *val, void *out) 584 { 585 struct rpc_listen_address *req = (struct rpc_listen_address *)out; 586 if (spdk_json_decode_object(val, rpc_listen_address_decoders, 587 SPDK_COUNTOF(rpc_listen_address_decoders), 588 req)) { 589 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 590 return -1; 591 } 592 return 0; 593 } 594 595 static void 596 free_rpc_listen_address(struct rpc_listen_address *r) 597 { 598 free(r->transport); 599 free(r->adrfam); 600 free(r->traddr); 601 free(r->trsvcid); 602 } 603 604 enum nvmf_rpc_listen_op { 605 NVMF_RPC_LISTEN_ADD, 606 NVMF_RPC_LISTEN_REMOVE, 607 NVMF_RPC_LISTEN_SET_ANA_STATE, 608 }; 609 610 struct nvmf_rpc_listener_ctx { 611 char *nqn; 612 char *tgt_name; 613 struct spdk_nvmf_tgt *tgt; 614 struct spdk_nvmf_transport *transport; 615 struct spdk_nvmf_subsystem *subsystem; 616 struct rpc_listen_address address; 617 char *ana_state_str; 618 enum spdk_nvme_ana_state ana_state; 619 uint32_t anagrpid; 620 621 struct spdk_jsonrpc_request *request; 622 struct spdk_nvme_transport_id trid; 623 enum nvmf_rpc_listen_op op; 624 bool response_sent; 625 struct spdk_nvmf_listen_opts opts; 626 627 /* Additional options for listener creation. */ 628 struct spdk_nvmf_listener_opts listener_opts; 629 }; 630 631 static const struct spdk_json_object_decoder nvmf_rpc_listener_decoder[] = { 632 {"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string}, 633 {"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address}, 634 {"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true}, 635 {"secure_channel", offsetof(struct nvmf_rpc_listener_ctx, listener_opts.secure_channel), spdk_json_decode_bool, true}, 636 }; 637 638 static void 639 nvmf_rpc_listener_ctx_free(struct nvmf_rpc_listener_ctx *ctx) 640 { 641 free(ctx->nqn); 642 free(ctx->tgt_name); 643 free_rpc_listen_address(&ctx->address); 644 free(ctx->ana_state_str); 645 free(ctx); 646 } 647 648 static void 649 nvmf_rpc_listen_resumed(struct spdk_nvmf_subsystem *subsystem, 650 void *cb_arg, int status) 651 { 652 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 653 struct spdk_jsonrpc_request *request; 654 655 request = ctx->request; 656 if (ctx->response_sent) { 657 /* If an error occurred, the response has already been sent. */ 658 nvmf_rpc_listener_ctx_free(ctx); 659 return; 660 } 661 662 nvmf_rpc_listener_ctx_free(ctx); 663 664 spdk_jsonrpc_send_bool_response(request, true); 665 } 666 667 static void 668 nvmf_rpc_subsystem_listen(void *cb_arg, int status) 669 { 670 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 671 672 if (status) { 673 /* Destroy the listener that we just created. Ignore the error code because 674 * the RPC is failing already anyway. */ 675 spdk_nvmf_tgt_stop_listen(ctx->tgt, &ctx->trid); 676 677 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 678 "Invalid parameters"); 679 ctx->response_sent = true; 680 } 681 682 if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) { 683 if (!ctx->response_sent) { 684 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 685 "Internal error"); 686 } 687 nvmf_rpc_listener_ctx_free(ctx); 688 /* Can't really do anything to recover here - subsystem will remain paused. */ 689 } 690 } 691 static void 692 nvmf_rpc_stop_listen_async_done(void *cb_arg, int status) 693 { 694 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 695 696 if (status) { 697 SPDK_ERRLOG("Unable to stop listener.\n"); 698 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 699 "error stopping listener: %d", status); 700 ctx->response_sent = true; 701 } 702 703 if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) { 704 if (!ctx->response_sent) { 705 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 706 "Internal error"); 707 } 708 nvmf_rpc_listener_ctx_free(ctx); 709 /* Can't really do anything to recover here - subsystem will remain paused. */ 710 } 711 } 712 713 static void 714 nvmf_rpc_set_ana_state_done(void *cb_arg, int status) 715 { 716 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 717 718 if (status) { 719 SPDK_ERRLOG("Unable to set ANA state.\n"); 720 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 721 "error setting ANA state: %d", status); 722 ctx->response_sent = true; 723 } 724 725 if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) { 726 if (!ctx->response_sent) { 727 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 728 "Internal error"); 729 } 730 nvmf_rpc_listener_ctx_free(ctx); 731 /* Can't really do anything to recover here - subsystem will remain paused. */ 732 } 733 } 734 735 static void 736 nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem, 737 void *cb_arg, int status) 738 { 739 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 740 int rc; 741 742 if (ctx->op == NVMF_RPC_LISTEN_ADD) { 743 if (!nvmf_subsystem_find_listener(subsystem, &ctx->trid)) { 744 rc = spdk_nvmf_tgt_listen_ext(ctx->tgt, &ctx->trid, &ctx->opts); 745 if (rc == 0) { 746 spdk_nvmf_subsystem_add_listener_ext(ctx->subsystem, &ctx->trid, nvmf_rpc_subsystem_listen, ctx, 747 &ctx->listener_opts); 748 return; 749 } 750 751 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 752 "Invalid parameters"); 753 ctx->response_sent = true; 754 } 755 } else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) { 756 rc = spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid); 757 if (rc == 0) { 758 spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, subsystem, 759 nvmf_rpc_stop_listen_async_done, ctx); 760 return; 761 } 762 SPDK_ERRLOG("Unable to remove listener, rc %d\n", rc); 763 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 764 "Invalid parameters"); 765 ctx->response_sent = true; 766 } else if (ctx->op == NVMF_RPC_LISTEN_SET_ANA_STATE) { 767 nvmf_subsystem_set_ana_state(subsystem, &ctx->trid, ctx->ana_state, ctx->anagrpid, 768 nvmf_rpc_set_ana_state_done, ctx); 769 return; 770 } else { 771 SPDK_UNREACHABLE(); 772 } 773 774 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) { 775 if (!ctx->response_sent) { 776 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 777 "Internal error"); 778 } 779 nvmf_rpc_listener_ctx_free(ctx); 780 /* Can't really do anything to recover here - subsystem will remain paused. */ 781 } 782 } 783 784 static int 785 rpc_listen_address_to_trid(const struct rpc_listen_address *address, 786 struct spdk_nvme_transport_id *trid) 787 { 788 size_t len; 789 790 memset(trid, 0, sizeof(*trid)); 791 792 if (spdk_nvme_transport_id_populate_trstring(trid, address->transport)) { 793 SPDK_ERRLOG("Invalid transport string: %s\n", address->transport); 794 return -EINVAL; 795 } 796 797 if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) { 798 SPDK_ERRLOG("Invalid transport type: %s\n", address->transport); 799 return -EINVAL; 800 } 801 802 if (address->adrfam) { 803 if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) { 804 SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam); 805 return -EINVAL; 806 } 807 } else { 808 trid->adrfam = SPDK_NVMF_ADRFAM_IPV4; 809 } 810 811 len = strlen(address->traddr); 812 if (len > sizeof(trid->traddr) - 1) { 813 SPDK_ERRLOG("Transport address longer than %zu characters: %s\n", 814 sizeof(trid->traddr) - 1, address->traddr); 815 return -EINVAL; 816 } 817 memcpy(trid->traddr, address->traddr, len + 1); 818 819 trid->trsvcid[0] = '\0'; 820 if (address->trsvcid) { 821 len = strlen(address->trsvcid); 822 if (len > sizeof(trid->trsvcid) - 1) { 823 SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n", 824 sizeof(trid->trsvcid) - 1, address->trsvcid); 825 return -EINVAL; 826 } 827 memcpy(trid->trsvcid, address->trsvcid, len + 1); 828 } 829 830 return 0; 831 } 832 833 static void 834 rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request, 835 const struct spdk_json_val *params) 836 { 837 struct nvmf_rpc_listener_ctx *ctx; 838 struct spdk_nvmf_subsystem *subsystem; 839 struct spdk_nvmf_tgt *tgt; 840 int rc; 841 842 ctx = calloc(1, sizeof(*ctx)); 843 if (!ctx) { 844 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 845 return; 846 } 847 848 ctx->request = request; 849 850 spdk_nvmf_subsystem_listener_opts_init(&ctx->listener_opts, sizeof(ctx->listener_opts)); 851 852 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_listener_decoder, 853 SPDK_COUNTOF(nvmf_rpc_listener_decoder), 854 ctx)) { 855 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 856 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 857 nvmf_rpc_listener_ctx_free(ctx); 858 return; 859 } 860 861 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 862 if (!tgt) { 863 SPDK_ERRLOG("Unable to find a target object.\n"); 864 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 865 "Unable to find a target."); 866 nvmf_rpc_listener_ctx_free(ctx); 867 return; 868 } 869 ctx->tgt = tgt; 870 871 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 872 if (!subsystem) { 873 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 874 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 875 nvmf_rpc_listener_ctx_free(ctx); 876 return; 877 } 878 879 ctx->subsystem = subsystem; 880 881 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 882 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 883 "Invalid parameters"); 884 nvmf_rpc_listener_ctx_free(ctx); 885 return; 886 } 887 888 ctx->op = NVMF_RPC_LISTEN_ADD; 889 spdk_nvmf_listen_opts_init(&ctx->opts, sizeof(ctx->opts)); 890 ctx->opts.transport_specific = params; 891 if (subsystem->flags.allow_any_host == 1 && ctx->listener_opts.secure_channel == true) { 892 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 893 "Cannot establish secure channel, when 'allow_any_host' is set"); 894 nvmf_rpc_listener_ctx_free(ctx); 895 return; 896 } 897 ctx->opts.secure_channel = ctx->listener_opts.secure_channel; 898 899 rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx); 900 if (rc != 0) { 901 if (rc == -EBUSY) { 902 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 903 "subsystem busy, retry later.\n"); 904 } else { 905 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 906 } 907 nvmf_rpc_listener_ctx_free(ctx); 908 } 909 } 910 SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", rpc_nvmf_subsystem_add_listener, 911 SPDK_RPC_RUNTIME); 912 913 static void 914 rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request, 915 const struct spdk_json_val *params) 916 { 917 struct nvmf_rpc_listener_ctx *ctx; 918 struct spdk_nvmf_subsystem *subsystem; 919 struct spdk_nvmf_tgt *tgt; 920 int rc; 921 922 ctx = calloc(1, sizeof(*ctx)); 923 if (!ctx) { 924 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 925 return; 926 } 927 928 ctx->request = request; 929 930 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder, 931 SPDK_COUNTOF(nvmf_rpc_listener_decoder), 932 ctx)) { 933 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 934 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 935 nvmf_rpc_listener_ctx_free(ctx); 936 return; 937 } 938 939 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 940 if (!tgt) { 941 SPDK_ERRLOG("Unable to find a target object.\n"); 942 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 943 "Unable to find a target."); 944 nvmf_rpc_listener_ctx_free(ctx); 945 return; 946 } 947 ctx->tgt = tgt; 948 949 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 950 if (!subsystem) { 951 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 952 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 953 nvmf_rpc_listener_ctx_free(ctx); 954 return; 955 } 956 957 ctx->subsystem = subsystem; 958 959 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 960 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 961 "Invalid parameters"); 962 nvmf_rpc_listener_ctx_free(ctx); 963 return; 964 } 965 966 ctx->transport = spdk_nvmf_tgt_get_transport(tgt, ctx->trid.trstring); 967 if (!ctx->transport) { 968 SPDK_ERRLOG("Unable to find %s transport. The transport must be created first also make sure it is properly registered.\n", 969 ctx->trid.trstring); 970 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 971 "Invalid parameters"); 972 nvmf_rpc_listener_ctx_free(ctx); 973 return; 974 } 975 976 ctx->op = NVMF_RPC_LISTEN_REMOVE; 977 978 rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx); 979 if (rc != 0) { 980 if (rc == -EBUSY) { 981 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 982 "subsystem busy, retry later.\n"); 983 } else { 984 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 985 } 986 nvmf_rpc_listener_ctx_free(ctx); 987 } 988 } 989 SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", rpc_nvmf_subsystem_remove_listener, 990 SPDK_RPC_RUNTIME); 991 992 struct nvmf_rpc_referral_ctx { 993 char *tgt_name; 994 struct spdk_nvmf_tgt *tgt; 995 struct spdk_nvmf_transport *transport; 996 struct spdk_nvmf_subsystem *subsystem; 997 struct rpc_listen_address address; 998 struct spdk_jsonrpc_request *request; 999 struct spdk_nvme_transport_id trid; 1000 bool response_sent; 1001 bool secure_channel; 1002 }; 1003 1004 static const struct spdk_json_object_decoder nvmf_rpc_referral_decoder[] = { 1005 {"address", offsetof(struct nvmf_rpc_referral_ctx, address), decode_rpc_listen_address}, 1006 {"tgt_name", offsetof(struct nvmf_rpc_referral_ctx, tgt_name), spdk_json_decode_string, true}, 1007 {"secure_channel", offsetof(struct nvmf_rpc_referral_ctx, secure_channel), spdk_json_decode_bool, true}, 1008 }; 1009 1010 static void 1011 nvmf_rpc_referral_ctx_free(struct nvmf_rpc_referral_ctx *ctx) 1012 { 1013 free(ctx->tgt_name); 1014 free_rpc_listen_address(&ctx->address); 1015 free(ctx); 1016 } 1017 1018 static void 1019 rpc_nvmf_add_referral(struct spdk_jsonrpc_request *request, 1020 const struct spdk_json_val *params) 1021 { 1022 struct nvmf_rpc_referral_ctx *ctx; 1023 struct spdk_nvmf_tgt *tgt; 1024 int rc; 1025 1026 ctx = calloc(1, sizeof(*ctx)); 1027 if (!ctx) { 1028 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1029 return; 1030 } 1031 1032 ctx->request = request; 1033 1034 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_referral_decoder, 1035 SPDK_COUNTOF(nvmf_rpc_referral_decoder), 1036 ctx)) { 1037 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 1038 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1039 nvmf_rpc_referral_ctx_free(ctx); 1040 return; 1041 } 1042 1043 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1044 if (!tgt) { 1045 SPDK_ERRLOG("Unable to find a target object.\n"); 1046 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1047 "Unable to find a target."); 1048 nvmf_rpc_referral_ctx_free(ctx); 1049 return; 1050 } 1051 ctx->tgt = tgt; 1052 1053 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 1054 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1055 "Invalid parameters"); 1056 nvmf_rpc_referral_ctx_free(ctx); 1057 return; 1058 } 1059 1060 if ((ctx->trid.trtype == SPDK_NVME_TRANSPORT_TCP || 1061 ctx->trid.trtype == SPDK_NVME_TRANSPORT_RDMA) && 1062 !strlen(ctx->trid.trsvcid)) { 1063 SPDK_ERRLOG("Service ID is required.\n"); 1064 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1065 "Service ID is required."); 1066 nvmf_rpc_referral_ctx_free(ctx); 1067 return; 1068 } 1069 1070 rc = spdk_nvmf_tgt_add_referral(tgt, &ctx->trid, ctx->secure_channel); 1071 if (rc != 0) { 1072 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1073 "Internal error"); 1074 nvmf_rpc_referral_ctx_free(ctx); 1075 return; 1076 } 1077 1078 nvmf_rpc_referral_ctx_free(ctx); 1079 1080 spdk_jsonrpc_send_bool_response(request, true); 1081 } 1082 1083 SPDK_RPC_REGISTER("nvmf_discovery_add_referral", rpc_nvmf_add_referral, 1084 SPDK_RPC_RUNTIME); 1085 1086 static void 1087 rpc_nvmf_remove_referral(struct spdk_jsonrpc_request *request, 1088 const struct spdk_json_val *params) 1089 { 1090 struct nvmf_rpc_referral_ctx *ctx; 1091 struct spdk_nvmf_tgt *tgt; 1092 1093 ctx = calloc(1, sizeof(*ctx)); 1094 if (!ctx) { 1095 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1096 return; 1097 } 1098 1099 ctx->request = request; 1100 1101 if (spdk_json_decode_object(params, nvmf_rpc_referral_decoder, 1102 SPDK_COUNTOF(nvmf_rpc_referral_decoder), 1103 ctx)) { 1104 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1105 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1106 nvmf_rpc_referral_ctx_free(ctx); 1107 return; 1108 } 1109 1110 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1111 if (!tgt) { 1112 SPDK_ERRLOG("Unable to find a target object.\n"); 1113 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1114 "Unable to find a target."); 1115 nvmf_rpc_referral_ctx_free(ctx); 1116 return; 1117 } 1118 ctx->tgt = tgt; 1119 1120 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 1121 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1122 "Invalid parameters"); 1123 nvmf_rpc_referral_ctx_free(ctx); 1124 return; 1125 } 1126 1127 if (spdk_nvmf_tgt_remove_referral(tgt, &ctx->trid)) { 1128 SPDK_ERRLOG("Failed to remove referral.\n"); 1129 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1130 "Unable to remove a referral."); 1131 nvmf_rpc_referral_ctx_free(ctx); 1132 return; 1133 } 1134 1135 nvmf_rpc_referral_ctx_free(ctx); 1136 1137 spdk_jsonrpc_send_bool_response(request, true); 1138 } 1139 1140 SPDK_RPC_REGISTER("nvmf_discovery_remove_referral", rpc_nvmf_remove_referral, 1141 SPDK_RPC_RUNTIME); 1142 1143 static void 1144 dump_nvmf_referral(struct spdk_json_write_ctx *w, 1145 struct spdk_nvmf_referral *referral) 1146 { 1147 spdk_json_write_object_begin(w); 1148 1149 spdk_json_write_named_object_begin(w, "address"); 1150 nvmf_transport_listen_dump_trid(&referral->trid, w); 1151 spdk_json_write_object_end(w); 1152 spdk_json_write_named_bool(w, "secure_channel", 1153 referral->entry.treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED); 1154 1155 spdk_json_write_object_end(w); 1156 } 1157 1158 struct rpc_get_referrals_ctx { 1159 char *tgt_name; 1160 }; 1161 1162 static const struct spdk_json_object_decoder rpc_get_referrals_decoders[] = { 1163 {"tgt_name", offsetof(struct rpc_get_referrals_ctx, tgt_name), spdk_json_decode_string, true}, 1164 }; 1165 1166 static void 1167 free_rpc_get_referrals_ctx(struct rpc_get_referrals_ctx *ctx) 1168 { 1169 free(ctx->tgt_name); 1170 free(ctx); 1171 } 1172 1173 static void 1174 rpc_nvmf_get_referrals(struct spdk_jsonrpc_request *request, 1175 const struct spdk_json_val *params) 1176 { 1177 struct rpc_get_referrals_ctx *ctx; 1178 struct spdk_nvmf_tgt *tgt; 1179 struct spdk_json_write_ctx *w; 1180 struct spdk_nvmf_referral *referral; 1181 1182 ctx = calloc(1, sizeof(*ctx)); 1183 if (!ctx) { 1184 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1185 "Out of memory"); 1186 return; 1187 } 1188 1189 if (params) { 1190 if (spdk_json_decode_object(params, rpc_get_referrals_decoders, 1191 SPDK_COUNTOF(rpc_get_referrals_decoders), 1192 ctx)) { 1193 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1194 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1195 "Invalid parameters"); 1196 free_rpc_get_referrals_ctx(ctx); 1197 return; 1198 } 1199 } 1200 1201 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1202 if (!tgt) { 1203 SPDK_ERRLOG("Unable to find a target object.\n"); 1204 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1205 "Unable to find a target"); 1206 free_rpc_get_referrals_ctx(ctx); 1207 return; 1208 } 1209 1210 w = spdk_jsonrpc_begin_result(request); 1211 1212 spdk_json_write_array_begin(w); 1213 1214 TAILQ_FOREACH(referral, &tgt->referrals, link) { 1215 dump_nvmf_referral(w, referral); 1216 } 1217 1218 spdk_json_write_array_end(w); 1219 1220 spdk_jsonrpc_end_result(request, w); 1221 1222 free_rpc_get_referrals_ctx(ctx); 1223 } 1224 SPDK_RPC_REGISTER("nvmf_discovery_get_referrals", rpc_nvmf_get_referrals, 1225 SPDK_RPC_RUNTIME); 1226 1227 static const struct spdk_json_object_decoder nvmf_rpc_set_ana_state_decoder[] = { 1228 {"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string}, 1229 {"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address}, 1230 {"ana_state", offsetof(struct nvmf_rpc_listener_ctx, ana_state_str), spdk_json_decode_string}, 1231 {"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true}, 1232 {"anagrpid", offsetof(struct nvmf_rpc_listener_ctx, anagrpid), spdk_json_decode_uint32, true}, 1233 }; 1234 1235 static int 1236 rpc_ana_state_parse(const char *str, enum spdk_nvme_ana_state *ana_state) 1237 { 1238 if (ana_state == NULL || str == NULL) { 1239 return -EINVAL; 1240 } 1241 1242 if (strcasecmp(str, "optimized") == 0) { 1243 *ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; 1244 } else if (strcasecmp(str, "non_optimized") == 0) { 1245 *ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE; 1246 } else if (strcasecmp(str, "inaccessible") == 0) { 1247 *ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE; 1248 } else { 1249 return -ENOENT; 1250 } 1251 1252 return 0; 1253 } 1254 1255 static void 1256 rpc_nvmf_subsystem_listener_set_ana_state(struct spdk_jsonrpc_request *request, 1257 const struct spdk_json_val *params) 1258 { 1259 struct nvmf_rpc_listener_ctx *ctx; 1260 struct spdk_nvmf_subsystem *subsystem; 1261 struct spdk_nvmf_tgt *tgt; 1262 1263 ctx = calloc(1, sizeof(*ctx)); 1264 if (!ctx) { 1265 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1266 "Out of memory"); 1267 return; 1268 } 1269 1270 ctx->request = request; 1271 1272 if (spdk_json_decode_object(params, nvmf_rpc_set_ana_state_decoder, 1273 SPDK_COUNTOF(nvmf_rpc_set_ana_state_decoder), 1274 ctx)) { 1275 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1276 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1277 "Invalid parameters"); 1278 nvmf_rpc_listener_ctx_free(ctx); 1279 return; 1280 } 1281 1282 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1283 if (!tgt) { 1284 SPDK_ERRLOG("Unable to find a target object.\n"); 1285 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1286 "Unable to find a target.\n"); 1287 nvmf_rpc_listener_ctx_free(ctx); 1288 return; 1289 } 1290 1291 ctx->tgt = tgt; 1292 1293 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1294 if (!subsystem) { 1295 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1296 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1297 "Unable to find subsystem with NQN %s", 1298 ctx->nqn); 1299 nvmf_rpc_listener_ctx_free(ctx); 1300 return; 1301 } 1302 1303 ctx->subsystem = subsystem; 1304 1305 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 1306 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1307 "Invalid parameters"); 1308 nvmf_rpc_listener_ctx_free(ctx); 1309 return; 1310 } 1311 1312 if (rpc_ana_state_parse(ctx->ana_state_str, &ctx->ana_state)) { 1313 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1314 "Invalid parameters"); 1315 nvmf_rpc_listener_ctx_free(ctx); 1316 return; 1317 } 1318 1319 ctx->op = NVMF_RPC_LISTEN_SET_ANA_STATE; 1320 1321 if (spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx)) { 1322 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1323 "Internal error"); 1324 nvmf_rpc_listener_ctx_free(ctx); 1325 } 1326 } 1327 SPDK_RPC_REGISTER("nvmf_subsystem_listener_set_ana_state", 1328 rpc_nvmf_subsystem_listener_set_ana_state, SPDK_RPC_RUNTIME); 1329 1330 struct spdk_nvmf_ns_params { 1331 char *bdev_name; 1332 char *ptpl_file; 1333 uint32_t nsid; 1334 char nguid[16]; 1335 char eui64[8]; 1336 struct spdk_uuid uuid; 1337 uint32_t anagrpid; 1338 }; 1339 1340 static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = { 1341 {"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true}, 1342 {"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string}, 1343 {"ptpl_file", offsetof(struct spdk_nvmf_ns_params, ptpl_file), spdk_json_decode_string, true}, 1344 {"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true}, 1345 {"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true}, 1346 {"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), spdk_json_decode_uuid, true}, 1347 {"anagrpid", offsetof(struct spdk_nvmf_ns_params, anagrpid), spdk_json_decode_uint32, true}, 1348 }; 1349 1350 static int 1351 decode_rpc_ns_params(const struct spdk_json_val *val, void *out) 1352 { 1353 struct spdk_nvmf_ns_params *ns_params = out; 1354 1355 return spdk_json_decode_object(val, rpc_ns_params_decoders, 1356 SPDK_COUNTOF(rpc_ns_params_decoders), 1357 ns_params); 1358 } 1359 1360 struct nvmf_rpc_ns_ctx { 1361 char *nqn; 1362 char *tgt_name; 1363 struct spdk_nvmf_ns_params ns_params; 1364 1365 struct spdk_jsonrpc_request *request; 1366 bool response_sent; 1367 }; 1368 1369 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = { 1370 {"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string}, 1371 {"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params}, 1372 {"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1373 }; 1374 1375 static void 1376 nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx) 1377 { 1378 free(ctx->nqn); 1379 free(ctx->tgt_name); 1380 free(ctx->ns_params.bdev_name); 1381 free(ctx->ns_params.ptpl_file); 1382 free(ctx); 1383 } 1384 1385 static void 1386 nvmf_rpc_ns_failback_resumed(struct spdk_nvmf_subsystem *subsystem, 1387 void *cb_arg, int status) 1388 { 1389 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1390 struct spdk_jsonrpc_request *request = ctx->request; 1391 1392 if (status) { 1393 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1394 "Unable to add ns, subsystem in invalid state"); 1395 } else { 1396 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1397 "Unable to add ns, subsystem in active state"); 1398 } 1399 1400 nvmf_rpc_ns_ctx_free(ctx); 1401 } 1402 1403 static void 1404 nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1405 void *cb_arg, int status) 1406 { 1407 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1408 struct spdk_jsonrpc_request *request = ctx->request; 1409 uint32_t nsid = ctx->ns_params.nsid; 1410 bool response_sent = ctx->response_sent; 1411 struct spdk_json_write_ctx *w; 1412 int rc; 1413 1414 /* The case where the call to add the namespace was successful, but the subsystem couldn't be resumed. */ 1415 if (status && !ctx->response_sent) { 1416 rc = spdk_nvmf_subsystem_remove_ns(subsystem, nsid); 1417 if (rc != 0) { 1418 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1419 "Unable to add ns, subsystem in invalid state"); 1420 nvmf_rpc_ns_ctx_free(ctx); 1421 return; 1422 } 1423 1424 rc = spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_failback_resumed, ctx); 1425 if (rc != 0) { 1426 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1427 nvmf_rpc_ns_ctx_free(ctx); 1428 return; 1429 } 1430 1431 return; 1432 } 1433 1434 nvmf_rpc_ns_ctx_free(ctx); 1435 1436 if (response_sent) { 1437 return; 1438 } 1439 1440 w = spdk_jsonrpc_begin_result(request); 1441 spdk_json_write_uint32(w, nsid); 1442 spdk_jsonrpc_end_result(request, w); 1443 } 1444 1445 static void 1446 nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1447 void *cb_arg, int status) 1448 { 1449 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1450 struct spdk_nvmf_ns_opts ns_opts; 1451 1452 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 1453 ns_opts.nsid = ctx->ns_params.nsid; 1454 1455 SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch"); 1456 memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid)); 1457 1458 SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch"); 1459 memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64)); 1460 1461 if (!spdk_uuid_is_null(&ctx->ns_params.uuid)) { 1462 ns_opts.uuid = ctx->ns_params.uuid; 1463 } 1464 1465 ns_opts.anagrpid = ctx->ns_params.anagrpid; 1466 1467 ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns_ext(subsystem, ctx->ns_params.bdev_name, 1468 &ns_opts, sizeof(ns_opts), 1469 ctx->ns_params.ptpl_file); 1470 if (ctx->ns_params.nsid == 0) { 1471 SPDK_ERRLOG("Unable to add namespace\n"); 1472 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1473 "Invalid parameters"); 1474 ctx->response_sent = true; 1475 goto resume; 1476 } 1477 1478 resume: 1479 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) { 1480 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1481 nvmf_rpc_ns_ctx_free(ctx); 1482 } 1483 } 1484 1485 static void 1486 rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request, 1487 const struct spdk_json_val *params) 1488 { 1489 struct nvmf_rpc_ns_ctx *ctx; 1490 struct spdk_nvmf_subsystem *subsystem; 1491 struct spdk_nvmf_tgt *tgt; 1492 int rc; 1493 1494 ctx = calloc(1, sizeof(*ctx)); 1495 if (!ctx) { 1496 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1497 return; 1498 } 1499 1500 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ns_decoder, 1501 SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder), 1502 ctx)) { 1503 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1504 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1505 nvmf_rpc_ns_ctx_free(ctx); 1506 return; 1507 } 1508 1509 ctx->request = request; 1510 ctx->response_sent = false; 1511 1512 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1513 if (!tgt) { 1514 SPDK_ERRLOG("Unable to find a target object.\n"); 1515 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1516 "Unable to find a target."); 1517 nvmf_rpc_ns_ctx_free(ctx); 1518 return; 1519 } 1520 1521 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1522 if (!subsystem) { 1523 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1524 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1525 nvmf_rpc_ns_ctx_free(ctx); 1526 return; 1527 } 1528 1529 rc = spdk_nvmf_subsystem_pause(subsystem, ctx->ns_params.nsid, nvmf_rpc_ns_paused, ctx); 1530 if (rc != 0) { 1531 if (rc == -EBUSY) { 1532 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1533 "subsystem busy, retry later.\n"); 1534 } else { 1535 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1536 } 1537 nvmf_rpc_ns_ctx_free(ctx); 1538 } 1539 } 1540 SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME) 1541 1542 struct nvmf_rpc_remove_ns_ctx { 1543 char *nqn; 1544 char *tgt_name; 1545 uint32_t nsid; 1546 1547 struct spdk_jsonrpc_request *request; 1548 bool response_sent; 1549 }; 1550 1551 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = { 1552 {"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string}, 1553 {"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32}, 1554 {"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1555 }; 1556 1557 static void 1558 nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx) 1559 { 1560 free(ctx->nqn); 1561 free(ctx->tgt_name); 1562 free(ctx); 1563 } 1564 1565 static void 1566 nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1567 void *cb_arg, int status) 1568 { 1569 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1570 struct spdk_jsonrpc_request *request = ctx->request; 1571 bool response_sent = ctx->response_sent; 1572 1573 nvmf_rpc_remove_ns_ctx_free(ctx); 1574 1575 if (response_sent) { 1576 return; 1577 } 1578 1579 spdk_jsonrpc_send_bool_response(request, true); 1580 } 1581 1582 static void 1583 nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1584 void *cb_arg, int status) 1585 { 1586 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1587 int ret; 1588 1589 ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid); 1590 if (ret < 0) { 1591 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid); 1592 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1593 "Invalid parameters"); 1594 ctx->response_sent = true; 1595 } 1596 1597 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) { 1598 if (!ctx->response_sent) { 1599 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1600 } 1601 nvmf_rpc_remove_ns_ctx_free(ctx); 1602 } 1603 } 1604 1605 static void 1606 rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request, 1607 const struct spdk_json_val *params) 1608 { 1609 struct nvmf_rpc_remove_ns_ctx *ctx; 1610 struct spdk_nvmf_subsystem *subsystem; 1611 struct spdk_nvmf_tgt *tgt; 1612 int rc; 1613 1614 ctx = calloc(1, sizeof(*ctx)); 1615 if (!ctx) { 1616 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1617 return; 1618 } 1619 1620 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder, 1621 SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder), 1622 ctx)) { 1623 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1624 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1625 nvmf_rpc_remove_ns_ctx_free(ctx); 1626 return; 1627 } 1628 1629 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1630 if (!tgt) { 1631 SPDK_ERRLOG("Unable to find a target object.\n"); 1632 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1633 "Unable to find a target."); 1634 nvmf_rpc_remove_ns_ctx_free(ctx); 1635 return; 1636 } 1637 1638 ctx->request = request; 1639 ctx->response_sent = false; 1640 1641 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1642 if (!subsystem) { 1643 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1644 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1645 nvmf_rpc_remove_ns_ctx_free(ctx); 1646 return; 1647 } 1648 1649 rc = spdk_nvmf_subsystem_pause(subsystem, ctx->nsid, nvmf_rpc_remove_ns_paused, ctx); 1650 if (rc != 0) { 1651 if (rc == -EBUSY) { 1652 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1653 "subsystem busy, retry later.\n"); 1654 } else { 1655 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1656 } 1657 nvmf_rpc_remove_ns_ctx_free(ctx); 1658 } 1659 } 1660 SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME) 1661 1662 struct nvmf_rpc_host_ctx { 1663 struct spdk_jsonrpc_request *request; 1664 char *nqn; 1665 char *host; 1666 char *tgt_name; 1667 bool allow_any_host; 1668 }; 1669 1670 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = { 1671 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1672 {"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string}, 1673 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1674 }; 1675 1676 static void 1677 nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx) 1678 { 1679 free(ctx->nqn); 1680 free(ctx->host); 1681 free(ctx->tgt_name); 1682 } 1683 1684 static void 1685 rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request, 1686 const struct spdk_json_val *params) 1687 { 1688 struct nvmf_rpc_host_ctx ctx = {}; 1689 struct spdk_nvmf_subsystem *subsystem; 1690 struct spdk_nvmf_tgt *tgt; 1691 int rc; 1692 1693 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_subsystem_host_decoder, 1694 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1695 &ctx)) { 1696 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1697 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1698 nvmf_rpc_host_ctx_free(&ctx); 1699 return; 1700 } 1701 1702 tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1703 if (!tgt) { 1704 SPDK_ERRLOG("Unable to find a target object.\n"); 1705 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1706 "Unable to find a target."); 1707 nvmf_rpc_host_ctx_free(&ctx); 1708 return; 1709 } 1710 1711 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 1712 if (!subsystem) { 1713 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn); 1714 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1715 nvmf_rpc_host_ctx_free(&ctx); 1716 return; 1717 } 1718 1719 rc = spdk_nvmf_subsystem_add_host(subsystem, ctx.host, params); 1720 if (rc != 0) { 1721 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1722 nvmf_rpc_host_ctx_free(&ctx); 1723 return; 1724 } 1725 1726 spdk_jsonrpc_send_bool_response(request, true); 1727 nvmf_rpc_host_ctx_free(&ctx); 1728 } 1729 SPDK_RPC_REGISTER("nvmf_subsystem_add_host", rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME) 1730 1731 static void 1732 rpc_nvmf_subsystem_remove_host_done(void *_ctx, int status) 1733 { 1734 struct nvmf_rpc_host_ctx *ctx = _ctx; 1735 1736 spdk_jsonrpc_send_bool_response(ctx->request, true); 1737 nvmf_rpc_host_ctx_free(ctx); 1738 free(ctx); 1739 } 1740 1741 static void 1742 rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request, 1743 const struct spdk_json_val *params) 1744 { 1745 struct nvmf_rpc_host_ctx *ctx; 1746 struct spdk_nvmf_subsystem *subsystem; 1747 struct spdk_nvmf_tgt *tgt; 1748 int rc; 1749 1750 ctx = calloc(1, sizeof(*ctx)); 1751 if (ctx == NULL) { 1752 SPDK_ERRLOG("Unable to allocate context to perform RPC\n"); 1753 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1754 return; 1755 } 1756 1757 ctx->request = request; 1758 1759 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 1760 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1761 ctx)) { 1762 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1763 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1764 nvmf_rpc_host_ctx_free(ctx); 1765 free(ctx); 1766 return; 1767 } 1768 1769 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1770 if (!tgt) { 1771 SPDK_ERRLOG("Unable to find a target object.\n"); 1772 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1773 "Unable to find a target."); 1774 nvmf_rpc_host_ctx_free(ctx); 1775 free(ctx); 1776 return; 1777 } 1778 1779 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1780 if (!subsystem) { 1781 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1782 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1783 nvmf_rpc_host_ctx_free(ctx); 1784 free(ctx); 1785 return; 1786 } 1787 1788 rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host); 1789 if (rc != 0) { 1790 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1791 nvmf_rpc_host_ctx_free(ctx); 1792 free(ctx); 1793 return; 1794 } 1795 1796 rc = spdk_nvmf_subsystem_disconnect_host(subsystem, ctx->host, 1797 rpc_nvmf_subsystem_remove_host_done, 1798 ctx); 1799 if (rc != 0) { 1800 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1801 nvmf_rpc_host_ctx_free(ctx); 1802 free(ctx); 1803 return; 1804 } 1805 } 1806 SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", rpc_nvmf_subsystem_remove_host, 1807 SPDK_RPC_RUNTIME) 1808 1809 1810 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = { 1811 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1812 {"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool}, 1813 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1814 }; 1815 1816 static void 1817 rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request, 1818 const struct spdk_json_val *params) 1819 { 1820 struct nvmf_rpc_host_ctx ctx = {}; 1821 struct spdk_nvmf_subsystem *subsystem; 1822 struct spdk_nvmf_tgt *tgt; 1823 int rc; 1824 1825 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder, 1826 SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder), 1827 &ctx)) { 1828 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1829 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1830 nvmf_rpc_host_ctx_free(&ctx); 1831 return; 1832 } 1833 1834 tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1835 if (!tgt) { 1836 SPDK_ERRLOG("Unable to find a target object.\n"); 1837 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1838 "Unable to find a target."); 1839 nvmf_rpc_host_ctx_free(&ctx); 1840 return; 1841 } 1842 1843 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 1844 if (!subsystem) { 1845 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn); 1846 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1847 nvmf_rpc_host_ctx_free(&ctx); 1848 return; 1849 } 1850 1851 rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx.allow_any_host); 1852 if (rc != 0) { 1853 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1854 nvmf_rpc_host_ctx_free(&ctx); 1855 return; 1856 } 1857 1858 spdk_jsonrpc_send_bool_response(request, true); 1859 nvmf_rpc_host_ctx_free(&ctx); 1860 } 1861 SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", rpc_nvmf_subsystem_allow_any_host, 1862 SPDK_RPC_RUNTIME) 1863 1864 struct nvmf_rpc_target_ctx { 1865 char *name; 1866 uint32_t max_subsystems; 1867 char *discovery_filter; 1868 }; 1869 1870 static int 1871 decode_discovery_filter(const struct spdk_json_val *val, void *out) 1872 { 1873 enum spdk_nvmf_tgt_discovery_filter *_filter = (enum spdk_nvmf_tgt_discovery_filter *)out; 1874 enum spdk_nvmf_tgt_discovery_filter filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY; 1875 char *tokens = spdk_json_strdup(val); 1876 char *tok; 1877 int rc = -EINVAL; 1878 bool all_specified = false; 1879 1880 if (!tokens) { 1881 return -ENOMEM; 1882 } 1883 1884 tok = strtok(tokens, ","); 1885 while (tok) { 1886 if (strncmp(tok, "match_any", 9) == 0) { 1887 if (filter != SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY) { 1888 goto out; 1889 } 1890 filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY; 1891 all_specified = true; 1892 } else { 1893 if (all_specified) { 1894 goto out; 1895 } 1896 if (strncmp(tok, "transport", 9) == 0) { 1897 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE; 1898 } else if (strncmp(tok, "address", 7) == 0) { 1899 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS; 1900 } else if (strncmp(tok, "svcid", 5) == 0) { 1901 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID; 1902 } else { 1903 SPDK_ERRLOG("Invalid value %s\n", tok); 1904 goto out; 1905 } 1906 } 1907 1908 tok = strtok(NULL, ","); 1909 } 1910 1911 rc = 0; 1912 *_filter = filter; 1913 1914 out: 1915 free(tokens); 1916 1917 return rc; 1918 } 1919 1920 static const struct spdk_json_object_decoder nvmf_rpc_create_target_decoder[] = { 1921 {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 1922 {"max_subsystems", offsetof(struct nvmf_rpc_target_ctx, max_subsystems), spdk_json_decode_uint32, true}, 1923 {"discovery_filter", offsetof(struct nvmf_rpc_target_ctx, discovery_filter), decode_discovery_filter, true} 1924 }; 1925 1926 static void 1927 rpc_nvmf_create_target(struct spdk_jsonrpc_request *request, 1928 const struct spdk_json_val *params) 1929 { 1930 struct spdk_nvmf_target_opts opts; 1931 struct nvmf_rpc_target_ctx ctx = {0}; 1932 struct spdk_nvmf_tgt *tgt; 1933 struct spdk_json_write_ctx *w; 1934 1935 /* Decode parameters the first time to get the transport type */ 1936 if (spdk_json_decode_object(params, nvmf_rpc_create_target_decoder, 1937 SPDK_COUNTOF(nvmf_rpc_create_target_decoder), 1938 &ctx)) { 1939 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1940 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1941 goto out; 1942 } 1943 1944 snprintf(opts.name, NVMF_TGT_NAME_MAX_LENGTH, "%s", ctx.name); 1945 opts.max_subsystems = ctx.max_subsystems; 1946 1947 if (spdk_nvmf_get_tgt(opts.name) != NULL) { 1948 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1949 "Target already exists."); 1950 goto out; 1951 } 1952 1953 tgt = spdk_nvmf_tgt_create(&opts); 1954 1955 if (tgt == NULL) { 1956 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1957 "Unable to create the requested target."); 1958 goto out; 1959 } 1960 1961 w = spdk_jsonrpc_begin_result(request); 1962 spdk_json_write_string(w, spdk_nvmf_tgt_get_name(tgt)); 1963 spdk_jsonrpc_end_result(request, w); 1964 out: 1965 free(ctx.name); 1966 free(ctx.discovery_filter); 1967 } 1968 /* private */ SPDK_RPC_REGISTER("nvmf_create_target", rpc_nvmf_create_target, SPDK_RPC_RUNTIME); 1969 1970 static const struct spdk_json_object_decoder nvmf_rpc_destroy_target_decoder[] = { 1971 {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 1972 }; 1973 1974 static void 1975 nvmf_rpc_destroy_target_done(void *ctx, int status) 1976 { 1977 struct spdk_jsonrpc_request *request = ctx; 1978 1979 spdk_jsonrpc_send_bool_response(request, true); 1980 } 1981 1982 static void 1983 rpc_nvmf_delete_target(struct spdk_jsonrpc_request *request, 1984 const struct spdk_json_val *params) 1985 { 1986 struct nvmf_rpc_target_ctx ctx = {0}; 1987 struct spdk_nvmf_tgt *tgt; 1988 1989 /* Decode parameters the first time to get the transport type */ 1990 if (spdk_json_decode_object(params, nvmf_rpc_destroy_target_decoder, 1991 SPDK_COUNTOF(nvmf_rpc_destroy_target_decoder), 1992 &ctx)) { 1993 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1994 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1995 free(ctx.name); 1996 return; 1997 } 1998 1999 tgt = spdk_nvmf_get_tgt(ctx.name); 2000 2001 if (tgt == NULL) { 2002 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2003 "The specified target doesn't exist, cannot delete it."); 2004 free(ctx.name); 2005 return; 2006 } 2007 2008 spdk_nvmf_tgt_destroy(tgt, nvmf_rpc_destroy_target_done, request); 2009 free(ctx.name); 2010 } 2011 /* private */ SPDK_RPC_REGISTER("nvmf_delete_target", rpc_nvmf_delete_target, SPDK_RPC_RUNTIME); 2012 2013 static void 2014 rpc_nvmf_get_targets(struct spdk_jsonrpc_request *request, 2015 const struct spdk_json_val *params) 2016 { 2017 struct spdk_json_write_ctx *w; 2018 struct spdk_nvmf_tgt *tgt; 2019 const char *name; 2020 2021 if (params != NULL) { 2022 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2023 "nvmf_get_targets has no parameters."); 2024 return; 2025 } 2026 2027 w = spdk_jsonrpc_begin_result(request); 2028 spdk_json_write_array_begin(w); 2029 2030 tgt = spdk_nvmf_get_first_tgt(); 2031 2032 while (tgt != NULL) { 2033 name = spdk_nvmf_tgt_get_name(tgt); 2034 spdk_json_write_string(w, name); 2035 tgt = spdk_nvmf_get_next_tgt(tgt); 2036 } 2037 2038 spdk_json_write_array_end(w); 2039 spdk_jsonrpc_end_result(request, w); 2040 } 2041 /* private */ SPDK_RPC_REGISTER("nvmf_get_targets", rpc_nvmf_get_targets, SPDK_RPC_RUNTIME); 2042 2043 struct nvmf_rpc_create_transport_ctx { 2044 char *trtype; 2045 char *tgt_name; 2046 struct spdk_nvmf_transport_opts opts; 2047 struct spdk_jsonrpc_request *request; 2048 struct spdk_nvmf_transport *transport; 2049 int status; 2050 }; 2051 2052 /** 2053 * `max_qpairs_per_ctrlr` represents both admin and IO qpairs, that confuses 2054 * users when they configure a transport using RPC. So it was decided to 2055 * deprecate `max_qpairs_per_ctrlr` RPC parameter and use `max_io_qpairs_per_ctrlr` 2056 * But internal logic remains unchanged and SPDK expects that 2057 * spdk_nvmf_transport_opts::max_qpairs_per_ctrlr includes an admin qpair. 2058 * This function parses the number of IO qpairs and adds +1 for admin qpair. 2059 */ 2060 static int 2061 nvmf_rpc_decode_max_io_qpairs(const struct spdk_json_val *val, void *out) 2062 { 2063 uint16_t *i = out; 2064 int rc; 2065 2066 rc = spdk_json_number_to_uint16(val, i); 2067 if (rc == 0) { 2068 (*i)++; 2069 } 2070 2071 return rc; 2072 } 2073 2074 static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = { 2075 { "trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string}, 2076 { 2077 "max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth), 2078 spdk_json_decode_uint16, true 2079 }, 2080 { 2081 "max_io_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr), 2082 nvmf_rpc_decode_max_io_qpairs, true 2083 }, 2084 { 2085 "in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size), 2086 spdk_json_decode_uint32, true 2087 }, 2088 { 2089 "max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size), 2090 spdk_json_decode_uint32, true 2091 }, 2092 { 2093 "io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size), 2094 spdk_json_decode_uint32, true 2095 }, 2096 { 2097 "max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth), 2098 spdk_json_decode_uint32, true 2099 }, 2100 { 2101 "num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers), 2102 spdk_json_decode_uint32, true 2103 }, 2104 { 2105 "buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size), 2106 spdk_json_decode_uint32, true 2107 }, 2108 { 2109 "dif_insert_or_strip", offsetof(struct nvmf_rpc_create_transport_ctx, opts.dif_insert_or_strip), 2110 spdk_json_decode_bool, true 2111 }, 2112 { 2113 "abort_timeout_sec", offsetof(struct nvmf_rpc_create_transport_ctx, opts.abort_timeout_sec), 2114 spdk_json_decode_uint32, true 2115 }, 2116 { 2117 "zcopy", offsetof(struct nvmf_rpc_create_transport_ctx, opts.zcopy), 2118 spdk_json_decode_bool, true 2119 }, 2120 { 2121 "tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name), 2122 spdk_json_decode_string, true 2123 }, 2124 { 2125 "acceptor_poll_rate", offsetof(struct nvmf_rpc_create_transport_ctx, opts.acceptor_poll_rate), 2126 spdk_json_decode_uint32, true 2127 }, 2128 }; 2129 2130 static void 2131 nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx) 2132 { 2133 free(ctx->trtype); 2134 free(ctx->tgt_name); 2135 free(ctx); 2136 } 2137 2138 static void 2139 nvmf_rpc_transport_destroy_done_cb(void *cb_arg) 2140 { 2141 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2142 2143 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2144 "Failed to add transport to tgt.(%d)", ctx->status); 2145 nvmf_rpc_create_transport_ctx_free(ctx); 2146 } 2147 2148 static void 2149 nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status) 2150 { 2151 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2152 2153 if (status) { 2154 SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status); 2155 ctx->status = status; 2156 spdk_nvmf_transport_destroy(ctx->transport, nvmf_rpc_transport_destroy_done_cb, ctx); 2157 return; 2158 } 2159 2160 spdk_jsonrpc_send_bool_response(ctx->request, true); 2161 nvmf_rpc_create_transport_ctx_free(ctx); 2162 } 2163 2164 static void 2165 nvmf_rpc_create_transport_done(void *cb_arg, struct spdk_nvmf_transport *transport) 2166 { 2167 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2168 2169 if (!transport) { 2170 SPDK_ERRLOG("Failed to create transport.\n"); 2171 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2172 "Failed to create transport."); 2173 nvmf_rpc_create_transport_ctx_free(ctx); 2174 return; 2175 } 2176 2177 ctx->transport = transport; 2178 2179 spdk_nvmf_tgt_add_transport(spdk_nvmf_get_tgt(ctx->tgt_name), transport, 2180 nvmf_rpc_tgt_add_transport_done, ctx); 2181 } 2182 2183 static void 2184 rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request, 2185 const struct spdk_json_val *params) 2186 { 2187 struct nvmf_rpc_create_transport_ctx *ctx; 2188 struct spdk_nvmf_tgt *tgt; 2189 int rc; 2190 2191 ctx = calloc(1, sizeof(*ctx)); 2192 if (!ctx) { 2193 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 2194 return; 2195 } 2196 2197 /* Decode parameters the first time to get the transport type */ 2198 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder, 2199 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 2200 ctx)) { 2201 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 2202 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2203 nvmf_rpc_create_transport_ctx_free(ctx); 2204 return; 2205 } 2206 2207 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2208 if (!tgt) { 2209 SPDK_ERRLOG("Unable to find a target object.\n"); 2210 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2211 "Unable to find a target."); 2212 nvmf_rpc_create_transport_ctx_free(ctx); 2213 return; 2214 } 2215 2216 /* Initialize all the transport options (based on transport type) and decode the 2217 * parameters again to update any options passed in rpc create transport call. 2218 */ 2219 if (!spdk_nvmf_transport_opts_init(ctx->trtype, &ctx->opts, sizeof(ctx->opts))) { 2220 /* This can happen if user specifies PCIE transport type which isn't valid for 2221 * NVMe-oF. 2222 */ 2223 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype); 2224 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2225 "Invalid transport type '%s'", ctx->trtype); 2226 nvmf_rpc_create_transport_ctx_free(ctx); 2227 return; 2228 } 2229 2230 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder, 2231 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 2232 ctx)) { 2233 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 2234 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2235 nvmf_rpc_create_transport_ctx_free(ctx); 2236 return; 2237 } 2238 2239 if (spdk_nvmf_tgt_get_transport(tgt, ctx->trtype)) { 2240 SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype); 2241 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2242 "Transport type '%s' already exists", ctx->trtype); 2243 nvmf_rpc_create_transport_ctx_free(ctx); 2244 return; 2245 } 2246 2247 /* Transport can parse additional params themselves */ 2248 ctx->opts.transport_specific = params; 2249 ctx->request = request; 2250 2251 rc = spdk_nvmf_transport_create_async(ctx->trtype, &ctx->opts, nvmf_rpc_create_transport_done, ctx); 2252 if (rc) { 2253 SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype); 2254 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2255 "Transport type '%s' create failed", ctx->trtype); 2256 nvmf_rpc_create_transport_ctx_free(ctx); 2257 } 2258 } 2259 SPDK_RPC_REGISTER("nvmf_create_transport", rpc_nvmf_create_transport, SPDK_RPC_RUNTIME) 2260 2261 struct rpc_get_transport { 2262 char *trtype; 2263 char *tgt_name; 2264 }; 2265 2266 static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = { 2267 {"trtype", offsetof(struct rpc_get_transport, trtype), spdk_json_decode_string, true}, 2268 {"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true}, 2269 }; 2270 2271 static void 2272 rpc_nvmf_get_transports(struct spdk_jsonrpc_request *request, 2273 const struct spdk_json_val *params) 2274 { 2275 struct rpc_get_transport req = { 0 }; 2276 struct spdk_json_write_ctx *w; 2277 struct spdk_nvmf_transport *transport = NULL; 2278 struct spdk_nvmf_tgt *tgt; 2279 2280 if (params) { 2281 if (spdk_json_decode_object(params, rpc_get_transport_decoders, 2282 SPDK_COUNTOF(rpc_get_transport_decoders), 2283 &req)) { 2284 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2285 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2286 return; 2287 } 2288 } 2289 2290 tgt = spdk_nvmf_get_tgt(req.tgt_name); 2291 if (!tgt) { 2292 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2293 "Unable to find a target."); 2294 free(req.trtype); 2295 free(req.tgt_name); 2296 return; 2297 } 2298 2299 if (req.trtype) { 2300 transport = spdk_nvmf_tgt_get_transport(tgt, req.trtype); 2301 if (transport == NULL) { 2302 SPDK_ERRLOG("transport '%s' does not exist\n", req.trtype); 2303 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 2304 free(req.trtype); 2305 free(req.tgt_name); 2306 return; 2307 } 2308 } 2309 2310 w = spdk_jsonrpc_begin_result(request); 2311 spdk_json_write_array_begin(w); 2312 2313 if (transport) { 2314 nvmf_transport_dump_opts(transport, w, false); 2315 } else { 2316 for (transport = spdk_nvmf_transport_get_first(tgt); transport != NULL; 2317 transport = spdk_nvmf_transport_get_next(transport)) { 2318 nvmf_transport_dump_opts(transport, w, false); 2319 } 2320 } 2321 2322 spdk_json_write_array_end(w); 2323 spdk_jsonrpc_end_result(request, w); 2324 free(req.trtype); 2325 free(req.tgt_name); 2326 } 2327 SPDK_RPC_REGISTER("nvmf_get_transports", rpc_nvmf_get_transports, SPDK_RPC_RUNTIME) 2328 2329 struct rpc_nvmf_get_stats_ctx { 2330 char *tgt_name; 2331 struct spdk_nvmf_tgt *tgt; 2332 struct spdk_jsonrpc_request *request; 2333 struct spdk_json_write_ctx *w; 2334 }; 2335 2336 static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = { 2337 {"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true}, 2338 }; 2339 2340 static void 2341 free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx) 2342 { 2343 free(ctx->tgt_name); 2344 free(ctx); 2345 } 2346 2347 static void 2348 rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status) 2349 { 2350 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2351 2352 spdk_json_write_array_end(ctx->w); 2353 spdk_json_write_object_end(ctx->w); 2354 spdk_jsonrpc_end_result(ctx->request, ctx->w); 2355 free_get_stats_ctx(ctx); 2356 } 2357 2358 static void 2359 _rpc_nvmf_get_stats(struct spdk_io_channel_iter *i) 2360 { 2361 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2362 struct spdk_io_channel *ch; 2363 struct spdk_nvmf_poll_group *group; 2364 2365 ch = spdk_get_io_channel(ctx->tgt); 2366 group = spdk_io_channel_get_ctx(ch); 2367 2368 spdk_nvmf_poll_group_dump_stat(group, ctx->w); 2369 2370 spdk_put_io_channel(ch); 2371 spdk_for_each_channel_continue(i, 0); 2372 } 2373 2374 2375 static void 2376 rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request, 2377 const struct spdk_json_val *params) 2378 { 2379 struct rpc_nvmf_get_stats_ctx *ctx; 2380 2381 ctx = calloc(1, sizeof(*ctx)); 2382 if (!ctx) { 2383 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2384 "Memory allocation error"); 2385 return; 2386 } 2387 ctx->request = request; 2388 2389 if (params) { 2390 if (spdk_json_decode_object(params, rpc_get_stats_decoders, 2391 SPDK_COUNTOF(rpc_get_stats_decoders), 2392 ctx)) { 2393 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2394 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2395 free_get_stats_ctx(ctx); 2396 return; 2397 } 2398 } 2399 2400 ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2401 if (!ctx->tgt) { 2402 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2403 "Unable to find a target."); 2404 free_get_stats_ctx(ctx); 2405 return; 2406 } 2407 2408 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 2409 spdk_json_write_object_begin(ctx->w); 2410 spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz()); 2411 spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 2412 2413 spdk_for_each_channel(ctx->tgt, 2414 _rpc_nvmf_get_stats, 2415 ctx, 2416 rpc_nvmf_get_stats_done); 2417 } 2418 2419 SPDK_RPC_REGISTER("nvmf_get_stats", rpc_nvmf_get_stats, SPDK_RPC_RUNTIME) 2420 2421 static void 2422 dump_nvmf_ctrlr(struct spdk_json_write_ctx *w, struct spdk_nvmf_ctrlr *ctrlr) 2423 { 2424 uint32_t count; 2425 2426 spdk_json_write_object_begin(w); 2427 2428 spdk_json_write_named_uint32(w, "cntlid", ctrlr->cntlid); 2429 spdk_json_write_named_string(w, "hostnqn", ctrlr->hostnqn); 2430 spdk_json_write_named_uuid(w, "hostid", &ctrlr->hostid); 2431 2432 count = spdk_bit_array_count_set(ctrlr->qpair_mask); 2433 spdk_json_write_named_uint32(w, "num_io_qpairs", count); 2434 2435 spdk_json_write_object_end(w); 2436 } 2437 2438 static const char * 2439 nvmf_qpair_state_str(enum spdk_nvmf_qpair_state state) 2440 { 2441 switch (state) { 2442 case SPDK_NVMF_QPAIR_UNINITIALIZED: 2443 return "uninitialized"; 2444 case SPDK_NVMF_QPAIR_ACTIVE: 2445 return "active"; 2446 case SPDK_NVMF_QPAIR_DEACTIVATING: 2447 return "deactivating"; 2448 case SPDK_NVMF_QPAIR_ERROR: 2449 return "error"; 2450 default: 2451 return NULL; 2452 } 2453 } 2454 2455 static void 2456 dump_nvmf_qpair(struct spdk_json_write_ctx *w, struct spdk_nvmf_qpair *qpair) 2457 { 2458 struct spdk_nvme_transport_id listen_trid = {}; 2459 2460 spdk_json_write_object_begin(w); 2461 2462 spdk_json_write_named_uint32(w, "cntlid", qpair->ctrlr->cntlid); 2463 spdk_json_write_named_uint32(w, "qid", qpair->qid); 2464 spdk_json_write_named_string(w, "state", nvmf_qpair_state_str(qpair->state)); 2465 2466 if (spdk_nvmf_qpair_get_listen_trid(qpair, &listen_trid) == 0) { 2467 spdk_json_write_named_object_begin(w, "listen_address"); 2468 nvmf_transport_listen_dump_trid(&listen_trid, w); 2469 spdk_json_write_object_end(w); 2470 if (qpair->transport->ops->listen_dump_opts) { 2471 qpair->transport->ops->listen_dump_opts(qpair->transport, &listen_trid, w); 2472 } 2473 } 2474 2475 spdk_json_write_object_end(w); 2476 } 2477 2478 static const char * 2479 nvme_ana_state_str(enum spdk_nvme_ana_state ana_state) 2480 { 2481 switch (ana_state) { 2482 case SPDK_NVME_ANA_OPTIMIZED_STATE: 2483 return "optimized"; 2484 case SPDK_NVME_ANA_NON_OPTIMIZED_STATE: 2485 return "non_optimized"; 2486 case SPDK_NVME_ANA_INACCESSIBLE_STATE: 2487 return "inaccessible"; 2488 case SPDK_NVME_ANA_PERSISTENT_LOSS_STATE: 2489 return "persistent_loss"; 2490 case SPDK_NVME_ANA_CHANGE_STATE: 2491 return "change"; 2492 default: 2493 return NULL; 2494 } 2495 } 2496 2497 static void 2498 dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w, 2499 struct spdk_nvmf_subsystem_listener *listener) 2500 { 2501 const struct spdk_nvme_transport_id *trid = listener->trid; 2502 uint32_t i; 2503 2504 spdk_json_write_object_begin(w); 2505 2506 spdk_json_write_named_object_begin(w, "address"); 2507 nvmf_transport_listen_dump_trid(trid, w); 2508 spdk_json_write_object_end(w); 2509 2510 if (nvmf_subsystem_get_ana_reporting(listener->subsystem)) { 2511 spdk_json_write_named_array_begin(w, "ana_states"); 2512 for (i = 0; i < listener->subsystem->max_nsid; i++) { 2513 spdk_json_write_object_begin(w); 2514 spdk_json_write_named_uint32(w, "ana_group", i + 1); 2515 spdk_json_write_named_string(w, "ana_state", 2516 nvme_ana_state_str(listener->ana_state[i])); 2517 spdk_json_write_object_end(w); 2518 } 2519 spdk_json_write_array_end(w); 2520 } 2521 2522 spdk_json_write_object_end(w); 2523 } 2524 2525 struct rpc_subsystem_query_ctx { 2526 char *nqn; 2527 char *tgt_name; 2528 struct spdk_nvmf_subsystem *subsystem; 2529 struct spdk_jsonrpc_request *request; 2530 struct spdk_json_write_ctx *w; 2531 }; 2532 2533 static const struct spdk_json_object_decoder rpc_subsystem_query_decoders[] = { 2534 {"nqn", offsetof(struct rpc_subsystem_query_ctx, nqn), spdk_json_decode_string}, 2535 {"tgt_name", offsetof(struct rpc_subsystem_query_ctx, tgt_name), spdk_json_decode_string, true}, 2536 }; 2537 2538 static void 2539 free_rpc_subsystem_query_ctx(struct rpc_subsystem_query_ctx *ctx) 2540 { 2541 free(ctx->nqn); 2542 free(ctx->tgt_name); 2543 free(ctx); 2544 } 2545 2546 static void 2547 rpc_nvmf_get_controllers_paused(struct spdk_nvmf_subsystem *subsystem, 2548 void *cb_arg, int status) 2549 { 2550 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2551 struct spdk_json_write_ctx *w; 2552 struct spdk_nvmf_ctrlr *ctrlr; 2553 2554 w = spdk_jsonrpc_begin_result(ctx->request); 2555 2556 spdk_json_write_array_begin(w); 2557 TAILQ_FOREACH(ctrlr, &ctx->subsystem->ctrlrs, link) { 2558 dump_nvmf_ctrlr(w, ctrlr); 2559 } 2560 spdk_json_write_array_end(w); 2561 2562 spdk_jsonrpc_end_result(ctx->request, w); 2563 2564 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2565 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2566 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2567 } 2568 2569 free_rpc_subsystem_query_ctx(ctx); 2570 } 2571 2572 static void 2573 rpc_nvmf_get_qpairs_done(struct spdk_io_channel_iter *i, int status) 2574 { 2575 struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2576 2577 spdk_json_write_array_end(ctx->w); 2578 spdk_jsonrpc_end_result(ctx->request, ctx->w); 2579 2580 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2581 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2582 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2583 } 2584 2585 free_rpc_subsystem_query_ctx(ctx); 2586 } 2587 2588 static void 2589 rpc_nvmf_get_qpairs(struct spdk_io_channel_iter *i) 2590 { 2591 struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2592 struct spdk_io_channel *ch; 2593 struct spdk_nvmf_poll_group *group; 2594 struct spdk_nvmf_qpair *qpair; 2595 2596 ch = spdk_io_channel_iter_get_channel(i); 2597 group = spdk_io_channel_get_ctx(ch); 2598 2599 TAILQ_FOREACH(qpair, &group->qpairs, link) { 2600 if (qpair->ctrlr->subsys == ctx->subsystem) { 2601 dump_nvmf_qpair(ctx->w, qpair); 2602 } 2603 } 2604 2605 spdk_for_each_channel_continue(i, 0); 2606 } 2607 2608 static void 2609 rpc_nvmf_get_qpairs_paused(struct spdk_nvmf_subsystem *subsystem, 2610 void *cb_arg, int status) 2611 { 2612 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2613 2614 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 2615 2616 spdk_json_write_array_begin(ctx->w); 2617 2618 spdk_for_each_channel(ctx->subsystem->tgt, 2619 rpc_nvmf_get_qpairs, 2620 ctx, 2621 rpc_nvmf_get_qpairs_done); 2622 } 2623 2624 static void 2625 rpc_nvmf_get_listeners_paused(struct spdk_nvmf_subsystem *subsystem, 2626 void *cb_arg, int status) 2627 { 2628 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2629 struct spdk_json_write_ctx *w; 2630 struct spdk_nvmf_subsystem_listener *listener; 2631 2632 w = spdk_jsonrpc_begin_result(ctx->request); 2633 2634 spdk_json_write_array_begin(w); 2635 2636 for (listener = spdk_nvmf_subsystem_get_first_listener(ctx->subsystem); 2637 listener != NULL; 2638 listener = spdk_nvmf_subsystem_get_next_listener(ctx->subsystem, listener)) { 2639 dump_nvmf_subsystem_listener(w, listener); 2640 } 2641 spdk_json_write_array_end(w); 2642 2643 spdk_jsonrpc_end_result(ctx->request, w); 2644 2645 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2646 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2647 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2648 } 2649 2650 free_rpc_subsystem_query_ctx(ctx); 2651 } 2652 2653 static void 2654 _rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request, 2655 const struct spdk_json_val *params, 2656 spdk_nvmf_subsystem_state_change_done cb_fn) 2657 { 2658 struct rpc_subsystem_query_ctx *ctx; 2659 struct spdk_nvmf_subsystem *subsystem; 2660 struct spdk_nvmf_tgt *tgt; 2661 2662 ctx = calloc(1, sizeof(*ctx)); 2663 if (!ctx) { 2664 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2665 "Out of memory"); 2666 return; 2667 } 2668 2669 ctx->request = request; 2670 2671 if (spdk_json_decode_object(params, rpc_subsystem_query_decoders, 2672 SPDK_COUNTOF(rpc_subsystem_query_decoders), 2673 ctx)) { 2674 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2675 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2676 "Invalid parameters"); 2677 free_rpc_subsystem_query_ctx(ctx); 2678 return; 2679 } 2680 2681 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2682 if (!tgt) { 2683 SPDK_ERRLOG("Unable to find a target object.\n"); 2684 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2685 "Unable to find a target"); 2686 free_rpc_subsystem_query_ctx(ctx); 2687 return; 2688 } 2689 2690 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 2691 if (!subsystem) { 2692 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 2693 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2694 "Invalid parameters"); 2695 free_rpc_subsystem_query_ctx(ctx); 2696 return; 2697 } 2698 2699 ctx->subsystem = subsystem; 2700 2701 if (spdk_nvmf_subsystem_pause(subsystem, 0, cb_fn, ctx)) { 2702 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2703 "Internal error"); 2704 free_rpc_subsystem_query_ctx(ctx); 2705 return; 2706 } 2707 } 2708 2709 static void 2710 rpc_nvmf_subsystem_get_controllers(struct spdk_jsonrpc_request *request, 2711 const struct spdk_json_val *params) 2712 { 2713 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_controllers_paused); 2714 } 2715 SPDK_RPC_REGISTER("nvmf_subsystem_get_controllers", rpc_nvmf_subsystem_get_controllers, 2716 SPDK_RPC_RUNTIME); 2717 2718 static void 2719 rpc_nvmf_subsystem_get_qpairs(struct spdk_jsonrpc_request *request, 2720 const struct spdk_json_val *params) 2721 { 2722 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused); 2723 } 2724 SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME); 2725 2726 static void 2727 rpc_nvmf_subsystem_get_listeners(struct spdk_jsonrpc_request *request, 2728 const struct spdk_json_val *params) 2729 { 2730 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_listeners_paused); 2731 } 2732 SPDK_RPC_REGISTER("nvmf_subsystem_get_listeners", rpc_nvmf_subsystem_get_listeners, 2733 SPDK_RPC_RUNTIME); 2734