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