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