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