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