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