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