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