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 if (ctx->op == NVMF_RPC_LISTEN_ADD) { 764 if (!nvmf_subsystem_find_listener(subsystem, &ctx->trid)) { 765 rc = spdk_nvmf_tgt_listen_ext(ctx->tgt, &ctx->trid, &ctx->opts); 766 if (rc == 0) { 767 spdk_nvmf_subsystem_add_listener_ext(ctx->subsystem, &ctx->trid, nvmf_rpc_subsystem_listen, ctx, 768 &ctx->listener_opts); 769 return; 770 } 771 772 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 773 "Invalid parameters"); 774 ctx->response_sent = true; 775 } 776 } else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) { 777 rc = spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid); 778 if (rc == 0) { 779 spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, subsystem, 780 nvmf_rpc_stop_listen_async_done, ctx); 781 return; 782 } 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 } else if (ctx->op == NVMF_RPC_LISTEN_SET_ANA_STATE) { 788 spdk_nvmf_subsystem_set_ana_state(subsystem, &ctx->trid, ctx->ana_state, ctx->anagrpid, 789 nvmf_rpc_set_ana_state_done, ctx); 790 return; 791 } else { 792 SPDK_UNREACHABLE(); 793 } 794 795 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) { 796 if (!ctx->response_sent) { 797 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 798 "Internal error"); 799 } 800 nvmf_rpc_listener_ctx_free(ctx); 801 /* Can't really do anything to recover here - subsystem will remain paused. */ 802 } 803 } 804 805 static int 806 rpc_listen_address_to_trid(const struct rpc_listen_address *address, 807 struct spdk_nvme_transport_id *trid) 808 { 809 size_t len; 810 811 memset(trid, 0, sizeof(*trid)); 812 813 if (spdk_nvme_transport_id_populate_trstring(trid, address->transport)) { 814 SPDK_ERRLOG("Invalid transport string: %s\n", address->transport); 815 return -EINVAL; 816 } 817 818 if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) { 819 SPDK_ERRLOG("Invalid transport type: %s\n", address->transport); 820 return -EINVAL; 821 } 822 823 if (address->adrfam) { 824 if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) { 825 SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam); 826 return -EINVAL; 827 } 828 } else { 829 trid->adrfam = SPDK_NVMF_ADRFAM_IPV4; 830 } 831 832 len = strlen(address->traddr); 833 if (len > sizeof(trid->traddr) - 1) { 834 SPDK_ERRLOG("Transport address longer than %zu characters: %s\n", 835 sizeof(trid->traddr) - 1, address->traddr); 836 return -EINVAL; 837 } 838 memcpy(trid->traddr, address->traddr, len + 1); 839 840 trid->trsvcid[0] = '\0'; 841 if (address->trsvcid) { 842 len = strlen(address->trsvcid); 843 if (len > sizeof(trid->trsvcid) - 1) { 844 SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n", 845 sizeof(trid->trsvcid) - 1, address->trsvcid); 846 return -EINVAL; 847 } 848 memcpy(trid->trsvcid, address->trsvcid, len + 1); 849 } 850 851 return 0; 852 } 853 854 static void 855 rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request, 856 const struct spdk_json_val *params) 857 { 858 struct nvmf_rpc_listener_ctx *ctx; 859 struct spdk_nvmf_subsystem *subsystem; 860 struct spdk_nvmf_tgt *tgt; 861 int rc; 862 863 ctx = calloc(1, sizeof(*ctx)); 864 if (!ctx) { 865 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 866 return; 867 } 868 869 ctx->request = request; 870 871 spdk_nvmf_subsystem_listener_opts_init(&ctx->listener_opts, sizeof(ctx->listener_opts)); 872 873 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_listener_decoder, 874 SPDK_COUNTOF(nvmf_rpc_listener_decoder), 875 ctx)) { 876 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 877 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 878 nvmf_rpc_listener_ctx_free(ctx); 879 return; 880 } 881 882 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 883 if (!tgt) { 884 SPDK_ERRLOG("Unable to find a target object.\n"); 885 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 886 "Unable to find a target."); 887 nvmf_rpc_listener_ctx_free(ctx); 888 return; 889 } 890 ctx->tgt = tgt; 891 892 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 893 if (!subsystem) { 894 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 895 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 896 nvmf_rpc_listener_ctx_free(ctx); 897 return; 898 } 899 900 ctx->subsystem = subsystem; 901 902 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 903 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 904 "Invalid parameters"); 905 nvmf_rpc_listener_ctx_free(ctx); 906 return; 907 } 908 909 ctx->op = NVMF_RPC_LISTEN_ADD; 910 spdk_nvmf_listen_opts_init(&ctx->opts, sizeof(ctx->opts)); 911 ctx->opts.transport_specific = params; 912 if (subsystem->flags.allow_any_host == 1 && ctx->listener_opts.secure_channel == true) { 913 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 914 "Cannot establish secure channel, when 'allow_any_host' is set"); 915 nvmf_rpc_listener_ctx_free(ctx); 916 return; 917 } 918 ctx->opts.secure_channel = ctx->listener_opts.secure_channel; 919 920 if (ctx->ana_state_str) { 921 if (rpc_ana_state_parse(ctx->ana_state_str, &ctx->ana_state)) { 922 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 923 "Invalid parameters"); 924 nvmf_rpc_listener_ctx_free(ctx); 925 return; 926 } 927 ctx->listener_opts.ana_state = ctx->ana_state; 928 } 929 930 rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx); 931 if (rc != 0) { 932 if (rc == -EBUSY) { 933 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 934 "subsystem busy, retry later.\n"); 935 } else { 936 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 937 } 938 nvmf_rpc_listener_ctx_free(ctx); 939 } 940 } 941 SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", rpc_nvmf_subsystem_add_listener, 942 SPDK_RPC_RUNTIME); 943 944 static void 945 rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request, 946 const struct spdk_json_val *params) 947 { 948 struct nvmf_rpc_listener_ctx *ctx; 949 struct spdk_nvmf_subsystem *subsystem; 950 struct spdk_nvmf_tgt *tgt; 951 int rc; 952 953 ctx = calloc(1, sizeof(*ctx)); 954 if (!ctx) { 955 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 956 return; 957 } 958 959 ctx->request = request; 960 961 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder, 962 SPDK_COUNTOF(nvmf_rpc_listener_decoder), 963 ctx)) { 964 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 965 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 966 nvmf_rpc_listener_ctx_free(ctx); 967 return; 968 } 969 970 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 971 if (!tgt) { 972 SPDK_ERRLOG("Unable to find a target object.\n"); 973 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 974 "Unable to find a target."); 975 nvmf_rpc_listener_ctx_free(ctx); 976 return; 977 } 978 ctx->tgt = tgt; 979 980 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 981 if (!subsystem) { 982 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 983 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 984 nvmf_rpc_listener_ctx_free(ctx); 985 return; 986 } 987 988 ctx->subsystem = subsystem; 989 990 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 991 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 992 "Invalid parameters"); 993 nvmf_rpc_listener_ctx_free(ctx); 994 return; 995 } 996 997 ctx->transport = spdk_nvmf_tgt_get_transport(tgt, ctx->trid.trstring); 998 if (!ctx->transport) { 999 SPDK_ERRLOG("Unable to find %s transport. The transport must be created first also make sure it is properly registered.\n", 1000 ctx->trid.trstring); 1001 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1002 "Invalid parameters"); 1003 nvmf_rpc_listener_ctx_free(ctx); 1004 return; 1005 } 1006 1007 ctx->op = NVMF_RPC_LISTEN_REMOVE; 1008 1009 rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx); 1010 if (rc != 0) { 1011 if (rc == -EBUSY) { 1012 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1013 "subsystem busy, retry later.\n"); 1014 } else { 1015 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1016 } 1017 nvmf_rpc_listener_ctx_free(ctx); 1018 } 1019 } 1020 SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", rpc_nvmf_subsystem_remove_listener, 1021 SPDK_RPC_RUNTIME); 1022 1023 struct nvmf_rpc_referral_ctx { 1024 char *tgt_name; 1025 struct rpc_listen_address address; 1026 bool secure_channel; 1027 char *subnqn; 1028 }; 1029 1030 static const struct spdk_json_object_decoder nvmf_rpc_referral_decoder[] = { 1031 {"address", offsetof(struct nvmf_rpc_referral_ctx, address), decode_rpc_listen_address}, 1032 {"tgt_name", offsetof(struct nvmf_rpc_referral_ctx, tgt_name), spdk_json_decode_string, true}, 1033 {"secure_channel", offsetof(struct nvmf_rpc_referral_ctx, secure_channel), spdk_json_decode_bool, true}, 1034 {"subnqn", offsetof(struct nvmf_rpc_referral_ctx, subnqn), spdk_json_decode_string, true}, 1035 }; 1036 1037 static void 1038 nvmf_rpc_referral_ctx_free(struct nvmf_rpc_referral_ctx *ctx) 1039 { 1040 free(ctx->tgt_name); 1041 free(ctx->subnqn); 1042 free_rpc_listen_address(&ctx->address); 1043 } 1044 1045 static void 1046 rpc_nvmf_add_referral(struct spdk_jsonrpc_request *request, 1047 const struct spdk_json_val *params) 1048 { 1049 struct nvmf_rpc_referral_ctx ctx = {}; 1050 struct spdk_nvme_transport_id trid = {}; 1051 struct spdk_nvmf_tgt *tgt; 1052 struct spdk_nvmf_referral_opts opts = {}; 1053 int rc; 1054 1055 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_referral_decoder, 1056 SPDK_COUNTOF(nvmf_rpc_referral_decoder), 1057 &ctx)) { 1058 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 1059 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1060 nvmf_rpc_referral_ctx_free(&ctx); 1061 return; 1062 } 1063 1064 tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1065 if (!tgt) { 1066 SPDK_ERRLOG("Unable to find a target object.\n"); 1067 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1068 "Unable to find a target."); 1069 nvmf_rpc_referral_ctx_free(&ctx); 1070 return; 1071 } 1072 1073 if (rpc_listen_address_to_trid(&ctx.address, &trid)) { 1074 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1075 "Invalid parameters"); 1076 nvmf_rpc_referral_ctx_free(&ctx); 1077 return; 1078 } 1079 1080 if (ctx.subnqn != NULL) { 1081 rc = snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx.subnqn); 1082 if (rc < 0 || (size_t)rc >= sizeof(trid.subnqn)) { 1083 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1084 "Invalid subsystem NQN"); 1085 nvmf_rpc_referral_ctx_free(&ctx); 1086 return; 1087 } 1088 } 1089 1090 if ((trid.trtype == SPDK_NVME_TRANSPORT_TCP || 1091 trid.trtype == SPDK_NVME_TRANSPORT_RDMA) && 1092 !strlen(trid.trsvcid)) { 1093 SPDK_ERRLOG("Service ID is required.\n"); 1094 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1095 "Service ID is required."); 1096 nvmf_rpc_referral_ctx_free(&ctx); 1097 return; 1098 } 1099 1100 opts.size = SPDK_SIZEOF(&opts, secure_channel); 1101 opts.trid = trid; 1102 opts.secure_channel = ctx.secure_channel; 1103 1104 rc = spdk_nvmf_tgt_add_referral(tgt, &opts); 1105 if (rc != 0) { 1106 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1107 "Internal error"); 1108 nvmf_rpc_referral_ctx_free(&ctx); 1109 return; 1110 } 1111 1112 nvmf_rpc_referral_ctx_free(&ctx); 1113 1114 spdk_jsonrpc_send_bool_response(request, true); 1115 } 1116 1117 SPDK_RPC_REGISTER("nvmf_discovery_add_referral", rpc_nvmf_add_referral, 1118 SPDK_RPC_RUNTIME); 1119 1120 static void 1121 rpc_nvmf_remove_referral(struct spdk_jsonrpc_request *request, 1122 const struct spdk_json_val *params) 1123 { 1124 struct nvmf_rpc_referral_ctx ctx = {}; 1125 struct spdk_nvme_transport_id trid = {}; 1126 struct spdk_nvmf_referral_opts opts = {}; 1127 struct spdk_nvmf_tgt *tgt; 1128 int rc; 1129 1130 if (spdk_json_decode_object(params, nvmf_rpc_referral_decoder, 1131 SPDK_COUNTOF(nvmf_rpc_referral_decoder), 1132 &ctx)) { 1133 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1134 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1135 nvmf_rpc_referral_ctx_free(&ctx); 1136 return; 1137 } 1138 1139 tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1140 if (!tgt) { 1141 SPDK_ERRLOG("Unable to find a target object.\n"); 1142 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1143 "Unable to find a target."); 1144 nvmf_rpc_referral_ctx_free(&ctx); 1145 return; 1146 } 1147 1148 if (rpc_listen_address_to_trid(&ctx.address, &trid)) { 1149 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1150 "Invalid parameters"); 1151 nvmf_rpc_referral_ctx_free(&ctx); 1152 return; 1153 } 1154 1155 if (ctx.subnqn != NULL) { 1156 rc = snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx.subnqn); 1157 if (rc < 0 || (size_t)rc >= sizeof(trid.subnqn)) { 1158 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1159 "Invalid subsystem NQN"); 1160 nvmf_rpc_referral_ctx_free(&ctx); 1161 return; 1162 } 1163 } 1164 1165 opts.size = SPDK_SIZEOF(&opts, secure_channel); 1166 opts.trid = trid; 1167 1168 if (spdk_nvmf_tgt_remove_referral(tgt, &opts)) { 1169 SPDK_ERRLOG("Failed to remove referral.\n"); 1170 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1171 "Unable to remove a referral."); 1172 nvmf_rpc_referral_ctx_free(&ctx); 1173 return; 1174 } 1175 1176 nvmf_rpc_referral_ctx_free(&ctx); 1177 1178 spdk_jsonrpc_send_bool_response(request, true); 1179 } 1180 1181 SPDK_RPC_REGISTER("nvmf_discovery_remove_referral", rpc_nvmf_remove_referral, 1182 SPDK_RPC_RUNTIME); 1183 1184 static void 1185 dump_nvmf_referral(struct spdk_json_write_ctx *w, 1186 struct spdk_nvmf_referral *referral) 1187 { 1188 spdk_json_write_object_begin(w); 1189 1190 spdk_json_write_named_object_begin(w, "address"); 1191 nvmf_transport_listen_dump_trid(&referral->trid, w); 1192 spdk_json_write_object_end(w); 1193 spdk_json_write_named_bool(w, "secure_channel", 1194 referral->entry.treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED); 1195 spdk_json_write_named_string(w, "subnqn", referral->trid.subnqn); 1196 1197 spdk_json_write_object_end(w); 1198 } 1199 1200 struct rpc_get_referrals_ctx { 1201 char *tgt_name; 1202 }; 1203 1204 static const struct spdk_json_object_decoder rpc_get_referrals_decoders[] = { 1205 {"tgt_name", offsetof(struct rpc_get_referrals_ctx, tgt_name), spdk_json_decode_string, true}, 1206 }; 1207 1208 static void 1209 free_rpc_get_referrals_ctx(struct rpc_get_referrals_ctx *ctx) 1210 { 1211 free(ctx->tgt_name); 1212 free(ctx); 1213 } 1214 1215 static void 1216 rpc_nvmf_get_referrals(struct spdk_jsonrpc_request *request, 1217 const struct spdk_json_val *params) 1218 { 1219 struct rpc_get_referrals_ctx *ctx; 1220 struct spdk_nvmf_tgt *tgt; 1221 struct spdk_json_write_ctx *w; 1222 struct spdk_nvmf_referral *referral; 1223 1224 ctx = calloc(1, sizeof(*ctx)); 1225 if (!ctx) { 1226 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1227 "Out of memory"); 1228 return; 1229 } 1230 1231 if (params) { 1232 if (spdk_json_decode_object(params, rpc_get_referrals_decoders, 1233 SPDK_COUNTOF(rpc_get_referrals_decoders), 1234 ctx)) { 1235 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1236 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1237 "Invalid parameters"); 1238 free_rpc_get_referrals_ctx(ctx); 1239 return; 1240 } 1241 } 1242 1243 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1244 if (!tgt) { 1245 SPDK_ERRLOG("Unable to find a target object.\n"); 1246 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1247 "Unable to find a target"); 1248 free_rpc_get_referrals_ctx(ctx); 1249 return; 1250 } 1251 1252 w = spdk_jsonrpc_begin_result(request); 1253 1254 spdk_json_write_array_begin(w); 1255 1256 TAILQ_FOREACH(referral, &tgt->referrals, link) { 1257 dump_nvmf_referral(w, referral); 1258 } 1259 1260 spdk_json_write_array_end(w); 1261 1262 spdk_jsonrpc_end_result(request, w); 1263 1264 free_rpc_get_referrals_ctx(ctx); 1265 } 1266 SPDK_RPC_REGISTER("nvmf_discovery_get_referrals", rpc_nvmf_get_referrals, 1267 SPDK_RPC_RUNTIME); 1268 1269 static const struct spdk_json_object_decoder nvmf_rpc_set_ana_state_decoder[] = { 1270 {"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string}, 1271 {"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address}, 1272 {"ana_state", offsetof(struct nvmf_rpc_listener_ctx, ana_state_str), spdk_json_decode_string}, 1273 {"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true}, 1274 {"anagrpid", offsetof(struct nvmf_rpc_listener_ctx, anagrpid), spdk_json_decode_uint32, true}, 1275 }; 1276 1277 static int 1278 rpc_ana_state_parse(const char *str, enum spdk_nvme_ana_state *ana_state) 1279 { 1280 if (ana_state == NULL || str == NULL) { 1281 return -EINVAL; 1282 } 1283 1284 if (strcasecmp(str, "optimized") == 0) { 1285 *ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; 1286 } else if (strcasecmp(str, "non_optimized") == 0) { 1287 *ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE; 1288 } else if (strcasecmp(str, "inaccessible") == 0) { 1289 *ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE; 1290 } else { 1291 return -ENOENT; 1292 } 1293 1294 return 0; 1295 } 1296 1297 static void 1298 rpc_nvmf_subsystem_listener_set_ana_state(struct spdk_jsonrpc_request *request, 1299 const struct spdk_json_val *params) 1300 { 1301 struct nvmf_rpc_listener_ctx *ctx; 1302 struct spdk_nvmf_subsystem *subsystem; 1303 struct spdk_nvmf_tgt *tgt; 1304 1305 ctx = calloc(1, sizeof(*ctx)); 1306 if (!ctx) { 1307 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1308 "Out of memory"); 1309 return; 1310 } 1311 1312 ctx->request = request; 1313 1314 if (spdk_json_decode_object(params, nvmf_rpc_set_ana_state_decoder, 1315 SPDK_COUNTOF(nvmf_rpc_set_ana_state_decoder), 1316 ctx)) { 1317 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1318 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1319 "Invalid parameters"); 1320 nvmf_rpc_listener_ctx_free(ctx); 1321 return; 1322 } 1323 1324 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1325 if (!tgt) { 1326 SPDK_ERRLOG("Unable to find a target object.\n"); 1327 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1328 "Unable to find a target.\n"); 1329 nvmf_rpc_listener_ctx_free(ctx); 1330 return; 1331 } 1332 1333 ctx->tgt = tgt; 1334 1335 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1336 if (!subsystem) { 1337 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1338 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1339 "Unable to find subsystem with NQN %s", 1340 ctx->nqn); 1341 nvmf_rpc_listener_ctx_free(ctx); 1342 return; 1343 } 1344 1345 ctx->subsystem = subsystem; 1346 1347 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 1348 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1349 "Invalid parameters"); 1350 nvmf_rpc_listener_ctx_free(ctx); 1351 return; 1352 } 1353 1354 if (rpc_ana_state_parse(ctx->ana_state_str, &ctx->ana_state)) { 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 ctx->op = NVMF_RPC_LISTEN_SET_ANA_STATE; 1362 1363 if (spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx)) { 1364 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1365 "Internal error"); 1366 nvmf_rpc_listener_ctx_free(ctx); 1367 } 1368 } 1369 SPDK_RPC_REGISTER("nvmf_subsystem_listener_set_ana_state", 1370 rpc_nvmf_subsystem_listener_set_ana_state, SPDK_RPC_RUNTIME); 1371 1372 struct nvmf_rpc_ns_params { 1373 char *bdev_name; 1374 char *ptpl_file; 1375 uint32_t nsid; 1376 char nguid[16]; 1377 char eui64[8]; 1378 struct spdk_uuid uuid; 1379 uint32_t anagrpid; 1380 }; 1381 1382 static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = { 1383 {"nsid", offsetof(struct nvmf_rpc_ns_params, nsid), spdk_json_decode_uint32, true}, 1384 {"bdev_name", offsetof(struct nvmf_rpc_ns_params, bdev_name), spdk_json_decode_string}, 1385 {"ptpl_file", offsetof(struct nvmf_rpc_ns_params, ptpl_file), spdk_json_decode_string, true}, 1386 {"nguid", offsetof(struct nvmf_rpc_ns_params, nguid), decode_ns_nguid, true}, 1387 {"eui64", offsetof(struct nvmf_rpc_ns_params, eui64), decode_ns_eui64, true}, 1388 {"uuid", offsetof(struct nvmf_rpc_ns_params, uuid), spdk_json_decode_uuid, true}, 1389 {"anagrpid", offsetof(struct nvmf_rpc_ns_params, anagrpid), spdk_json_decode_uint32, true}, 1390 }; 1391 1392 static int 1393 decode_rpc_ns_params(const struct spdk_json_val *val, void *out) 1394 { 1395 struct nvmf_rpc_ns_params *ns_params = out; 1396 1397 return spdk_json_decode_object(val, rpc_ns_params_decoders, 1398 SPDK_COUNTOF(rpc_ns_params_decoders), 1399 ns_params); 1400 } 1401 1402 struct nvmf_rpc_ns_ctx { 1403 char *nqn; 1404 char *tgt_name; 1405 struct nvmf_rpc_ns_params ns_params; 1406 1407 struct spdk_jsonrpc_request *request; 1408 const struct spdk_json_val *params; 1409 bool response_sent; 1410 }; 1411 1412 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = { 1413 {"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string}, 1414 {"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params}, 1415 {"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1416 }; 1417 1418 static void 1419 nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx) 1420 { 1421 free(ctx->nqn); 1422 free(ctx->tgt_name); 1423 free(ctx->ns_params.bdev_name); 1424 free(ctx->ns_params.ptpl_file); 1425 free(ctx); 1426 } 1427 1428 static void 1429 nvmf_rpc_ns_failback_resumed(struct spdk_nvmf_subsystem *subsystem, 1430 void *cb_arg, int status) 1431 { 1432 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1433 struct spdk_jsonrpc_request *request = ctx->request; 1434 1435 if (status) { 1436 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1437 "Unable to add ns, subsystem in invalid state"); 1438 } else { 1439 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1440 "Unable to add ns, subsystem in active state"); 1441 } 1442 1443 nvmf_rpc_ns_ctx_free(ctx); 1444 } 1445 1446 static void 1447 nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1448 void *cb_arg, int status) 1449 { 1450 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1451 struct spdk_jsonrpc_request *request = ctx->request; 1452 uint32_t nsid = ctx->ns_params.nsid; 1453 bool response_sent = ctx->response_sent; 1454 struct spdk_json_write_ctx *w; 1455 int rc; 1456 1457 /* The case where the call to add the namespace was successful, but the subsystem couldn't be resumed. */ 1458 if (status && !ctx->response_sent) { 1459 rc = spdk_nvmf_subsystem_remove_ns(subsystem, nsid); 1460 if (rc != 0) { 1461 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1462 "Unable to add ns, subsystem in invalid state"); 1463 nvmf_rpc_ns_ctx_free(ctx); 1464 return; 1465 } 1466 1467 rc = spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_failback_resumed, ctx); 1468 if (rc != 0) { 1469 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1470 nvmf_rpc_ns_ctx_free(ctx); 1471 return; 1472 } 1473 1474 return; 1475 } 1476 1477 nvmf_rpc_ns_ctx_free(ctx); 1478 1479 if (response_sent) { 1480 return; 1481 } 1482 1483 w = spdk_jsonrpc_begin_result(request); 1484 spdk_json_write_uint32(w, nsid); 1485 spdk_jsonrpc_end_result(request, w); 1486 } 1487 1488 static void 1489 nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1490 void *cb_arg, int status) 1491 { 1492 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1493 struct spdk_nvmf_ns_opts ns_opts; 1494 1495 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 1496 ns_opts.nsid = ctx->ns_params.nsid; 1497 ns_opts.transport_specific = ctx->params; 1498 1499 SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch"); 1500 memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid)); 1501 1502 SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch"); 1503 memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64)); 1504 1505 if (!spdk_uuid_is_null(&ctx->ns_params.uuid)) { 1506 ns_opts.uuid = ctx->ns_params.uuid; 1507 } 1508 1509 ns_opts.anagrpid = ctx->ns_params.anagrpid; 1510 1511 ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns_ext(subsystem, ctx->ns_params.bdev_name, 1512 &ns_opts, sizeof(ns_opts), 1513 ctx->ns_params.ptpl_file); 1514 if (ctx->ns_params.nsid == 0) { 1515 SPDK_ERRLOG("Unable to add namespace\n"); 1516 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1517 "Invalid parameters"); 1518 ctx->response_sent = true; 1519 goto resume; 1520 } 1521 1522 resume: 1523 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) { 1524 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1525 nvmf_rpc_ns_ctx_free(ctx); 1526 } 1527 } 1528 1529 static void 1530 rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request, 1531 const struct spdk_json_val *params) 1532 { 1533 struct nvmf_rpc_ns_ctx *ctx; 1534 struct spdk_nvmf_subsystem *subsystem; 1535 struct spdk_nvmf_tgt *tgt; 1536 int rc; 1537 1538 ctx = calloc(1, sizeof(*ctx)); 1539 if (!ctx) { 1540 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1541 return; 1542 } 1543 1544 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_subsystem_ns_decoder, 1545 SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder), ctx)) { 1546 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1547 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1548 nvmf_rpc_ns_ctx_free(ctx); 1549 return; 1550 } 1551 1552 ctx->request = request; 1553 ctx->params = params; 1554 ctx->response_sent = false; 1555 1556 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1557 if (!tgt) { 1558 SPDK_ERRLOG("Unable to find a target object.\n"); 1559 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1560 "Unable to find a target."); 1561 nvmf_rpc_ns_ctx_free(ctx); 1562 return; 1563 } 1564 1565 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1566 if (!subsystem) { 1567 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1568 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1569 nvmf_rpc_ns_ctx_free(ctx); 1570 return; 1571 } 1572 1573 rc = spdk_nvmf_subsystem_pause(subsystem, ctx->ns_params.nsid, nvmf_rpc_ns_paused, ctx); 1574 if (rc != 0) { 1575 if (rc == -EBUSY) { 1576 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1577 "subsystem busy, retry later.\n"); 1578 } else { 1579 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1580 } 1581 nvmf_rpc_ns_ctx_free(ctx); 1582 } 1583 } 1584 SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME) 1585 1586 struct nvmf_rpc_remove_ns_ctx { 1587 char *nqn; 1588 char *tgt_name; 1589 uint32_t nsid; 1590 1591 struct spdk_jsonrpc_request *request; 1592 bool response_sent; 1593 }; 1594 1595 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = { 1596 {"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string}, 1597 {"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32}, 1598 {"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1599 }; 1600 1601 static void 1602 nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx) 1603 { 1604 free(ctx->nqn); 1605 free(ctx->tgt_name); 1606 free(ctx); 1607 } 1608 1609 static void 1610 nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1611 void *cb_arg, int status) 1612 { 1613 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1614 struct spdk_jsonrpc_request *request = ctx->request; 1615 bool response_sent = ctx->response_sent; 1616 1617 nvmf_rpc_remove_ns_ctx_free(ctx); 1618 1619 if (response_sent) { 1620 return; 1621 } 1622 1623 spdk_jsonrpc_send_bool_response(request, true); 1624 } 1625 1626 static void 1627 nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1628 void *cb_arg, int status) 1629 { 1630 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1631 int ret; 1632 1633 ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid); 1634 if (ret < 0) { 1635 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid); 1636 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1637 "Invalid parameters"); 1638 ctx->response_sent = true; 1639 } 1640 1641 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) { 1642 if (!ctx->response_sent) { 1643 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1644 } 1645 nvmf_rpc_remove_ns_ctx_free(ctx); 1646 } 1647 } 1648 1649 static void 1650 rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request, 1651 const struct spdk_json_val *params) 1652 { 1653 struct nvmf_rpc_remove_ns_ctx *ctx; 1654 struct spdk_nvmf_subsystem *subsystem; 1655 struct spdk_nvmf_tgt *tgt; 1656 int rc; 1657 1658 ctx = calloc(1, sizeof(*ctx)); 1659 if (!ctx) { 1660 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1661 return; 1662 } 1663 1664 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder, 1665 SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder), 1666 ctx)) { 1667 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1668 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1669 nvmf_rpc_remove_ns_ctx_free(ctx); 1670 return; 1671 } 1672 1673 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1674 if (!tgt) { 1675 SPDK_ERRLOG("Unable to find a target object.\n"); 1676 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1677 "Unable to find a target."); 1678 nvmf_rpc_remove_ns_ctx_free(ctx); 1679 return; 1680 } 1681 1682 ctx->request = request; 1683 ctx->response_sent = false; 1684 1685 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1686 if (!subsystem) { 1687 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1688 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1689 nvmf_rpc_remove_ns_ctx_free(ctx); 1690 return; 1691 } 1692 1693 rc = spdk_nvmf_subsystem_pause(subsystem, ctx->nsid, nvmf_rpc_remove_ns_paused, ctx); 1694 if (rc != 0) { 1695 if (rc == -EBUSY) { 1696 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1697 "subsystem busy, retry later.\n"); 1698 } else { 1699 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1700 } 1701 nvmf_rpc_remove_ns_ctx_free(ctx); 1702 } 1703 } 1704 SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME) 1705 1706 struct nvmf_rpc_host_ctx { 1707 struct spdk_jsonrpc_request *request; 1708 char *nqn; 1709 char *host; 1710 char *tgt_name; 1711 bool allow_any_host; 1712 }; 1713 1714 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = { 1715 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1716 {"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string}, 1717 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1718 }; 1719 1720 static void 1721 nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx) 1722 { 1723 free(ctx->nqn); 1724 free(ctx->host); 1725 free(ctx->tgt_name); 1726 } 1727 1728 static void 1729 rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request, 1730 const struct spdk_json_val *params) 1731 { 1732 struct nvmf_rpc_host_ctx ctx = {}; 1733 struct spdk_nvmf_subsystem *subsystem; 1734 struct spdk_nvmf_tgt *tgt; 1735 int rc; 1736 1737 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_subsystem_host_decoder, 1738 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1739 &ctx)) { 1740 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1741 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1742 nvmf_rpc_host_ctx_free(&ctx); 1743 return; 1744 } 1745 1746 tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1747 if (!tgt) { 1748 SPDK_ERRLOG("Unable to find a target object.\n"); 1749 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1750 "Unable to find a target."); 1751 nvmf_rpc_host_ctx_free(&ctx); 1752 return; 1753 } 1754 1755 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 1756 if (!subsystem) { 1757 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn); 1758 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1759 nvmf_rpc_host_ctx_free(&ctx); 1760 return; 1761 } 1762 1763 rc = spdk_nvmf_subsystem_add_host(subsystem, ctx.host, params); 1764 if (rc != 0) { 1765 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1766 nvmf_rpc_host_ctx_free(&ctx); 1767 return; 1768 } 1769 1770 spdk_jsonrpc_send_bool_response(request, true); 1771 nvmf_rpc_host_ctx_free(&ctx); 1772 } 1773 SPDK_RPC_REGISTER("nvmf_subsystem_add_host", rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME) 1774 1775 static void 1776 rpc_nvmf_subsystem_remove_host_done(void *_ctx, int status) 1777 { 1778 struct nvmf_rpc_host_ctx *ctx = _ctx; 1779 1780 spdk_jsonrpc_send_bool_response(ctx->request, true); 1781 nvmf_rpc_host_ctx_free(ctx); 1782 free(ctx); 1783 } 1784 1785 static void 1786 rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request, 1787 const struct spdk_json_val *params) 1788 { 1789 struct nvmf_rpc_host_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 == NULL) { 1796 SPDK_ERRLOG("Unable to allocate context to perform RPC\n"); 1797 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1798 return; 1799 } 1800 1801 ctx->request = request; 1802 1803 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 1804 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1805 ctx)) { 1806 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1807 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1808 nvmf_rpc_host_ctx_free(ctx); 1809 free(ctx); 1810 return; 1811 } 1812 1813 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1814 if (!tgt) { 1815 SPDK_ERRLOG("Unable to find a target object.\n"); 1816 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1817 "Unable to find a target."); 1818 nvmf_rpc_host_ctx_free(ctx); 1819 free(ctx); 1820 return; 1821 } 1822 1823 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1824 if (!subsystem) { 1825 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1826 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1827 nvmf_rpc_host_ctx_free(ctx); 1828 free(ctx); 1829 return; 1830 } 1831 1832 rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host); 1833 if (rc != 0) { 1834 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1835 nvmf_rpc_host_ctx_free(ctx); 1836 free(ctx); 1837 return; 1838 } 1839 1840 rc = spdk_nvmf_subsystem_disconnect_host(subsystem, ctx->host, 1841 rpc_nvmf_subsystem_remove_host_done, 1842 ctx); 1843 if (rc != 0) { 1844 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1845 nvmf_rpc_host_ctx_free(ctx); 1846 free(ctx); 1847 return; 1848 } 1849 } 1850 SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", rpc_nvmf_subsystem_remove_host, 1851 SPDK_RPC_RUNTIME) 1852 1853 1854 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = { 1855 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1856 {"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool}, 1857 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1858 }; 1859 1860 static void 1861 rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request, 1862 const struct spdk_json_val *params) 1863 { 1864 struct nvmf_rpc_host_ctx ctx = {}; 1865 struct spdk_nvmf_subsystem *subsystem; 1866 struct spdk_nvmf_tgt *tgt; 1867 int rc; 1868 1869 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder, 1870 SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder), 1871 &ctx)) { 1872 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1873 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1874 nvmf_rpc_host_ctx_free(&ctx); 1875 return; 1876 } 1877 1878 tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1879 if (!tgt) { 1880 SPDK_ERRLOG("Unable to find a target object.\n"); 1881 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1882 "Unable to find a target."); 1883 nvmf_rpc_host_ctx_free(&ctx); 1884 return; 1885 } 1886 1887 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 1888 if (!subsystem) { 1889 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn); 1890 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1891 nvmf_rpc_host_ctx_free(&ctx); 1892 return; 1893 } 1894 1895 rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx.allow_any_host); 1896 if (rc != 0) { 1897 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1898 nvmf_rpc_host_ctx_free(&ctx); 1899 return; 1900 } 1901 1902 spdk_jsonrpc_send_bool_response(request, true); 1903 nvmf_rpc_host_ctx_free(&ctx); 1904 } 1905 SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", rpc_nvmf_subsystem_allow_any_host, 1906 SPDK_RPC_RUNTIME) 1907 1908 struct nvmf_rpc_target_ctx { 1909 char *name; 1910 uint32_t max_subsystems; 1911 char *discovery_filter; 1912 }; 1913 1914 static int 1915 decode_discovery_filter(const struct spdk_json_val *val, void *out) 1916 { 1917 enum spdk_nvmf_tgt_discovery_filter *_filter = (enum spdk_nvmf_tgt_discovery_filter *)out; 1918 enum spdk_nvmf_tgt_discovery_filter filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY; 1919 char *tokens = spdk_json_strdup(val); 1920 char *tok; 1921 int rc = -EINVAL; 1922 bool all_specified = false; 1923 1924 if (!tokens) { 1925 return -ENOMEM; 1926 } 1927 1928 tok = strtok(tokens, ","); 1929 while (tok) { 1930 if (strncmp(tok, "match_any", 9) == 0) { 1931 if (filter != SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY) { 1932 goto out; 1933 } 1934 filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY; 1935 all_specified = true; 1936 } else { 1937 if (all_specified) { 1938 goto out; 1939 } 1940 if (strncmp(tok, "transport", 9) == 0) { 1941 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE; 1942 } else if (strncmp(tok, "address", 7) == 0) { 1943 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS; 1944 } else if (strncmp(tok, "svcid", 5) == 0) { 1945 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID; 1946 } else { 1947 SPDK_ERRLOG("Invalid value %s\n", tok); 1948 goto out; 1949 } 1950 } 1951 1952 tok = strtok(NULL, ","); 1953 } 1954 1955 rc = 0; 1956 *_filter = filter; 1957 1958 out: 1959 free(tokens); 1960 1961 return rc; 1962 } 1963 1964 static const struct spdk_json_object_decoder nvmf_rpc_create_target_decoder[] = { 1965 {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 1966 {"max_subsystems", offsetof(struct nvmf_rpc_target_ctx, max_subsystems), spdk_json_decode_uint32, true}, 1967 {"discovery_filter", offsetof(struct nvmf_rpc_target_ctx, discovery_filter), decode_discovery_filter, true} 1968 }; 1969 1970 static void 1971 rpc_nvmf_create_target(struct spdk_jsonrpc_request *request, 1972 const struct spdk_json_val *params) 1973 { 1974 struct spdk_nvmf_target_opts opts; 1975 struct nvmf_rpc_target_ctx ctx = {0}; 1976 struct spdk_nvmf_tgt *tgt; 1977 struct spdk_json_write_ctx *w; 1978 1979 /* Decode parameters the first time to get the transport type */ 1980 if (spdk_json_decode_object(params, nvmf_rpc_create_target_decoder, 1981 SPDK_COUNTOF(nvmf_rpc_create_target_decoder), 1982 &ctx)) { 1983 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1984 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1985 goto out; 1986 } 1987 1988 snprintf(opts.name, NVMF_TGT_NAME_MAX_LENGTH, "%s", ctx.name); 1989 opts.max_subsystems = ctx.max_subsystems; 1990 1991 if (spdk_nvmf_get_tgt(opts.name) != NULL) { 1992 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1993 "Target already exists."); 1994 goto out; 1995 } 1996 1997 tgt = spdk_nvmf_tgt_create(&opts); 1998 1999 if (tgt == NULL) { 2000 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2001 "Unable to create the requested target."); 2002 goto out; 2003 } 2004 2005 w = spdk_jsonrpc_begin_result(request); 2006 spdk_json_write_string(w, spdk_nvmf_tgt_get_name(tgt)); 2007 spdk_jsonrpc_end_result(request, w); 2008 out: 2009 free(ctx.name); 2010 free(ctx.discovery_filter); 2011 } 2012 /* private */ SPDK_RPC_REGISTER("nvmf_create_target", rpc_nvmf_create_target, SPDK_RPC_RUNTIME); 2013 2014 static const struct spdk_json_object_decoder nvmf_rpc_destroy_target_decoder[] = { 2015 {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 2016 }; 2017 2018 static void 2019 nvmf_rpc_destroy_target_done(void *ctx, int status) 2020 { 2021 struct spdk_jsonrpc_request *request = ctx; 2022 2023 spdk_jsonrpc_send_bool_response(request, true); 2024 } 2025 2026 static void 2027 rpc_nvmf_delete_target(struct spdk_jsonrpc_request *request, 2028 const struct spdk_json_val *params) 2029 { 2030 struct nvmf_rpc_target_ctx ctx = {0}; 2031 struct spdk_nvmf_tgt *tgt; 2032 2033 /* Decode parameters the first time to get the transport type */ 2034 if (spdk_json_decode_object(params, nvmf_rpc_destroy_target_decoder, 2035 SPDK_COUNTOF(nvmf_rpc_destroy_target_decoder), 2036 &ctx)) { 2037 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2038 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2039 free(ctx.name); 2040 return; 2041 } 2042 2043 tgt = spdk_nvmf_get_tgt(ctx.name); 2044 2045 if (tgt == NULL) { 2046 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2047 "The specified target doesn't exist, cannot delete it."); 2048 free(ctx.name); 2049 return; 2050 } 2051 2052 spdk_nvmf_tgt_destroy(tgt, nvmf_rpc_destroy_target_done, request); 2053 free(ctx.name); 2054 } 2055 /* private */ SPDK_RPC_REGISTER("nvmf_delete_target", rpc_nvmf_delete_target, SPDK_RPC_RUNTIME); 2056 2057 static void 2058 rpc_nvmf_get_targets(struct spdk_jsonrpc_request *request, 2059 const struct spdk_json_val *params) 2060 { 2061 struct spdk_json_write_ctx *w; 2062 struct spdk_nvmf_tgt *tgt; 2063 const char *name; 2064 2065 if (params != NULL) { 2066 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2067 "nvmf_get_targets has no parameters."); 2068 return; 2069 } 2070 2071 w = spdk_jsonrpc_begin_result(request); 2072 spdk_json_write_array_begin(w); 2073 2074 tgt = spdk_nvmf_get_first_tgt(); 2075 2076 while (tgt != NULL) { 2077 name = spdk_nvmf_tgt_get_name(tgt); 2078 spdk_json_write_string(w, name); 2079 tgt = spdk_nvmf_get_next_tgt(tgt); 2080 } 2081 2082 spdk_json_write_array_end(w); 2083 spdk_jsonrpc_end_result(request, w); 2084 } 2085 /* private */ SPDK_RPC_REGISTER("nvmf_get_targets", rpc_nvmf_get_targets, SPDK_RPC_RUNTIME); 2086 2087 struct nvmf_rpc_create_transport_ctx { 2088 char *trtype; 2089 char *tgt_name; 2090 struct spdk_nvmf_transport_opts opts; 2091 struct spdk_jsonrpc_request *request; 2092 struct spdk_nvmf_transport *transport; 2093 int status; 2094 }; 2095 2096 /** 2097 * `max_qpairs_per_ctrlr` represents both admin and IO qpairs, that confuses 2098 * users when they configure a transport using RPC. So it was decided to 2099 * deprecate `max_qpairs_per_ctrlr` RPC parameter and use `max_io_qpairs_per_ctrlr` 2100 * But internal logic remains unchanged and SPDK expects that 2101 * spdk_nvmf_transport_opts::max_qpairs_per_ctrlr includes an admin qpair. 2102 * This function parses the number of IO qpairs and adds +1 for admin qpair. 2103 */ 2104 static int 2105 nvmf_rpc_decode_max_io_qpairs(const struct spdk_json_val *val, void *out) 2106 { 2107 uint16_t *i = out; 2108 int rc; 2109 2110 rc = spdk_json_number_to_uint16(val, i); 2111 if (rc == 0) { 2112 (*i)++; 2113 } 2114 2115 return rc; 2116 } 2117 2118 static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = { 2119 { "trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string}, 2120 { 2121 "max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth), 2122 spdk_json_decode_uint16, true 2123 }, 2124 { 2125 "max_io_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr), 2126 nvmf_rpc_decode_max_io_qpairs, true 2127 }, 2128 { 2129 "in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size), 2130 spdk_json_decode_uint32, true 2131 }, 2132 { 2133 "max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size), 2134 spdk_json_decode_uint32, true 2135 }, 2136 { 2137 "io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size), 2138 spdk_json_decode_uint32, true 2139 }, 2140 { 2141 "max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth), 2142 spdk_json_decode_uint32, true 2143 }, 2144 { 2145 "num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers), 2146 spdk_json_decode_uint32, true 2147 }, 2148 { 2149 "buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size), 2150 spdk_json_decode_uint32, true 2151 }, 2152 { 2153 "dif_insert_or_strip", offsetof(struct nvmf_rpc_create_transport_ctx, opts.dif_insert_or_strip), 2154 spdk_json_decode_bool, true 2155 }, 2156 { 2157 "abort_timeout_sec", offsetof(struct nvmf_rpc_create_transport_ctx, opts.abort_timeout_sec), 2158 spdk_json_decode_uint32, true 2159 }, 2160 { 2161 "zcopy", offsetof(struct nvmf_rpc_create_transport_ctx, opts.zcopy), 2162 spdk_json_decode_bool, true 2163 }, 2164 { 2165 "tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name), 2166 spdk_json_decode_string, true 2167 }, 2168 { 2169 "acceptor_poll_rate", offsetof(struct nvmf_rpc_create_transport_ctx, opts.acceptor_poll_rate), 2170 spdk_json_decode_uint32, true 2171 }, 2172 { 2173 "ack_timeout", offsetof(struct nvmf_rpc_create_transport_ctx, opts.ack_timeout), 2174 spdk_json_decode_uint32, true 2175 } 2176 }; 2177 2178 static void 2179 nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx) 2180 { 2181 free(ctx->trtype); 2182 free(ctx->tgt_name); 2183 free(ctx); 2184 } 2185 2186 static void 2187 nvmf_rpc_transport_destroy_done_cb(void *cb_arg) 2188 { 2189 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2190 2191 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2192 "Failed to add transport to tgt.(%d)", ctx->status); 2193 nvmf_rpc_create_transport_ctx_free(ctx); 2194 } 2195 2196 static void 2197 nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status) 2198 { 2199 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2200 2201 if (status) { 2202 SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status); 2203 ctx->status = status; 2204 spdk_nvmf_transport_destroy(ctx->transport, nvmf_rpc_transport_destroy_done_cb, ctx); 2205 return; 2206 } 2207 2208 spdk_jsonrpc_send_bool_response(ctx->request, true); 2209 nvmf_rpc_create_transport_ctx_free(ctx); 2210 } 2211 2212 static void 2213 nvmf_rpc_create_transport_done(void *cb_arg, struct spdk_nvmf_transport *transport) 2214 { 2215 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2216 2217 if (!transport) { 2218 SPDK_ERRLOG("Failed to create transport.\n"); 2219 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2220 "Failed to create transport."); 2221 nvmf_rpc_create_transport_ctx_free(ctx); 2222 return; 2223 } 2224 2225 ctx->transport = transport; 2226 2227 spdk_nvmf_tgt_add_transport(spdk_nvmf_get_tgt(ctx->tgt_name), transport, 2228 nvmf_rpc_tgt_add_transport_done, ctx); 2229 } 2230 2231 static void 2232 rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request, 2233 const struct spdk_json_val *params) 2234 { 2235 struct nvmf_rpc_create_transport_ctx *ctx; 2236 struct spdk_nvmf_tgt *tgt; 2237 int rc; 2238 2239 ctx = calloc(1, sizeof(*ctx)); 2240 if (!ctx) { 2241 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 2242 return; 2243 } 2244 2245 /* Decode parameters the first time to get the transport type */ 2246 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder, 2247 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 2248 ctx)) { 2249 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 2250 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2251 nvmf_rpc_create_transport_ctx_free(ctx); 2252 return; 2253 } 2254 2255 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2256 if (!tgt) { 2257 SPDK_ERRLOG("Unable to find a target object.\n"); 2258 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2259 "Unable to find a target."); 2260 nvmf_rpc_create_transport_ctx_free(ctx); 2261 return; 2262 } 2263 2264 /* Initialize all the transport options (based on transport type) and decode the 2265 * parameters again to update any options passed in rpc create transport call. 2266 */ 2267 if (!spdk_nvmf_transport_opts_init(ctx->trtype, &ctx->opts, sizeof(ctx->opts))) { 2268 /* This can happen if user specifies PCIE transport type which isn't valid for 2269 * NVMe-oF. 2270 */ 2271 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype); 2272 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2273 "Invalid transport type '%s'", ctx->trtype); 2274 nvmf_rpc_create_transport_ctx_free(ctx); 2275 return; 2276 } 2277 2278 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder, 2279 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 2280 ctx)) { 2281 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 2282 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2283 nvmf_rpc_create_transport_ctx_free(ctx); 2284 return; 2285 } 2286 2287 if (spdk_nvmf_tgt_get_transport(tgt, ctx->trtype)) { 2288 SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype); 2289 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2290 "Transport type '%s' already exists", ctx->trtype); 2291 nvmf_rpc_create_transport_ctx_free(ctx); 2292 return; 2293 } 2294 2295 /* Transport can parse additional params themselves */ 2296 ctx->opts.transport_specific = params; 2297 ctx->request = request; 2298 2299 rc = spdk_nvmf_transport_create_async(ctx->trtype, &ctx->opts, nvmf_rpc_create_transport_done, ctx); 2300 if (rc) { 2301 SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype); 2302 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2303 "Transport type '%s' create failed", ctx->trtype); 2304 nvmf_rpc_create_transport_ctx_free(ctx); 2305 } 2306 } 2307 SPDK_RPC_REGISTER("nvmf_create_transport", rpc_nvmf_create_transport, SPDK_RPC_RUNTIME) 2308 2309 struct rpc_get_transport { 2310 char *trtype; 2311 char *tgt_name; 2312 }; 2313 2314 static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = { 2315 {"trtype", offsetof(struct rpc_get_transport, trtype), spdk_json_decode_string, true}, 2316 {"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true}, 2317 }; 2318 2319 static void 2320 rpc_nvmf_get_transports(struct spdk_jsonrpc_request *request, 2321 const struct spdk_json_val *params) 2322 { 2323 struct rpc_get_transport req = { 0 }; 2324 struct spdk_json_write_ctx *w; 2325 struct spdk_nvmf_transport *transport = NULL; 2326 struct spdk_nvmf_tgt *tgt; 2327 2328 if (params) { 2329 if (spdk_json_decode_object(params, rpc_get_transport_decoders, 2330 SPDK_COUNTOF(rpc_get_transport_decoders), 2331 &req)) { 2332 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2333 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2334 return; 2335 } 2336 } 2337 2338 tgt = spdk_nvmf_get_tgt(req.tgt_name); 2339 if (!tgt) { 2340 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2341 "Unable to find a target."); 2342 free(req.trtype); 2343 free(req.tgt_name); 2344 return; 2345 } 2346 2347 if (req.trtype) { 2348 transport = spdk_nvmf_tgt_get_transport(tgt, req.trtype); 2349 if (transport == NULL) { 2350 SPDK_ERRLOG("transport '%s' does not exist\n", req.trtype); 2351 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 2352 free(req.trtype); 2353 free(req.tgt_name); 2354 return; 2355 } 2356 } 2357 2358 w = spdk_jsonrpc_begin_result(request); 2359 spdk_json_write_array_begin(w); 2360 2361 if (transport) { 2362 nvmf_transport_dump_opts(transport, w, false); 2363 } else { 2364 for (transport = spdk_nvmf_transport_get_first(tgt); transport != NULL; 2365 transport = spdk_nvmf_transport_get_next(transport)) { 2366 nvmf_transport_dump_opts(transport, w, false); 2367 } 2368 } 2369 2370 spdk_json_write_array_end(w); 2371 spdk_jsonrpc_end_result(request, w); 2372 free(req.trtype); 2373 free(req.tgt_name); 2374 } 2375 SPDK_RPC_REGISTER("nvmf_get_transports", rpc_nvmf_get_transports, SPDK_RPC_RUNTIME) 2376 2377 struct rpc_nvmf_get_stats_ctx { 2378 char *tgt_name; 2379 struct spdk_nvmf_tgt *tgt; 2380 struct spdk_jsonrpc_request *request; 2381 struct spdk_json_write_ctx *w; 2382 }; 2383 2384 static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = { 2385 {"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true}, 2386 }; 2387 2388 static void 2389 free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx) 2390 { 2391 free(ctx->tgt_name); 2392 free(ctx); 2393 } 2394 2395 static void 2396 rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status) 2397 { 2398 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2399 2400 spdk_json_write_array_end(ctx->w); 2401 spdk_json_write_object_end(ctx->w); 2402 spdk_jsonrpc_end_result(ctx->request, ctx->w); 2403 free_get_stats_ctx(ctx); 2404 } 2405 2406 static void 2407 _rpc_nvmf_get_stats(struct spdk_io_channel_iter *i) 2408 { 2409 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2410 struct spdk_io_channel *ch; 2411 struct spdk_nvmf_poll_group *group; 2412 2413 ch = spdk_get_io_channel(ctx->tgt); 2414 group = spdk_io_channel_get_ctx(ch); 2415 2416 spdk_nvmf_poll_group_dump_stat(group, ctx->w); 2417 2418 spdk_put_io_channel(ch); 2419 spdk_for_each_channel_continue(i, 0); 2420 } 2421 2422 2423 static void 2424 rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request, 2425 const struct spdk_json_val *params) 2426 { 2427 struct rpc_nvmf_get_stats_ctx *ctx; 2428 2429 ctx = calloc(1, sizeof(*ctx)); 2430 if (!ctx) { 2431 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2432 "Memory allocation error"); 2433 return; 2434 } 2435 ctx->request = request; 2436 2437 if (params) { 2438 if (spdk_json_decode_object(params, rpc_get_stats_decoders, 2439 SPDK_COUNTOF(rpc_get_stats_decoders), 2440 ctx)) { 2441 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2442 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2443 free_get_stats_ctx(ctx); 2444 return; 2445 } 2446 } 2447 2448 ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2449 if (!ctx->tgt) { 2450 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2451 "Unable to find a target."); 2452 free_get_stats_ctx(ctx); 2453 return; 2454 } 2455 2456 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 2457 spdk_json_write_object_begin(ctx->w); 2458 spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz()); 2459 spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 2460 2461 spdk_for_each_channel(ctx->tgt, 2462 _rpc_nvmf_get_stats, 2463 ctx, 2464 rpc_nvmf_get_stats_done); 2465 } 2466 2467 SPDK_RPC_REGISTER("nvmf_get_stats", rpc_nvmf_get_stats, SPDK_RPC_RUNTIME) 2468 2469 static void 2470 dump_nvmf_ctrlr(struct spdk_json_write_ctx *w, struct spdk_nvmf_ctrlr *ctrlr) 2471 { 2472 uint32_t count; 2473 2474 spdk_json_write_object_begin(w); 2475 2476 spdk_json_write_named_uint32(w, "cntlid", ctrlr->cntlid); 2477 spdk_json_write_named_string(w, "hostnqn", ctrlr->hostnqn); 2478 spdk_json_write_named_uuid(w, "hostid", &ctrlr->hostid); 2479 2480 count = spdk_bit_array_count_set(ctrlr->qpair_mask); 2481 spdk_json_write_named_uint32(w, "num_io_qpairs", count); 2482 2483 spdk_json_write_object_end(w); 2484 } 2485 2486 static const char * 2487 nvmf_qpair_state_str(enum spdk_nvmf_qpair_state state) 2488 { 2489 switch (state) { 2490 case SPDK_NVMF_QPAIR_UNINITIALIZED: 2491 return "uninitialized"; 2492 case SPDK_NVMF_QPAIR_ACTIVE: 2493 return "active"; 2494 case SPDK_NVMF_QPAIR_DEACTIVATING: 2495 return "deactivating"; 2496 case SPDK_NVMF_QPAIR_ERROR: 2497 return "error"; 2498 default: 2499 return NULL; 2500 } 2501 } 2502 2503 static void 2504 dump_nvmf_qpair(struct spdk_json_write_ctx *w, struct spdk_nvmf_qpair *qpair) 2505 { 2506 struct spdk_nvme_transport_id trid = {}; 2507 2508 spdk_json_write_object_begin(w); 2509 2510 spdk_json_write_named_uint32(w, "cntlid", qpair->ctrlr->cntlid); 2511 spdk_json_write_named_uint32(w, "qid", qpair->qid); 2512 spdk_json_write_named_string(w, "state", nvmf_qpair_state_str(qpair->state)); 2513 2514 if (spdk_nvmf_qpair_get_listen_trid(qpair, &trid) == 0) { 2515 spdk_json_write_named_object_begin(w, "listen_address"); 2516 nvmf_transport_listen_dump_trid(&trid, w); 2517 spdk_json_write_object_end(w); 2518 if (qpair->transport->ops->listen_dump_opts) { 2519 qpair->transport->ops->listen_dump_opts(qpair->transport, &trid, w); 2520 } 2521 } 2522 2523 memset(&trid, 0, sizeof(trid)); 2524 if (spdk_nvmf_qpair_get_peer_trid(qpair, &trid) == 0) { 2525 spdk_json_write_named_object_begin(w, "peer_address"); 2526 nvmf_transport_listen_dump_trid(&trid, w); 2527 spdk_json_write_object_end(w); 2528 } 2529 2530 spdk_json_write_object_end(w); 2531 } 2532 2533 static const char * 2534 nvme_ana_state_str(enum spdk_nvme_ana_state ana_state) 2535 { 2536 switch (ana_state) { 2537 case SPDK_NVME_ANA_OPTIMIZED_STATE: 2538 return "optimized"; 2539 case SPDK_NVME_ANA_NON_OPTIMIZED_STATE: 2540 return "non_optimized"; 2541 case SPDK_NVME_ANA_INACCESSIBLE_STATE: 2542 return "inaccessible"; 2543 case SPDK_NVME_ANA_PERSISTENT_LOSS_STATE: 2544 return "persistent_loss"; 2545 case SPDK_NVME_ANA_CHANGE_STATE: 2546 return "change"; 2547 default: 2548 return NULL; 2549 } 2550 } 2551 2552 static void 2553 dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w, 2554 struct spdk_nvmf_subsystem_listener *listener) 2555 { 2556 const struct spdk_nvme_transport_id *trid = listener->trid; 2557 uint32_t i; 2558 2559 spdk_json_write_object_begin(w); 2560 2561 spdk_json_write_named_object_begin(w, "address"); 2562 nvmf_transport_listen_dump_trid(trid, w); 2563 spdk_json_write_object_end(w); 2564 2565 if (spdk_nvmf_subsystem_get_ana_reporting(listener->subsystem)) { 2566 spdk_json_write_named_array_begin(w, "ana_states"); 2567 for (i = 0; i < listener->subsystem->max_nsid; i++) { 2568 spdk_json_write_object_begin(w); 2569 spdk_json_write_named_uint32(w, "ana_group", i + 1); 2570 spdk_json_write_named_string(w, "ana_state", 2571 nvme_ana_state_str(listener->ana_state[i])); 2572 spdk_json_write_object_end(w); 2573 } 2574 spdk_json_write_array_end(w); 2575 } 2576 2577 spdk_json_write_object_end(w); 2578 } 2579 2580 struct rpc_subsystem_query_ctx { 2581 char *nqn; 2582 char *tgt_name; 2583 struct spdk_nvmf_subsystem *subsystem; 2584 struct spdk_jsonrpc_request *request; 2585 struct spdk_json_write_ctx *w; 2586 }; 2587 2588 static const struct spdk_json_object_decoder rpc_subsystem_query_decoders[] = { 2589 {"nqn", offsetof(struct rpc_subsystem_query_ctx, nqn), spdk_json_decode_string}, 2590 {"tgt_name", offsetof(struct rpc_subsystem_query_ctx, tgt_name), spdk_json_decode_string, true}, 2591 }; 2592 2593 static void 2594 free_rpc_subsystem_query_ctx(struct rpc_subsystem_query_ctx *ctx) 2595 { 2596 free(ctx->nqn); 2597 free(ctx->tgt_name); 2598 free(ctx); 2599 } 2600 2601 static void 2602 rpc_nvmf_get_controllers_paused(struct spdk_nvmf_subsystem *subsystem, 2603 void *cb_arg, int status) 2604 { 2605 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2606 struct spdk_json_write_ctx *w; 2607 struct spdk_nvmf_ctrlr *ctrlr; 2608 2609 w = spdk_jsonrpc_begin_result(ctx->request); 2610 2611 spdk_json_write_array_begin(w); 2612 TAILQ_FOREACH(ctrlr, &ctx->subsystem->ctrlrs, link) { 2613 dump_nvmf_ctrlr(w, ctrlr); 2614 } 2615 spdk_json_write_array_end(w); 2616 2617 spdk_jsonrpc_end_result(ctx->request, w); 2618 2619 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2620 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2621 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2622 } 2623 2624 free_rpc_subsystem_query_ctx(ctx); 2625 } 2626 2627 static void 2628 rpc_nvmf_get_qpairs_done(struct spdk_io_channel_iter *i, int status) 2629 { 2630 struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2631 2632 spdk_json_write_array_end(ctx->w); 2633 spdk_jsonrpc_end_result(ctx->request, ctx->w); 2634 2635 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2636 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2637 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2638 } 2639 2640 free_rpc_subsystem_query_ctx(ctx); 2641 } 2642 2643 static void 2644 rpc_nvmf_get_qpairs(struct spdk_io_channel_iter *i) 2645 { 2646 struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2647 struct spdk_io_channel *ch; 2648 struct spdk_nvmf_poll_group *group; 2649 struct spdk_nvmf_qpair *qpair; 2650 2651 ch = spdk_io_channel_iter_get_channel(i); 2652 group = spdk_io_channel_get_ctx(ch); 2653 2654 TAILQ_FOREACH(qpair, &group->qpairs, link) { 2655 if (qpair->ctrlr->subsys == ctx->subsystem) { 2656 dump_nvmf_qpair(ctx->w, qpair); 2657 } 2658 } 2659 2660 spdk_for_each_channel_continue(i, 0); 2661 } 2662 2663 static void 2664 rpc_nvmf_get_qpairs_paused(struct spdk_nvmf_subsystem *subsystem, 2665 void *cb_arg, int status) 2666 { 2667 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2668 2669 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 2670 2671 spdk_json_write_array_begin(ctx->w); 2672 2673 spdk_for_each_channel(ctx->subsystem->tgt, 2674 rpc_nvmf_get_qpairs, 2675 ctx, 2676 rpc_nvmf_get_qpairs_done); 2677 } 2678 2679 static void 2680 rpc_nvmf_get_listeners_paused(struct spdk_nvmf_subsystem *subsystem, 2681 void *cb_arg, int status) 2682 { 2683 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2684 struct spdk_json_write_ctx *w; 2685 struct spdk_nvmf_subsystem_listener *listener; 2686 2687 w = spdk_jsonrpc_begin_result(ctx->request); 2688 2689 spdk_json_write_array_begin(w); 2690 2691 for (listener = spdk_nvmf_subsystem_get_first_listener(ctx->subsystem); 2692 listener != NULL; 2693 listener = spdk_nvmf_subsystem_get_next_listener(ctx->subsystem, listener)) { 2694 dump_nvmf_subsystem_listener(w, listener); 2695 } 2696 spdk_json_write_array_end(w); 2697 2698 spdk_jsonrpc_end_result(ctx->request, w); 2699 2700 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2701 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2702 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2703 } 2704 2705 free_rpc_subsystem_query_ctx(ctx); 2706 } 2707 2708 static void 2709 _rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request, 2710 const struct spdk_json_val *params, 2711 spdk_nvmf_subsystem_state_change_done cb_fn) 2712 { 2713 struct rpc_subsystem_query_ctx *ctx; 2714 struct spdk_nvmf_subsystem *subsystem; 2715 struct spdk_nvmf_tgt *tgt; 2716 2717 ctx = calloc(1, sizeof(*ctx)); 2718 if (!ctx) { 2719 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2720 "Out of memory"); 2721 return; 2722 } 2723 2724 ctx->request = request; 2725 2726 if (spdk_json_decode_object(params, rpc_subsystem_query_decoders, 2727 SPDK_COUNTOF(rpc_subsystem_query_decoders), 2728 ctx)) { 2729 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2730 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2731 "Invalid parameters"); 2732 free_rpc_subsystem_query_ctx(ctx); 2733 return; 2734 } 2735 2736 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2737 if (!tgt) { 2738 SPDK_ERRLOG("Unable to find a target object.\n"); 2739 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2740 "Unable to find a target"); 2741 free_rpc_subsystem_query_ctx(ctx); 2742 return; 2743 } 2744 2745 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 2746 if (!subsystem) { 2747 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 2748 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2749 "Invalid parameters"); 2750 free_rpc_subsystem_query_ctx(ctx); 2751 return; 2752 } 2753 2754 ctx->subsystem = subsystem; 2755 2756 if (spdk_nvmf_subsystem_pause(subsystem, 0, cb_fn, ctx)) { 2757 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2758 "Internal error"); 2759 free_rpc_subsystem_query_ctx(ctx); 2760 return; 2761 } 2762 } 2763 2764 static void 2765 rpc_nvmf_subsystem_get_controllers(struct spdk_jsonrpc_request *request, 2766 const struct spdk_json_val *params) 2767 { 2768 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_controllers_paused); 2769 } 2770 SPDK_RPC_REGISTER("nvmf_subsystem_get_controllers", rpc_nvmf_subsystem_get_controllers, 2771 SPDK_RPC_RUNTIME); 2772 2773 static void 2774 rpc_nvmf_subsystem_get_qpairs(struct spdk_jsonrpc_request *request, 2775 const struct spdk_json_val *params) 2776 { 2777 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused); 2778 } 2779 SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME); 2780 2781 static void 2782 rpc_nvmf_subsystem_get_listeners(struct spdk_jsonrpc_request *request, 2783 const struct spdk_json_val *params) 2784 { 2785 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_listeners_paused); 2786 } 2787 SPDK_RPC_REGISTER("nvmf_subsystem_get_listeners", rpc_nvmf_subsystem_get_listeners, 2788 SPDK_RPC_RUNTIME); 2789