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