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