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