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