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 spdk_nvmf_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 spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true}, 1384 {"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string}, 1385 {"ptpl_file", offsetof(struct spdk_nvmf_ns_params, ptpl_file), spdk_json_decode_string, true}, 1386 {"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true}, 1387 {"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true}, 1388 {"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), spdk_json_decode_uuid, true}, 1389 {"anagrpid", offsetof(struct spdk_nvmf_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 spdk_nvmf_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 spdk_nvmf_ns_params ns_params; 1406 1407 struct spdk_jsonrpc_request *request; 1408 bool response_sent; 1409 }; 1410 1411 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = { 1412 {"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string}, 1413 {"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params}, 1414 {"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1415 }; 1416 1417 static void 1418 nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx) 1419 { 1420 free(ctx->nqn); 1421 free(ctx->tgt_name); 1422 free(ctx->ns_params.bdev_name); 1423 free(ctx->ns_params.ptpl_file); 1424 free(ctx); 1425 } 1426 1427 static void 1428 nvmf_rpc_ns_failback_resumed(struct spdk_nvmf_subsystem *subsystem, 1429 void *cb_arg, int status) 1430 { 1431 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1432 struct spdk_jsonrpc_request *request = ctx->request; 1433 1434 if (status) { 1435 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1436 "Unable to add ns, subsystem in invalid state"); 1437 } else { 1438 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1439 "Unable to add ns, subsystem in active state"); 1440 } 1441 1442 nvmf_rpc_ns_ctx_free(ctx); 1443 } 1444 1445 static void 1446 nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1447 void *cb_arg, int status) 1448 { 1449 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1450 struct spdk_jsonrpc_request *request = ctx->request; 1451 uint32_t nsid = ctx->ns_params.nsid; 1452 bool response_sent = ctx->response_sent; 1453 struct spdk_json_write_ctx *w; 1454 int rc; 1455 1456 /* The case where the call to add the namespace was successful, but the subsystem couldn't be resumed. */ 1457 if (status && !ctx->response_sent) { 1458 rc = spdk_nvmf_subsystem_remove_ns(subsystem, nsid); 1459 if (rc != 0) { 1460 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1461 "Unable to add ns, subsystem in invalid state"); 1462 nvmf_rpc_ns_ctx_free(ctx); 1463 return; 1464 } 1465 1466 rc = spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_failback_resumed, ctx); 1467 if (rc != 0) { 1468 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1469 nvmf_rpc_ns_ctx_free(ctx); 1470 return; 1471 } 1472 1473 return; 1474 } 1475 1476 nvmf_rpc_ns_ctx_free(ctx); 1477 1478 if (response_sent) { 1479 return; 1480 } 1481 1482 w = spdk_jsonrpc_begin_result(request); 1483 spdk_json_write_uint32(w, nsid); 1484 spdk_jsonrpc_end_result(request, w); 1485 } 1486 1487 static void 1488 nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1489 void *cb_arg, int status) 1490 { 1491 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1492 struct spdk_nvmf_ns_opts ns_opts; 1493 1494 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 1495 ns_opts.nsid = ctx->ns_params.nsid; 1496 1497 SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch"); 1498 memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid)); 1499 1500 SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch"); 1501 memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64)); 1502 1503 if (!spdk_uuid_is_null(&ctx->ns_params.uuid)) { 1504 ns_opts.uuid = ctx->ns_params.uuid; 1505 } 1506 1507 ns_opts.anagrpid = ctx->ns_params.anagrpid; 1508 1509 ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns_ext(subsystem, ctx->ns_params.bdev_name, 1510 &ns_opts, sizeof(ns_opts), 1511 ctx->ns_params.ptpl_file); 1512 if (ctx->ns_params.nsid == 0) { 1513 SPDK_ERRLOG("Unable to add namespace\n"); 1514 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1515 "Invalid parameters"); 1516 ctx->response_sent = true; 1517 goto resume; 1518 } 1519 1520 resume: 1521 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) { 1522 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1523 nvmf_rpc_ns_ctx_free(ctx); 1524 } 1525 } 1526 1527 static void 1528 rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request, 1529 const struct spdk_json_val *params) 1530 { 1531 struct nvmf_rpc_ns_ctx *ctx; 1532 struct spdk_nvmf_subsystem *subsystem; 1533 struct spdk_nvmf_tgt *tgt; 1534 int rc; 1535 1536 ctx = calloc(1, sizeof(*ctx)); 1537 if (!ctx) { 1538 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1539 return; 1540 } 1541 1542 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ns_decoder, 1543 SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder), 1544 ctx)) { 1545 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1546 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1547 nvmf_rpc_ns_ctx_free(ctx); 1548 return; 1549 } 1550 1551 ctx->request = request; 1552 ctx->response_sent = false; 1553 1554 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1555 if (!tgt) { 1556 SPDK_ERRLOG("Unable to find a target object.\n"); 1557 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1558 "Unable to find a target."); 1559 nvmf_rpc_ns_ctx_free(ctx); 1560 return; 1561 } 1562 1563 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1564 if (!subsystem) { 1565 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1566 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1567 nvmf_rpc_ns_ctx_free(ctx); 1568 return; 1569 } 1570 1571 rc = spdk_nvmf_subsystem_pause(subsystem, ctx->ns_params.nsid, nvmf_rpc_ns_paused, ctx); 1572 if (rc != 0) { 1573 if (rc == -EBUSY) { 1574 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1575 "subsystem busy, retry later.\n"); 1576 } else { 1577 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1578 } 1579 nvmf_rpc_ns_ctx_free(ctx); 1580 } 1581 } 1582 SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME) 1583 1584 struct nvmf_rpc_remove_ns_ctx { 1585 char *nqn; 1586 char *tgt_name; 1587 uint32_t nsid; 1588 1589 struct spdk_jsonrpc_request *request; 1590 bool response_sent; 1591 }; 1592 1593 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = { 1594 {"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string}, 1595 {"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32}, 1596 {"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1597 }; 1598 1599 static void 1600 nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx) 1601 { 1602 free(ctx->nqn); 1603 free(ctx->tgt_name); 1604 free(ctx); 1605 } 1606 1607 static void 1608 nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1609 void *cb_arg, int status) 1610 { 1611 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1612 struct spdk_jsonrpc_request *request = ctx->request; 1613 bool response_sent = ctx->response_sent; 1614 1615 nvmf_rpc_remove_ns_ctx_free(ctx); 1616 1617 if (response_sent) { 1618 return; 1619 } 1620 1621 spdk_jsonrpc_send_bool_response(request, true); 1622 } 1623 1624 static void 1625 nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1626 void *cb_arg, int status) 1627 { 1628 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1629 int ret; 1630 1631 ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid); 1632 if (ret < 0) { 1633 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid); 1634 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1635 "Invalid parameters"); 1636 ctx->response_sent = true; 1637 } 1638 1639 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) { 1640 if (!ctx->response_sent) { 1641 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1642 } 1643 nvmf_rpc_remove_ns_ctx_free(ctx); 1644 } 1645 } 1646 1647 static void 1648 rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request, 1649 const struct spdk_json_val *params) 1650 { 1651 struct nvmf_rpc_remove_ns_ctx *ctx; 1652 struct spdk_nvmf_subsystem *subsystem; 1653 struct spdk_nvmf_tgt *tgt; 1654 int rc; 1655 1656 ctx = calloc(1, sizeof(*ctx)); 1657 if (!ctx) { 1658 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1659 return; 1660 } 1661 1662 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder, 1663 SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder), 1664 ctx)) { 1665 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1666 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1667 nvmf_rpc_remove_ns_ctx_free(ctx); 1668 return; 1669 } 1670 1671 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1672 if (!tgt) { 1673 SPDK_ERRLOG("Unable to find a target object.\n"); 1674 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1675 "Unable to find a target."); 1676 nvmf_rpc_remove_ns_ctx_free(ctx); 1677 return; 1678 } 1679 1680 ctx->request = request; 1681 ctx->response_sent = false; 1682 1683 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1684 if (!subsystem) { 1685 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1686 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1687 nvmf_rpc_remove_ns_ctx_free(ctx); 1688 return; 1689 } 1690 1691 rc = spdk_nvmf_subsystem_pause(subsystem, ctx->nsid, nvmf_rpc_remove_ns_paused, ctx); 1692 if (rc != 0) { 1693 if (rc == -EBUSY) { 1694 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1695 "subsystem busy, retry later.\n"); 1696 } else { 1697 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1698 } 1699 nvmf_rpc_remove_ns_ctx_free(ctx); 1700 } 1701 } 1702 SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME) 1703 1704 struct nvmf_rpc_host_ctx { 1705 struct spdk_jsonrpc_request *request; 1706 char *nqn; 1707 char *host; 1708 char *tgt_name; 1709 bool allow_any_host; 1710 }; 1711 1712 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = { 1713 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1714 {"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string}, 1715 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1716 }; 1717 1718 static void 1719 nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx) 1720 { 1721 free(ctx->nqn); 1722 free(ctx->host); 1723 free(ctx->tgt_name); 1724 } 1725 1726 static void 1727 rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request, 1728 const struct spdk_json_val *params) 1729 { 1730 struct nvmf_rpc_host_ctx ctx = {}; 1731 struct spdk_nvmf_subsystem *subsystem; 1732 struct spdk_nvmf_tgt *tgt; 1733 int rc; 1734 1735 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_subsystem_host_decoder, 1736 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1737 &ctx)) { 1738 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1739 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1740 nvmf_rpc_host_ctx_free(&ctx); 1741 return; 1742 } 1743 1744 tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1745 if (!tgt) { 1746 SPDK_ERRLOG("Unable to find a target object.\n"); 1747 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1748 "Unable to find a target."); 1749 nvmf_rpc_host_ctx_free(&ctx); 1750 return; 1751 } 1752 1753 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 1754 if (!subsystem) { 1755 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn); 1756 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1757 nvmf_rpc_host_ctx_free(&ctx); 1758 return; 1759 } 1760 1761 rc = spdk_nvmf_subsystem_add_host(subsystem, ctx.host, params); 1762 if (rc != 0) { 1763 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1764 nvmf_rpc_host_ctx_free(&ctx); 1765 return; 1766 } 1767 1768 spdk_jsonrpc_send_bool_response(request, true); 1769 nvmf_rpc_host_ctx_free(&ctx); 1770 } 1771 SPDK_RPC_REGISTER("nvmf_subsystem_add_host", rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME) 1772 1773 static void 1774 rpc_nvmf_subsystem_remove_host_done(void *_ctx, int status) 1775 { 1776 struct nvmf_rpc_host_ctx *ctx = _ctx; 1777 1778 spdk_jsonrpc_send_bool_response(ctx->request, true); 1779 nvmf_rpc_host_ctx_free(ctx); 1780 free(ctx); 1781 } 1782 1783 static void 1784 rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request, 1785 const struct spdk_json_val *params) 1786 { 1787 struct nvmf_rpc_host_ctx *ctx; 1788 struct spdk_nvmf_subsystem *subsystem; 1789 struct spdk_nvmf_tgt *tgt; 1790 int rc; 1791 1792 ctx = calloc(1, sizeof(*ctx)); 1793 if (ctx == NULL) { 1794 SPDK_ERRLOG("Unable to allocate context to perform RPC\n"); 1795 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1796 return; 1797 } 1798 1799 ctx->request = request; 1800 1801 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 1802 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1803 ctx)) { 1804 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1805 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1806 nvmf_rpc_host_ctx_free(ctx); 1807 free(ctx); 1808 return; 1809 } 1810 1811 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1812 if (!tgt) { 1813 SPDK_ERRLOG("Unable to find a target object.\n"); 1814 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1815 "Unable to find a target."); 1816 nvmf_rpc_host_ctx_free(ctx); 1817 free(ctx); 1818 return; 1819 } 1820 1821 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1822 if (!subsystem) { 1823 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1824 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1825 nvmf_rpc_host_ctx_free(ctx); 1826 free(ctx); 1827 return; 1828 } 1829 1830 rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host); 1831 if (rc != 0) { 1832 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1833 nvmf_rpc_host_ctx_free(ctx); 1834 free(ctx); 1835 return; 1836 } 1837 1838 rc = spdk_nvmf_subsystem_disconnect_host(subsystem, ctx->host, 1839 rpc_nvmf_subsystem_remove_host_done, 1840 ctx); 1841 if (rc != 0) { 1842 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1843 nvmf_rpc_host_ctx_free(ctx); 1844 free(ctx); 1845 return; 1846 } 1847 } 1848 SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", rpc_nvmf_subsystem_remove_host, 1849 SPDK_RPC_RUNTIME) 1850 1851 1852 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = { 1853 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1854 {"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool}, 1855 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1856 }; 1857 1858 static void 1859 rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request, 1860 const struct spdk_json_val *params) 1861 { 1862 struct nvmf_rpc_host_ctx ctx = {}; 1863 struct spdk_nvmf_subsystem *subsystem; 1864 struct spdk_nvmf_tgt *tgt; 1865 int rc; 1866 1867 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder, 1868 SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder), 1869 &ctx)) { 1870 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1871 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1872 nvmf_rpc_host_ctx_free(&ctx); 1873 return; 1874 } 1875 1876 tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1877 if (!tgt) { 1878 SPDK_ERRLOG("Unable to find a target object.\n"); 1879 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1880 "Unable to find a target."); 1881 nvmf_rpc_host_ctx_free(&ctx); 1882 return; 1883 } 1884 1885 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 1886 if (!subsystem) { 1887 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn); 1888 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1889 nvmf_rpc_host_ctx_free(&ctx); 1890 return; 1891 } 1892 1893 rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx.allow_any_host); 1894 if (rc != 0) { 1895 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1896 nvmf_rpc_host_ctx_free(&ctx); 1897 return; 1898 } 1899 1900 spdk_jsonrpc_send_bool_response(request, true); 1901 nvmf_rpc_host_ctx_free(&ctx); 1902 } 1903 SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", rpc_nvmf_subsystem_allow_any_host, 1904 SPDK_RPC_RUNTIME) 1905 1906 struct nvmf_rpc_target_ctx { 1907 char *name; 1908 uint32_t max_subsystems; 1909 char *discovery_filter; 1910 }; 1911 1912 static int 1913 decode_discovery_filter(const struct spdk_json_val *val, void *out) 1914 { 1915 enum spdk_nvmf_tgt_discovery_filter *_filter = (enum spdk_nvmf_tgt_discovery_filter *)out; 1916 enum spdk_nvmf_tgt_discovery_filter filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY; 1917 char *tokens = spdk_json_strdup(val); 1918 char *tok; 1919 int rc = -EINVAL; 1920 bool all_specified = false; 1921 1922 if (!tokens) { 1923 return -ENOMEM; 1924 } 1925 1926 tok = strtok(tokens, ","); 1927 while (tok) { 1928 if (strncmp(tok, "match_any", 9) == 0) { 1929 if (filter != SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY) { 1930 goto out; 1931 } 1932 filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY; 1933 all_specified = true; 1934 } else { 1935 if (all_specified) { 1936 goto out; 1937 } 1938 if (strncmp(tok, "transport", 9) == 0) { 1939 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE; 1940 } else if (strncmp(tok, "address", 7) == 0) { 1941 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS; 1942 } else if (strncmp(tok, "svcid", 5) == 0) { 1943 filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID; 1944 } else { 1945 SPDK_ERRLOG("Invalid value %s\n", tok); 1946 goto out; 1947 } 1948 } 1949 1950 tok = strtok(NULL, ","); 1951 } 1952 1953 rc = 0; 1954 *_filter = filter; 1955 1956 out: 1957 free(tokens); 1958 1959 return rc; 1960 } 1961 1962 static const struct spdk_json_object_decoder nvmf_rpc_create_target_decoder[] = { 1963 {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 1964 {"max_subsystems", offsetof(struct nvmf_rpc_target_ctx, max_subsystems), spdk_json_decode_uint32, true}, 1965 {"discovery_filter", offsetof(struct nvmf_rpc_target_ctx, discovery_filter), decode_discovery_filter, true} 1966 }; 1967 1968 static void 1969 rpc_nvmf_create_target(struct spdk_jsonrpc_request *request, 1970 const struct spdk_json_val *params) 1971 { 1972 struct spdk_nvmf_target_opts opts; 1973 struct nvmf_rpc_target_ctx ctx = {0}; 1974 struct spdk_nvmf_tgt *tgt; 1975 struct spdk_json_write_ctx *w; 1976 1977 /* Decode parameters the first time to get the transport type */ 1978 if (spdk_json_decode_object(params, nvmf_rpc_create_target_decoder, 1979 SPDK_COUNTOF(nvmf_rpc_create_target_decoder), 1980 &ctx)) { 1981 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1982 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1983 goto out; 1984 } 1985 1986 snprintf(opts.name, NVMF_TGT_NAME_MAX_LENGTH, "%s", ctx.name); 1987 opts.max_subsystems = ctx.max_subsystems; 1988 1989 if (spdk_nvmf_get_tgt(opts.name) != NULL) { 1990 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1991 "Target already exists."); 1992 goto out; 1993 } 1994 1995 tgt = spdk_nvmf_tgt_create(&opts); 1996 1997 if (tgt == NULL) { 1998 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1999 "Unable to create the requested target."); 2000 goto out; 2001 } 2002 2003 w = spdk_jsonrpc_begin_result(request); 2004 spdk_json_write_string(w, spdk_nvmf_tgt_get_name(tgt)); 2005 spdk_jsonrpc_end_result(request, w); 2006 out: 2007 free(ctx.name); 2008 free(ctx.discovery_filter); 2009 } 2010 /* private */ SPDK_RPC_REGISTER("nvmf_create_target", rpc_nvmf_create_target, SPDK_RPC_RUNTIME); 2011 2012 static const struct spdk_json_object_decoder nvmf_rpc_destroy_target_decoder[] = { 2013 {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 2014 }; 2015 2016 static void 2017 nvmf_rpc_destroy_target_done(void *ctx, int status) 2018 { 2019 struct spdk_jsonrpc_request *request = ctx; 2020 2021 spdk_jsonrpc_send_bool_response(request, true); 2022 } 2023 2024 static void 2025 rpc_nvmf_delete_target(struct spdk_jsonrpc_request *request, 2026 const struct spdk_json_val *params) 2027 { 2028 struct nvmf_rpc_target_ctx ctx = {0}; 2029 struct spdk_nvmf_tgt *tgt; 2030 2031 /* Decode parameters the first time to get the transport type */ 2032 if (spdk_json_decode_object(params, nvmf_rpc_destroy_target_decoder, 2033 SPDK_COUNTOF(nvmf_rpc_destroy_target_decoder), 2034 &ctx)) { 2035 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2036 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2037 free(ctx.name); 2038 return; 2039 } 2040 2041 tgt = spdk_nvmf_get_tgt(ctx.name); 2042 2043 if (tgt == NULL) { 2044 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2045 "The specified target doesn't exist, cannot delete it."); 2046 free(ctx.name); 2047 return; 2048 } 2049 2050 spdk_nvmf_tgt_destroy(tgt, nvmf_rpc_destroy_target_done, request); 2051 free(ctx.name); 2052 } 2053 /* private */ SPDK_RPC_REGISTER("nvmf_delete_target", rpc_nvmf_delete_target, SPDK_RPC_RUNTIME); 2054 2055 static void 2056 rpc_nvmf_get_targets(struct spdk_jsonrpc_request *request, 2057 const struct spdk_json_val *params) 2058 { 2059 struct spdk_json_write_ctx *w; 2060 struct spdk_nvmf_tgt *tgt; 2061 const char *name; 2062 2063 if (params != NULL) { 2064 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2065 "nvmf_get_targets has no parameters."); 2066 return; 2067 } 2068 2069 w = spdk_jsonrpc_begin_result(request); 2070 spdk_json_write_array_begin(w); 2071 2072 tgt = spdk_nvmf_get_first_tgt(); 2073 2074 while (tgt != NULL) { 2075 name = spdk_nvmf_tgt_get_name(tgt); 2076 spdk_json_write_string(w, name); 2077 tgt = spdk_nvmf_get_next_tgt(tgt); 2078 } 2079 2080 spdk_json_write_array_end(w); 2081 spdk_jsonrpc_end_result(request, w); 2082 } 2083 /* private */ SPDK_RPC_REGISTER("nvmf_get_targets", rpc_nvmf_get_targets, SPDK_RPC_RUNTIME); 2084 2085 struct nvmf_rpc_create_transport_ctx { 2086 char *trtype; 2087 char *tgt_name; 2088 struct spdk_nvmf_transport_opts opts; 2089 struct spdk_jsonrpc_request *request; 2090 struct spdk_nvmf_transport *transport; 2091 int status; 2092 }; 2093 2094 /** 2095 * `max_qpairs_per_ctrlr` represents both admin and IO qpairs, that confuses 2096 * users when they configure a transport using RPC. So it was decided to 2097 * deprecate `max_qpairs_per_ctrlr` RPC parameter and use `max_io_qpairs_per_ctrlr` 2098 * But internal logic remains unchanged and SPDK expects that 2099 * spdk_nvmf_transport_opts::max_qpairs_per_ctrlr includes an admin qpair. 2100 * This function parses the number of IO qpairs and adds +1 for admin qpair. 2101 */ 2102 static int 2103 nvmf_rpc_decode_max_io_qpairs(const struct spdk_json_val *val, void *out) 2104 { 2105 uint16_t *i = out; 2106 int rc; 2107 2108 rc = spdk_json_number_to_uint16(val, i); 2109 if (rc == 0) { 2110 (*i)++; 2111 } 2112 2113 return rc; 2114 } 2115 2116 static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = { 2117 { "trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string}, 2118 { 2119 "max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth), 2120 spdk_json_decode_uint16, true 2121 }, 2122 { 2123 "max_io_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr), 2124 nvmf_rpc_decode_max_io_qpairs, true 2125 }, 2126 { 2127 "in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size), 2128 spdk_json_decode_uint32, true 2129 }, 2130 { 2131 "max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size), 2132 spdk_json_decode_uint32, true 2133 }, 2134 { 2135 "io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size), 2136 spdk_json_decode_uint32, true 2137 }, 2138 { 2139 "max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth), 2140 spdk_json_decode_uint32, true 2141 }, 2142 { 2143 "num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers), 2144 spdk_json_decode_uint32, true 2145 }, 2146 { 2147 "buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size), 2148 spdk_json_decode_uint32, true 2149 }, 2150 { 2151 "dif_insert_or_strip", offsetof(struct nvmf_rpc_create_transport_ctx, opts.dif_insert_or_strip), 2152 spdk_json_decode_bool, true 2153 }, 2154 { 2155 "abort_timeout_sec", offsetof(struct nvmf_rpc_create_transport_ctx, opts.abort_timeout_sec), 2156 spdk_json_decode_uint32, true 2157 }, 2158 { 2159 "zcopy", offsetof(struct nvmf_rpc_create_transport_ctx, opts.zcopy), 2160 spdk_json_decode_bool, true 2161 }, 2162 { 2163 "tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name), 2164 spdk_json_decode_string, true 2165 }, 2166 { 2167 "acceptor_poll_rate", offsetof(struct nvmf_rpc_create_transport_ctx, opts.acceptor_poll_rate), 2168 spdk_json_decode_uint32, true 2169 }, 2170 }; 2171 2172 static void 2173 nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx) 2174 { 2175 free(ctx->trtype); 2176 free(ctx->tgt_name); 2177 free(ctx); 2178 } 2179 2180 static void 2181 nvmf_rpc_transport_destroy_done_cb(void *cb_arg) 2182 { 2183 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2184 2185 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2186 "Failed to add transport to tgt.(%d)", ctx->status); 2187 nvmf_rpc_create_transport_ctx_free(ctx); 2188 } 2189 2190 static void 2191 nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status) 2192 { 2193 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2194 2195 if (status) { 2196 SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status); 2197 ctx->status = status; 2198 spdk_nvmf_transport_destroy(ctx->transport, nvmf_rpc_transport_destroy_done_cb, ctx); 2199 return; 2200 } 2201 2202 spdk_jsonrpc_send_bool_response(ctx->request, true); 2203 nvmf_rpc_create_transport_ctx_free(ctx); 2204 } 2205 2206 static void 2207 nvmf_rpc_create_transport_done(void *cb_arg, struct spdk_nvmf_transport *transport) 2208 { 2209 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2210 2211 if (!transport) { 2212 SPDK_ERRLOG("Failed to create transport.\n"); 2213 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2214 "Failed to create transport."); 2215 nvmf_rpc_create_transport_ctx_free(ctx); 2216 return; 2217 } 2218 2219 ctx->transport = transport; 2220 2221 spdk_nvmf_tgt_add_transport(spdk_nvmf_get_tgt(ctx->tgt_name), transport, 2222 nvmf_rpc_tgt_add_transport_done, ctx); 2223 } 2224 2225 static void 2226 rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request, 2227 const struct spdk_json_val *params) 2228 { 2229 struct nvmf_rpc_create_transport_ctx *ctx; 2230 struct spdk_nvmf_tgt *tgt; 2231 int rc; 2232 2233 ctx = calloc(1, sizeof(*ctx)); 2234 if (!ctx) { 2235 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 2236 return; 2237 } 2238 2239 /* Decode parameters the first time to get the transport type */ 2240 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder, 2241 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 2242 ctx)) { 2243 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 2244 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2245 nvmf_rpc_create_transport_ctx_free(ctx); 2246 return; 2247 } 2248 2249 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2250 if (!tgt) { 2251 SPDK_ERRLOG("Unable to find a target object.\n"); 2252 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2253 "Unable to find a target."); 2254 nvmf_rpc_create_transport_ctx_free(ctx); 2255 return; 2256 } 2257 2258 /* Initialize all the transport options (based on transport type) and decode the 2259 * parameters again to update any options passed in rpc create transport call. 2260 */ 2261 if (!spdk_nvmf_transport_opts_init(ctx->trtype, &ctx->opts, sizeof(ctx->opts))) { 2262 /* This can happen if user specifies PCIE transport type which isn't valid for 2263 * NVMe-oF. 2264 */ 2265 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype); 2266 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2267 "Invalid transport type '%s'", ctx->trtype); 2268 nvmf_rpc_create_transport_ctx_free(ctx); 2269 return; 2270 } 2271 2272 if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder, 2273 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 2274 ctx)) { 2275 SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 2276 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2277 nvmf_rpc_create_transport_ctx_free(ctx); 2278 return; 2279 } 2280 2281 if (spdk_nvmf_tgt_get_transport(tgt, ctx->trtype)) { 2282 SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype); 2283 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2284 "Transport type '%s' already exists", ctx->trtype); 2285 nvmf_rpc_create_transport_ctx_free(ctx); 2286 return; 2287 } 2288 2289 /* Transport can parse additional params themselves */ 2290 ctx->opts.transport_specific = params; 2291 ctx->request = request; 2292 2293 rc = spdk_nvmf_transport_create_async(ctx->trtype, &ctx->opts, nvmf_rpc_create_transport_done, ctx); 2294 if (rc) { 2295 SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype); 2296 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2297 "Transport type '%s' create failed", ctx->trtype); 2298 nvmf_rpc_create_transport_ctx_free(ctx); 2299 } 2300 } 2301 SPDK_RPC_REGISTER("nvmf_create_transport", rpc_nvmf_create_transport, SPDK_RPC_RUNTIME) 2302 2303 struct rpc_get_transport { 2304 char *trtype; 2305 char *tgt_name; 2306 }; 2307 2308 static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = { 2309 {"trtype", offsetof(struct rpc_get_transport, trtype), spdk_json_decode_string, true}, 2310 {"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true}, 2311 }; 2312 2313 static void 2314 rpc_nvmf_get_transports(struct spdk_jsonrpc_request *request, 2315 const struct spdk_json_val *params) 2316 { 2317 struct rpc_get_transport req = { 0 }; 2318 struct spdk_json_write_ctx *w; 2319 struct spdk_nvmf_transport *transport = NULL; 2320 struct spdk_nvmf_tgt *tgt; 2321 2322 if (params) { 2323 if (spdk_json_decode_object(params, rpc_get_transport_decoders, 2324 SPDK_COUNTOF(rpc_get_transport_decoders), 2325 &req)) { 2326 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2327 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2328 return; 2329 } 2330 } 2331 2332 tgt = spdk_nvmf_get_tgt(req.tgt_name); 2333 if (!tgt) { 2334 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2335 "Unable to find a target."); 2336 free(req.trtype); 2337 free(req.tgt_name); 2338 return; 2339 } 2340 2341 if (req.trtype) { 2342 transport = spdk_nvmf_tgt_get_transport(tgt, req.trtype); 2343 if (transport == NULL) { 2344 SPDK_ERRLOG("transport '%s' does not exist\n", req.trtype); 2345 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 2346 free(req.trtype); 2347 free(req.tgt_name); 2348 return; 2349 } 2350 } 2351 2352 w = spdk_jsonrpc_begin_result(request); 2353 spdk_json_write_array_begin(w); 2354 2355 if (transport) { 2356 nvmf_transport_dump_opts(transport, w, false); 2357 } else { 2358 for (transport = spdk_nvmf_transport_get_first(tgt); transport != NULL; 2359 transport = spdk_nvmf_transport_get_next(transport)) { 2360 nvmf_transport_dump_opts(transport, w, false); 2361 } 2362 } 2363 2364 spdk_json_write_array_end(w); 2365 spdk_jsonrpc_end_result(request, w); 2366 free(req.trtype); 2367 free(req.tgt_name); 2368 } 2369 SPDK_RPC_REGISTER("nvmf_get_transports", rpc_nvmf_get_transports, SPDK_RPC_RUNTIME) 2370 2371 struct rpc_nvmf_get_stats_ctx { 2372 char *tgt_name; 2373 struct spdk_nvmf_tgt *tgt; 2374 struct spdk_jsonrpc_request *request; 2375 struct spdk_json_write_ctx *w; 2376 }; 2377 2378 static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = { 2379 {"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true}, 2380 }; 2381 2382 static void 2383 free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx) 2384 { 2385 free(ctx->tgt_name); 2386 free(ctx); 2387 } 2388 2389 static void 2390 rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status) 2391 { 2392 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2393 2394 spdk_json_write_array_end(ctx->w); 2395 spdk_json_write_object_end(ctx->w); 2396 spdk_jsonrpc_end_result(ctx->request, ctx->w); 2397 free_get_stats_ctx(ctx); 2398 } 2399 2400 static void 2401 _rpc_nvmf_get_stats(struct spdk_io_channel_iter *i) 2402 { 2403 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2404 struct spdk_io_channel *ch; 2405 struct spdk_nvmf_poll_group *group; 2406 2407 ch = spdk_get_io_channel(ctx->tgt); 2408 group = spdk_io_channel_get_ctx(ch); 2409 2410 spdk_nvmf_poll_group_dump_stat(group, ctx->w); 2411 2412 spdk_put_io_channel(ch); 2413 spdk_for_each_channel_continue(i, 0); 2414 } 2415 2416 2417 static void 2418 rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request, 2419 const struct spdk_json_val *params) 2420 { 2421 struct rpc_nvmf_get_stats_ctx *ctx; 2422 2423 ctx = calloc(1, sizeof(*ctx)); 2424 if (!ctx) { 2425 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2426 "Memory allocation error"); 2427 return; 2428 } 2429 ctx->request = request; 2430 2431 if (params) { 2432 if (spdk_json_decode_object(params, rpc_get_stats_decoders, 2433 SPDK_COUNTOF(rpc_get_stats_decoders), 2434 ctx)) { 2435 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2436 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2437 free_get_stats_ctx(ctx); 2438 return; 2439 } 2440 } 2441 2442 ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2443 if (!ctx->tgt) { 2444 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2445 "Unable to find a target."); 2446 free_get_stats_ctx(ctx); 2447 return; 2448 } 2449 2450 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 2451 spdk_json_write_object_begin(ctx->w); 2452 spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz()); 2453 spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 2454 2455 spdk_for_each_channel(ctx->tgt, 2456 _rpc_nvmf_get_stats, 2457 ctx, 2458 rpc_nvmf_get_stats_done); 2459 } 2460 2461 SPDK_RPC_REGISTER("nvmf_get_stats", rpc_nvmf_get_stats, SPDK_RPC_RUNTIME) 2462 2463 static void 2464 dump_nvmf_ctrlr(struct spdk_json_write_ctx *w, struct spdk_nvmf_ctrlr *ctrlr) 2465 { 2466 uint32_t count; 2467 2468 spdk_json_write_object_begin(w); 2469 2470 spdk_json_write_named_uint32(w, "cntlid", ctrlr->cntlid); 2471 spdk_json_write_named_string(w, "hostnqn", ctrlr->hostnqn); 2472 spdk_json_write_named_uuid(w, "hostid", &ctrlr->hostid); 2473 2474 count = spdk_bit_array_count_set(ctrlr->qpair_mask); 2475 spdk_json_write_named_uint32(w, "num_io_qpairs", count); 2476 2477 spdk_json_write_object_end(w); 2478 } 2479 2480 static const char * 2481 nvmf_qpair_state_str(enum spdk_nvmf_qpair_state state) 2482 { 2483 switch (state) { 2484 case SPDK_NVMF_QPAIR_UNINITIALIZED: 2485 return "uninitialized"; 2486 case SPDK_NVMF_QPAIR_ACTIVE: 2487 return "active"; 2488 case SPDK_NVMF_QPAIR_DEACTIVATING: 2489 return "deactivating"; 2490 case SPDK_NVMF_QPAIR_ERROR: 2491 return "error"; 2492 default: 2493 return NULL; 2494 } 2495 } 2496 2497 static void 2498 dump_nvmf_qpair(struct spdk_json_write_ctx *w, struct spdk_nvmf_qpair *qpair) 2499 { 2500 struct spdk_nvme_transport_id trid = {}; 2501 2502 spdk_json_write_object_begin(w); 2503 2504 spdk_json_write_named_uint32(w, "cntlid", qpair->ctrlr->cntlid); 2505 spdk_json_write_named_uint32(w, "qid", qpair->qid); 2506 spdk_json_write_named_string(w, "state", nvmf_qpair_state_str(qpair->state)); 2507 2508 if (spdk_nvmf_qpair_get_listen_trid(qpair, &trid) == 0) { 2509 spdk_json_write_named_object_begin(w, "listen_address"); 2510 nvmf_transport_listen_dump_trid(&trid, w); 2511 spdk_json_write_object_end(w); 2512 if (qpair->transport->ops->listen_dump_opts) { 2513 qpair->transport->ops->listen_dump_opts(qpair->transport, &trid, w); 2514 } 2515 } 2516 2517 memset(&trid, 0, sizeof(trid)); 2518 if (spdk_nvmf_qpair_get_peer_trid(qpair, &trid) == 0) { 2519 spdk_json_write_named_object_begin(w, "peer_address"); 2520 nvmf_transport_listen_dump_trid(&trid, w); 2521 spdk_json_write_object_end(w); 2522 } 2523 2524 spdk_json_write_object_end(w); 2525 } 2526 2527 static const char * 2528 nvme_ana_state_str(enum spdk_nvme_ana_state ana_state) 2529 { 2530 switch (ana_state) { 2531 case SPDK_NVME_ANA_OPTIMIZED_STATE: 2532 return "optimized"; 2533 case SPDK_NVME_ANA_NON_OPTIMIZED_STATE: 2534 return "non_optimized"; 2535 case SPDK_NVME_ANA_INACCESSIBLE_STATE: 2536 return "inaccessible"; 2537 case SPDK_NVME_ANA_PERSISTENT_LOSS_STATE: 2538 return "persistent_loss"; 2539 case SPDK_NVME_ANA_CHANGE_STATE: 2540 return "change"; 2541 default: 2542 return NULL; 2543 } 2544 } 2545 2546 static void 2547 dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w, 2548 struct spdk_nvmf_subsystem_listener *listener) 2549 { 2550 const struct spdk_nvme_transport_id *trid = listener->trid; 2551 uint32_t i; 2552 2553 spdk_json_write_object_begin(w); 2554 2555 spdk_json_write_named_object_begin(w, "address"); 2556 nvmf_transport_listen_dump_trid(trid, w); 2557 spdk_json_write_object_end(w); 2558 2559 if (spdk_nvmf_subsystem_get_ana_reporting(listener->subsystem)) { 2560 spdk_json_write_named_array_begin(w, "ana_states"); 2561 for (i = 0; i < listener->subsystem->max_nsid; i++) { 2562 spdk_json_write_object_begin(w); 2563 spdk_json_write_named_uint32(w, "ana_group", i + 1); 2564 spdk_json_write_named_string(w, "ana_state", 2565 nvme_ana_state_str(listener->ana_state[i])); 2566 spdk_json_write_object_end(w); 2567 } 2568 spdk_json_write_array_end(w); 2569 } 2570 2571 spdk_json_write_object_end(w); 2572 } 2573 2574 struct rpc_subsystem_query_ctx { 2575 char *nqn; 2576 char *tgt_name; 2577 struct spdk_nvmf_subsystem *subsystem; 2578 struct spdk_jsonrpc_request *request; 2579 struct spdk_json_write_ctx *w; 2580 }; 2581 2582 static const struct spdk_json_object_decoder rpc_subsystem_query_decoders[] = { 2583 {"nqn", offsetof(struct rpc_subsystem_query_ctx, nqn), spdk_json_decode_string}, 2584 {"tgt_name", offsetof(struct rpc_subsystem_query_ctx, tgt_name), spdk_json_decode_string, true}, 2585 }; 2586 2587 static void 2588 free_rpc_subsystem_query_ctx(struct rpc_subsystem_query_ctx *ctx) 2589 { 2590 free(ctx->nqn); 2591 free(ctx->tgt_name); 2592 free(ctx); 2593 } 2594 2595 static void 2596 rpc_nvmf_get_controllers_paused(struct spdk_nvmf_subsystem *subsystem, 2597 void *cb_arg, int status) 2598 { 2599 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2600 struct spdk_json_write_ctx *w; 2601 struct spdk_nvmf_ctrlr *ctrlr; 2602 2603 w = spdk_jsonrpc_begin_result(ctx->request); 2604 2605 spdk_json_write_array_begin(w); 2606 TAILQ_FOREACH(ctrlr, &ctx->subsystem->ctrlrs, link) { 2607 dump_nvmf_ctrlr(w, ctrlr); 2608 } 2609 spdk_json_write_array_end(w); 2610 2611 spdk_jsonrpc_end_result(ctx->request, w); 2612 2613 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2614 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2615 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2616 } 2617 2618 free_rpc_subsystem_query_ctx(ctx); 2619 } 2620 2621 static void 2622 rpc_nvmf_get_qpairs_done(struct spdk_io_channel_iter *i, int status) 2623 { 2624 struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2625 2626 spdk_json_write_array_end(ctx->w); 2627 spdk_jsonrpc_end_result(ctx->request, ctx->w); 2628 2629 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2630 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2631 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2632 } 2633 2634 free_rpc_subsystem_query_ctx(ctx); 2635 } 2636 2637 static void 2638 rpc_nvmf_get_qpairs(struct spdk_io_channel_iter *i) 2639 { 2640 struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2641 struct spdk_io_channel *ch; 2642 struct spdk_nvmf_poll_group *group; 2643 struct spdk_nvmf_qpair *qpair; 2644 2645 ch = spdk_io_channel_iter_get_channel(i); 2646 group = spdk_io_channel_get_ctx(ch); 2647 2648 TAILQ_FOREACH(qpair, &group->qpairs, link) { 2649 if (qpair->ctrlr->subsys == ctx->subsystem) { 2650 dump_nvmf_qpair(ctx->w, qpair); 2651 } 2652 } 2653 2654 spdk_for_each_channel_continue(i, 0); 2655 } 2656 2657 static void 2658 rpc_nvmf_get_qpairs_paused(struct spdk_nvmf_subsystem *subsystem, 2659 void *cb_arg, int status) 2660 { 2661 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2662 2663 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 2664 2665 spdk_json_write_array_begin(ctx->w); 2666 2667 spdk_for_each_channel(ctx->subsystem->tgt, 2668 rpc_nvmf_get_qpairs, 2669 ctx, 2670 rpc_nvmf_get_qpairs_done); 2671 } 2672 2673 static void 2674 rpc_nvmf_get_listeners_paused(struct spdk_nvmf_subsystem *subsystem, 2675 void *cb_arg, int status) 2676 { 2677 struct rpc_subsystem_query_ctx *ctx = cb_arg; 2678 struct spdk_json_write_ctx *w; 2679 struct spdk_nvmf_subsystem_listener *listener; 2680 2681 w = spdk_jsonrpc_begin_result(ctx->request); 2682 2683 spdk_json_write_array_begin(w); 2684 2685 for (listener = spdk_nvmf_subsystem_get_first_listener(ctx->subsystem); 2686 listener != NULL; 2687 listener = spdk_nvmf_subsystem_get_next_listener(ctx->subsystem, listener)) { 2688 dump_nvmf_subsystem_listener(w, listener); 2689 } 2690 spdk_json_write_array_end(w); 2691 2692 spdk_jsonrpc_end_result(ctx->request, w); 2693 2694 if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 2695 SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 2696 /* FIXME: RPC should fail if resuming the subsystem failed. */ 2697 } 2698 2699 free_rpc_subsystem_query_ctx(ctx); 2700 } 2701 2702 static void 2703 _rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request, 2704 const struct spdk_json_val *params, 2705 spdk_nvmf_subsystem_state_change_done cb_fn) 2706 { 2707 struct rpc_subsystem_query_ctx *ctx; 2708 struct spdk_nvmf_subsystem *subsystem; 2709 struct spdk_nvmf_tgt *tgt; 2710 2711 ctx = calloc(1, sizeof(*ctx)); 2712 if (!ctx) { 2713 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2714 "Out of memory"); 2715 return; 2716 } 2717 2718 ctx->request = request; 2719 2720 if (spdk_json_decode_object(params, rpc_subsystem_query_decoders, 2721 SPDK_COUNTOF(rpc_subsystem_query_decoders), 2722 ctx)) { 2723 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2724 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2725 "Invalid parameters"); 2726 free_rpc_subsystem_query_ctx(ctx); 2727 return; 2728 } 2729 2730 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2731 if (!tgt) { 2732 SPDK_ERRLOG("Unable to find a target object.\n"); 2733 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2734 "Unable to find a target"); 2735 free_rpc_subsystem_query_ctx(ctx); 2736 return; 2737 } 2738 2739 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 2740 if (!subsystem) { 2741 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 2742 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2743 "Invalid parameters"); 2744 free_rpc_subsystem_query_ctx(ctx); 2745 return; 2746 } 2747 2748 ctx->subsystem = subsystem; 2749 2750 if (spdk_nvmf_subsystem_pause(subsystem, 0, cb_fn, ctx)) { 2751 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2752 "Internal error"); 2753 free_rpc_subsystem_query_ctx(ctx); 2754 return; 2755 } 2756 } 2757 2758 static void 2759 rpc_nvmf_subsystem_get_controllers(struct spdk_jsonrpc_request *request, 2760 const struct spdk_json_val *params) 2761 { 2762 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_controllers_paused); 2763 } 2764 SPDK_RPC_REGISTER("nvmf_subsystem_get_controllers", rpc_nvmf_subsystem_get_controllers, 2765 SPDK_RPC_RUNTIME); 2766 2767 static void 2768 rpc_nvmf_subsystem_get_qpairs(struct spdk_jsonrpc_request *request, 2769 const struct spdk_json_val *params) 2770 { 2771 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused); 2772 } 2773 SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME); 2774 2775 static void 2776 rpc_nvmf_subsystem_get_listeners(struct spdk_jsonrpc_request *request, 2777 const struct spdk_json_val *params) 2778 { 2779 _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_listeners_paused); 2780 } 2781 SPDK_RPC_REGISTER("nvmf_subsystem_get_listeners", rpc_nvmf_subsystem_get_listeners, 2782 SPDK_RPC_RUNTIME); 2783