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