1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2018-2019 Mellanox Technologies LTD. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/bdev.h" 35 #include "spdk/log.h" 36 #include "spdk/rpc.h" 37 #include "spdk/env.h" 38 #include "spdk/nvme.h" 39 #include "spdk/nvmf.h" 40 #include "spdk/string.h" 41 #include "spdk/util.h" 42 43 #include "spdk_internal/event.h" 44 #include "spdk_internal/log.h" 45 46 static int 47 json_write_hex_str(struct spdk_json_write_ctx *w, const void *data, size_t size) 48 { 49 static const char hex_char[16] = "0123456789ABCDEF"; 50 const uint8_t *buf = data; 51 char *str, *out; 52 int rc; 53 54 str = malloc(size * 2 + 1); 55 if (str == NULL) { 56 return -1; 57 } 58 59 out = str; 60 while (size--) { 61 unsigned byte = *buf++; 62 63 out[0] = hex_char[(byte >> 4) & 0xF]; 64 out[1] = hex_char[byte & 0xF]; 65 66 out += 2; 67 } 68 *out = '\0'; 69 70 rc = spdk_json_write_string(w, str); 71 free(str); 72 73 return rc; 74 } 75 76 static int 77 hex_nybble_to_num(char c) 78 { 79 if (c >= '0' && c <= '9') { 80 return c - '0'; 81 } 82 83 if (c >= 'a' && c <= 'f') { 84 return c - 'a' + 0xA; 85 } 86 87 if (c >= 'A' && c <= 'F') { 88 return c - 'A' + 0xA; 89 } 90 91 return -1; 92 } 93 94 static int 95 hex_byte_to_num(const char *str) 96 { 97 int hi, lo; 98 99 hi = hex_nybble_to_num(str[0]); 100 if (hi < 0) { 101 return hi; 102 } 103 104 lo = hex_nybble_to_num(str[1]); 105 if (lo < 0) { 106 return lo; 107 } 108 109 return hi * 16 + lo; 110 } 111 112 static int 113 decode_hex_string_be(const char *str, uint8_t *out, size_t size) 114 { 115 size_t i; 116 117 /* Decode a string in "ABCDEF012345" format to its binary representation */ 118 for (i = 0; i < size; i++) { 119 int num = hex_byte_to_num(str); 120 121 if (num < 0) { 122 /* Invalid hex byte or end of string */ 123 return -1; 124 } 125 126 out[i] = (uint8_t)num; 127 str += 2; 128 } 129 130 if (i != size || *str != '\0') { 131 /* Length mismatch */ 132 return -1; 133 } 134 135 return 0; 136 } 137 138 static int 139 decode_ns_nguid(const struct spdk_json_val *val, void *out) 140 { 141 char *str = NULL; 142 int rc; 143 144 rc = spdk_json_decode_string(val, &str); 145 if (rc == 0) { 146 /* 16-byte NGUID */ 147 rc = decode_hex_string_be(str, out, 16); 148 } 149 150 free(str); 151 return rc; 152 } 153 154 static int 155 decode_ns_eui64(const struct spdk_json_val *val, void *out) 156 { 157 char *str = NULL; 158 int rc; 159 160 rc = spdk_json_decode_string(val, &str); 161 if (rc == 0) { 162 /* 8-byte EUI-64 */ 163 rc = decode_hex_string_be(str, out, 8); 164 } 165 166 free(str); 167 return rc; 168 } 169 170 static int 171 decode_ns_uuid(const struct spdk_json_val *val, void *out) 172 { 173 char *str = NULL; 174 int rc; 175 176 rc = spdk_json_decode_string(val, &str); 177 if (rc == 0) { 178 rc = spdk_uuid_parse(out, str); 179 } 180 181 free(str); 182 return rc; 183 } 184 185 struct rpc_get_subsystem { 186 char *tgt_name; 187 }; 188 189 static const struct spdk_json_object_decoder rpc_get_subsystem_decoders[] = { 190 {"tgt_name", offsetof(struct rpc_get_subsystem, tgt_name), spdk_json_decode_string, true}, 191 }; 192 193 static void 194 dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *subsystem) 195 { 196 struct spdk_nvmf_host *host; 197 struct spdk_nvmf_listener *listener; 198 199 spdk_json_write_object_begin(w); 200 201 spdk_json_write_named_string(w, "nqn", spdk_nvmf_subsystem_get_nqn(subsystem)); 202 spdk_json_write_name(w, "subtype"); 203 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) { 204 spdk_json_write_string(w, "NVMe"); 205 } else { 206 spdk_json_write_string(w, "Discovery"); 207 } 208 209 spdk_json_write_named_array_begin(w, "listen_addresses"); 210 211 for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL; 212 listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) { 213 const struct spdk_nvme_transport_id *trid; 214 const char *trtype; 215 const char *adrfam; 216 217 trid = spdk_nvmf_listener_get_trid(listener); 218 219 spdk_json_write_object_begin(w); 220 trtype = spdk_nvme_transport_id_trtype_str(trid->trtype); 221 if (trtype == NULL) { 222 trtype = "unknown"; 223 } 224 adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam); 225 if (adrfam == NULL) { 226 adrfam = "unknown"; 227 } 228 /* NOTE: "transport" is kept for compatibility; new code should use "trtype" */ 229 spdk_json_write_named_string(w, "transport", trtype); 230 spdk_json_write_named_string(w, "trtype", trtype); 231 spdk_json_write_named_string(w, "adrfam", adrfam); 232 spdk_json_write_named_string(w, "traddr", trid->traddr); 233 spdk_json_write_named_string(w, "trsvcid", trid->trsvcid); 234 spdk_json_write_object_end(w); 235 } 236 spdk_json_write_array_end(w); 237 238 spdk_json_write_named_bool(w, "allow_any_host", 239 spdk_nvmf_subsystem_get_allow_any_host(subsystem)); 240 241 spdk_json_write_named_array_begin(w, "hosts"); 242 243 for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL; 244 host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) { 245 spdk_json_write_object_begin(w); 246 spdk_json_write_named_string(w, "nqn", spdk_nvmf_host_get_nqn(host)); 247 spdk_json_write_object_end(w); 248 } 249 spdk_json_write_array_end(w); 250 251 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) { 252 struct spdk_nvmf_ns *ns; 253 struct spdk_nvmf_ns_opts ns_opts; 254 uint32_t max_namespaces; 255 256 spdk_json_write_named_string(w, "serial_number", spdk_nvmf_subsystem_get_sn(subsystem)); 257 258 spdk_json_write_named_string(w, "model_number", spdk_nvmf_subsystem_get_mn(subsystem)); 259 260 max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem); 261 if (max_namespaces != 0) { 262 spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces); 263 } 264 265 spdk_json_write_named_array_begin(w, "namespaces"); 266 for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL; 267 ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) { 268 spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts)); 269 spdk_json_write_object_begin(w); 270 spdk_json_write_named_int32(w, "nsid", spdk_nvmf_ns_get_id(ns)); 271 spdk_json_write_named_string(w, "bdev_name", 272 spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); 273 /* NOTE: "name" is kept for compatibility only - new code should use bdev_name. */ 274 spdk_json_write_named_string(w, "name", 275 spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); 276 277 if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) { 278 spdk_json_write_name(w, "nguid"); 279 json_write_hex_str(w, ns_opts.nguid, sizeof(ns_opts.nguid)); 280 } 281 282 if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) { 283 spdk_json_write_name(w, "eui64"); 284 json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64)); 285 } 286 287 if (!spdk_mem_all_zero(&ns_opts.uuid, sizeof(ns_opts.uuid))) { 288 char uuid_str[SPDK_UUID_STRING_LEN]; 289 290 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid); 291 spdk_json_write_named_string(w, "uuid", uuid_str); 292 } 293 294 spdk_json_write_object_end(w); 295 } 296 spdk_json_write_array_end(w); 297 } 298 spdk_json_write_object_end(w); 299 } 300 301 static void 302 spdk_rpc_get_nvmf_subsystems(struct spdk_jsonrpc_request *request, 303 const struct spdk_json_val *params) 304 { 305 struct rpc_get_subsystem req = { 0 }; 306 struct spdk_json_write_ctx *w; 307 struct spdk_nvmf_subsystem *subsystem; 308 struct spdk_nvmf_tgt *tgt; 309 310 if (params) { 311 if (spdk_json_decode_object(params, rpc_get_subsystem_decoders, 312 SPDK_COUNTOF(rpc_get_subsystem_decoders), 313 &req)) { 314 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 315 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 316 return; 317 } 318 } 319 320 tgt = spdk_nvmf_get_tgt(req.tgt_name); 321 if (!tgt) { 322 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 323 "Unable to find a target."); 324 free(req.tgt_name); 325 return; 326 } 327 328 w = spdk_jsonrpc_begin_result(request); 329 spdk_json_write_array_begin(w); 330 subsystem = spdk_nvmf_subsystem_get_first(tgt); 331 while (subsystem) { 332 dump_nvmf_subsystem(w, subsystem); 333 subsystem = spdk_nvmf_subsystem_get_next(subsystem); 334 } 335 spdk_json_write_array_end(w); 336 spdk_jsonrpc_end_result(request, w); 337 free(req.tgt_name); 338 } 339 SPDK_RPC_REGISTER("get_nvmf_subsystems", spdk_rpc_get_nvmf_subsystems, SPDK_RPC_RUNTIME) 340 341 struct rpc_subsystem_create { 342 char *nqn; 343 char *serial_number; 344 char *model_number; 345 char *tgt_name; 346 uint32_t max_namespaces; 347 bool allow_any_host; 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 }; 358 359 static void 360 spdk_rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem, 361 void *cb_arg, int status) 362 { 363 struct spdk_jsonrpc_request *request = cb_arg; 364 struct spdk_json_write_ctx *w; 365 366 w = spdk_jsonrpc_begin_result(request); 367 spdk_json_write_bool(w, true); 368 spdk_jsonrpc_end_result(request, w); 369 } 370 371 static void 372 spdk_rpc_nvmf_subsystem_create(struct spdk_jsonrpc_request *request, 373 const struct spdk_json_val *params) 374 { 375 struct rpc_subsystem_create *req; 376 struct spdk_nvmf_subsystem *subsystem; 377 struct spdk_nvmf_tgt *tgt; 378 379 req = calloc(1, sizeof(*req)); 380 if (!req) { 381 goto invalid; 382 } 383 384 if (spdk_json_decode_object(params, rpc_subsystem_create_decoders, 385 SPDK_COUNTOF(rpc_subsystem_create_decoders), 386 req)) { 387 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 388 goto invalid; 389 } 390 391 tgt = spdk_nvmf_get_tgt(req->tgt_name); 392 if (!tgt) { 393 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 394 "Unable to find a target."); 395 goto invalid_custom_response; 396 } 397 398 subsystem = spdk_nvmf_subsystem_create(tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME, 399 req->max_namespaces); 400 if (!subsystem) { 401 goto invalid; 402 } 403 404 if (req->serial_number) { 405 if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) { 406 SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number); 407 goto invalid; 408 } 409 } 410 411 if (req->model_number) { 412 if (spdk_nvmf_subsystem_set_mn(subsystem, req->model_number)) { 413 SPDK_ERRLOG("Subsystem %s: invalid model number '%s'\n", req->nqn, req->model_number); 414 goto invalid; 415 } 416 } 417 418 spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host); 419 420 free(req->nqn); 421 free(req->tgt_name); 422 free(req->serial_number); 423 free(req->model_number); 424 free(req); 425 426 spdk_nvmf_subsystem_start(subsystem, 427 spdk_rpc_nvmf_subsystem_started, 428 request); 429 430 return; 431 432 invalid: 433 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 434 invalid_custom_response: 435 if (req) { 436 free(req->nqn); 437 free(req->tgt_name); 438 free(req->serial_number); 439 free(req->model_number); 440 } 441 free(req); 442 } 443 SPDK_RPC_REGISTER("nvmf_subsystem_create", spdk_rpc_nvmf_subsystem_create, SPDK_RPC_RUNTIME) 444 445 struct rpc_delete_subsystem { 446 char *nqn; 447 char *tgt_name; 448 }; 449 450 static void 451 free_rpc_delete_subsystem(struct rpc_delete_subsystem *r) 452 { 453 free(r->nqn); 454 free(r->tgt_name); 455 } 456 457 static void 458 spdk_rpc_nvmf_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem, 459 void *cb_arg, int status) 460 { 461 struct spdk_jsonrpc_request *request = cb_arg; 462 struct spdk_json_write_ctx *w; 463 464 spdk_nvmf_subsystem_destroy(subsystem); 465 466 w = spdk_jsonrpc_begin_result(request); 467 spdk_json_write_bool(w, true); 468 spdk_jsonrpc_end_result(request, w); 469 } 470 471 static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = { 472 {"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string}, 473 {"tgt_name", offsetof(struct rpc_delete_subsystem, tgt_name), spdk_json_decode_string, true}, 474 }; 475 476 static void 477 spdk_rpc_delete_nvmf_subsystem(struct spdk_jsonrpc_request *request, 478 const struct spdk_json_val *params) 479 { 480 struct rpc_delete_subsystem req = { 0 }; 481 struct spdk_nvmf_subsystem *subsystem; 482 struct spdk_nvmf_tgt *tgt; 483 484 if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders, 485 SPDK_COUNTOF(rpc_delete_subsystem_decoders), 486 &req)) { 487 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 488 goto invalid; 489 } 490 491 if (req.nqn == NULL) { 492 SPDK_ERRLOG("missing name param\n"); 493 goto invalid; 494 } 495 496 tgt = spdk_nvmf_get_tgt(req.tgt_name); 497 if (!tgt) { 498 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 499 "Unable to find a target."); 500 goto invalid_custom_response; 501 } 502 503 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn); 504 if (!subsystem) { 505 goto invalid; 506 } 507 508 free_rpc_delete_subsystem(&req); 509 510 spdk_nvmf_subsystem_stop(subsystem, 511 spdk_rpc_nvmf_subsystem_stopped, 512 request); 513 514 return; 515 516 invalid: 517 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 518 invalid_custom_response: 519 free_rpc_delete_subsystem(&req); 520 } 521 SPDK_RPC_REGISTER("delete_nvmf_subsystem", spdk_rpc_delete_nvmf_subsystem, SPDK_RPC_RUNTIME) 522 523 struct rpc_listen_address { 524 char *transport; 525 char *adrfam; 526 char *traddr; 527 char *trsvcid; 528 }; 529 530 #define RPC_MAX_LISTEN_ADDRESSES 255 531 #define RPC_MAX_NAMESPACES 255 532 533 struct rpc_listen_addresses { 534 size_t num_listen_address; 535 struct rpc_listen_address addresses[RPC_MAX_LISTEN_ADDRESSES]; 536 }; 537 538 static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = { 539 /* NOTE: "transport" is kept for compatibility; new code should use "trtype" */ 540 {"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true}, 541 {"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true}, 542 {"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true}, 543 {"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string}, 544 {"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string}, 545 }; 546 547 static int 548 decode_rpc_listen_address(const struct spdk_json_val *val, void *out) 549 { 550 struct rpc_listen_address *req = (struct rpc_listen_address *)out; 551 if (spdk_json_decode_object(val, rpc_listen_address_decoders, 552 SPDK_COUNTOF(rpc_listen_address_decoders), 553 req)) { 554 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 555 return -1; 556 } 557 return 0; 558 } 559 560 static void 561 free_rpc_listen_address(struct rpc_listen_address *r) 562 { 563 free(r->transport); 564 free(r->adrfam); 565 free(r->traddr); 566 free(r->trsvcid); 567 } 568 569 enum nvmf_rpc_listen_op { 570 NVMF_RPC_LISTEN_ADD, 571 NVMF_RPC_LISTEN_REMOVE, 572 }; 573 574 struct nvmf_rpc_listener_ctx { 575 char *nqn; 576 char *tgt_name; 577 struct spdk_nvmf_tgt *tgt; 578 struct spdk_nvmf_subsystem *subsystem; 579 struct rpc_listen_address address; 580 581 struct spdk_jsonrpc_request *request; 582 struct spdk_nvme_transport_id trid; 583 enum nvmf_rpc_listen_op op; 584 bool response_sent; 585 }; 586 587 static const struct spdk_json_object_decoder nvmf_rpc_listener_decoder[] = { 588 {"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string}, 589 {"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address}, 590 {"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true}, 591 }; 592 593 static void 594 nvmf_rpc_listener_ctx_free(struct nvmf_rpc_listener_ctx *ctx) 595 { 596 free(ctx->nqn); 597 free(ctx->tgt_name); 598 free_rpc_listen_address(&ctx->address); 599 free(ctx); 600 } 601 602 static void 603 nvmf_rpc_listen_resumed(struct spdk_nvmf_subsystem *subsystem, 604 void *cb_arg, int status) 605 { 606 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 607 struct spdk_jsonrpc_request *request; 608 struct spdk_json_write_ctx *w; 609 610 request = ctx->request; 611 if (ctx->response_sent) { 612 /* If an error occurred, the response has already been sent. */ 613 nvmf_rpc_listener_ctx_free(ctx); 614 return; 615 } 616 617 nvmf_rpc_listener_ctx_free(ctx); 618 619 w = spdk_jsonrpc_begin_result(request); 620 spdk_json_write_bool(w, true); 621 spdk_jsonrpc_end_result(request, w); 622 } 623 624 static void 625 nvmf_rpc_tgt_listen(void *cb_arg, int status) 626 { 627 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 628 629 if (status) { 630 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 631 "Invalid parameters"); 632 ctx->response_sent = true; 633 } else { 634 if (spdk_nvmf_subsystem_add_listener(ctx->subsystem, &ctx->trid)) { 635 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 636 "Invalid parameters"); 637 ctx->response_sent = true; 638 } 639 } 640 641 if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) { 642 if (!ctx->response_sent) { 643 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 644 } 645 nvmf_rpc_listener_ctx_free(ctx); 646 /* Can't really do anything to recover here - subsystem will remain paused. */ 647 } 648 } 649 650 static void 651 nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem, 652 void *cb_arg, int status) 653 { 654 struct nvmf_rpc_listener_ctx *ctx = cb_arg; 655 656 if (ctx->op == NVMF_RPC_LISTEN_ADD) { 657 spdk_nvmf_tgt_listen(ctx->tgt, &ctx->trid, nvmf_rpc_tgt_listen, ctx); 658 return; 659 } else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) { 660 if (spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid)) { 661 SPDK_ERRLOG("Unable to remove listener.\n"); 662 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 663 "Invalid parameters"); 664 ctx->response_sent = true; 665 } 666 } else { 667 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 668 "Invalid parameters"); 669 ctx->response_sent = true; 670 } 671 672 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) { 673 if (!ctx->response_sent) { 674 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 675 } 676 nvmf_rpc_listener_ctx_free(ctx); 677 /* Can't really do anything to recover here - subsystem will remain paused. */ 678 } 679 } 680 681 static int 682 rpc_listen_address_to_trid(const struct rpc_listen_address *address, 683 struct spdk_nvme_transport_id *trid) 684 { 685 size_t len; 686 687 memset(trid, 0, sizeof(*trid)); 688 689 if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) { 690 SPDK_ERRLOG("Invalid transport type: %s\n", address->transport); 691 return -EINVAL; 692 } 693 694 if (address->adrfam) { 695 if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) { 696 SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam); 697 return -EINVAL; 698 } 699 } else { 700 trid->adrfam = SPDK_NVMF_ADRFAM_IPV4; 701 } 702 703 len = strlen(address->traddr); 704 if (len > sizeof(trid->traddr) - 1) { 705 SPDK_ERRLOG("Transport address longer than %zu characters: %s\n", 706 sizeof(trid->traddr) - 1, address->traddr); 707 return -EINVAL; 708 } 709 memcpy(trid->traddr, address->traddr, len + 1); 710 711 len = strlen(address->trsvcid); 712 if (len > sizeof(trid->trsvcid) - 1) { 713 SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n", 714 sizeof(trid->trsvcid) - 1, address->trsvcid); 715 return -EINVAL; 716 } 717 memcpy(trid->trsvcid, address->trsvcid, len + 1); 718 719 return 0; 720 } 721 722 static void 723 spdk_rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request, 724 const struct spdk_json_val *params) 725 { 726 struct nvmf_rpc_listener_ctx *ctx; 727 struct spdk_nvmf_subsystem *subsystem; 728 struct spdk_nvmf_tgt *tgt; 729 730 ctx = calloc(1, sizeof(*ctx)); 731 if (!ctx) { 732 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 733 return; 734 } 735 736 ctx->request = request; 737 738 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder, 739 SPDK_COUNTOF(nvmf_rpc_listener_decoder), 740 ctx)) { 741 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 742 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 743 nvmf_rpc_listener_ctx_free(ctx); 744 return; 745 } 746 747 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 748 if (!tgt) { 749 SPDK_ERRLOG("Unable to find a target object.\n"); 750 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 751 "Unable to find a target."); 752 nvmf_rpc_listener_ctx_free(ctx); 753 return; 754 } 755 ctx->tgt = tgt; 756 757 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 758 if (!subsystem) { 759 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 760 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 761 nvmf_rpc_listener_ctx_free(ctx); 762 return; 763 } 764 765 ctx->subsystem = subsystem; 766 767 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 768 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 769 "Invalid parameters"); 770 nvmf_rpc_listener_ctx_free(ctx); 771 return; 772 } 773 774 ctx->op = NVMF_RPC_LISTEN_ADD; 775 776 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) { 777 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 778 nvmf_rpc_listener_ctx_free(ctx); 779 return; 780 } 781 } 782 SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", spdk_rpc_nvmf_subsystem_add_listener, 783 SPDK_RPC_RUNTIME); 784 785 static void 786 spdk_rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request, 787 const struct spdk_json_val *params) 788 { 789 struct nvmf_rpc_listener_ctx *ctx; 790 struct spdk_nvmf_subsystem *subsystem; 791 struct spdk_nvmf_tgt *tgt; 792 793 ctx = calloc(1, sizeof(*ctx)); 794 if (!ctx) { 795 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 796 return; 797 } 798 799 ctx->request = request; 800 801 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder, 802 SPDK_COUNTOF(nvmf_rpc_listener_decoder), 803 ctx)) { 804 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 805 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 806 nvmf_rpc_listener_ctx_free(ctx); 807 return; 808 } 809 810 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 811 if (!tgt) { 812 SPDK_ERRLOG("Unable to find a target object.\n"); 813 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 814 "Unable to find a target."); 815 nvmf_rpc_listener_ctx_free(ctx); 816 return; 817 } 818 ctx->tgt = tgt; 819 820 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 821 if (!subsystem) { 822 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 823 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 824 nvmf_rpc_listener_ctx_free(ctx); 825 return; 826 } 827 828 ctx->subsystem = subsystem; 829 830 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 831 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 832 "Invalid parameters"); 833 nvmf_rpc_listener_ctx_free(ctx); 834 return; 835 } 836 837 ctx->op = NVMF_RPC_LISTEN_REMOVE; 838 839 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) { 840 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 841 nvmf_rpc_listener_ctx_free(ctx); 842 return; 843 } 844 845 } 846 SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", spdk_rpc_nvmf_subsystem_remove_listener, 847 SPDK_RPC_RUNTIME); 848 849 struct spdk_nvmf_ns_params { 850 char *bdev_name; 851 char *ptpl_file; 852 uint32_t nsid; 853 char nguid[16]; 854 char eui64[8]; 855 struct spdk_uuid uuid; 856 }; 857 858 struct rpc_namespaces { 859 size_t num_ns; 860 struct spdk_nvmf_ns_params ns_params[RPC_MAX_NAMESPACES]; 861 }; 862 863 864 static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = { 865 {"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true}, 866 {"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string}, 867 {"ptpl_file", offsetof(struct spdk_nvmf_ns_params, ptpl_file), spdk_json_decode_string, true}, 868 {"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true}, 869 {"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true}, 870 {"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true}, 871 }; 872 873 static int 874 decode_rpc_ns_params(const struct spdk_json_val *val, void *out) 875 { 876 struct spdk_nvmf_ns_params *ns_params = out; 877 878 return spdk_json_decode_object(val, rpc_ns_params_decoders, 879 SPDK_COUNTOF(rpc_ns_params_decoders), 880 ns_params); 881 } 882 883 struct nvmf_rpc_ns_ctx { 884 char *nqn; 885 char *tgt_name; 886 struct spdk_nvmf_ns_params ns_params; 887 888 struct spdk_jsonrpc_request *request; 889 bool response_sent; 890 }; 891 892 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = { 893 {"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string}, 894 {"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params}, 895 {"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true}, 896 }; 897 898 static void 899 nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx) 900 { 901 free(ctx->nqn); 902 free(ctx->tgt_name); 903 free(ctx->ns_params.bdev_name); 904 free(ctx->ns_params.ptpl_file); 905 free(ctx); 906 } 907 908 static void 909 nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 910 void *cb_arg, int status) 911 { 912 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 913 struct spdk_jsonrpc_request *request = ctx->request; 914 uint32_t nsid = ctx->ns_params.nsid; 915 bool response_sent = ctx->response_sent; 916 struct spdk_json_write_ctx *w; 917 918 nvmf_rpc_ns_ctx_free(ctx); 919 920 if (response_sent) { 921 return; 922 } 923 924 w = spdk_jsonrpc_begin_result(request); 925 spdk_json_write_uint32(w, nsid); 926 spdk_jsonrpc_end_result(request, w); 927 } 928 929 static void 930 nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem, 931 void *cb_arg, int status) 932 { 933 struct nvmf_rpc_ns_ctx *ctx = cb_arg; 934 struct spdk_nvmf_ns_opts ns_opts; 935 struct spdk_bdev *bdev; 936 937 bdev = spdk_bdev_get_by_name(ctx->ns_params.bdev_name); 938 if (!bdev) { 939 SPDK_ERRLOG("No bdev with name %s\n", ctx->ns_params.bdev_name); 940 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 941 "Invalid parameters"); 942 ctx->response_sent = true; 943 goto resume; 944 } 945 946 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 947 ns_opts.nsid = ctx->ns_params.nsid; 948 949 SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch"); 950 memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid)); 951 952 SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch"); 953 memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64)); 954 955 if (!spdk_mem_all_zero(&ctx->ns_params.uuid, sizeof(ctx->ns_params.uuid))) { 956 ns_opts.uuid = ctx->ns_params.uuid; 957 } 958 959 ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns(subsystem, bdev, &ns_opts, sizeof(ns_opts), 960 ctx->ns_params.ptpl_file); 961 if (ctx->ns_params.nsid == 0) { 962 SPDK_ERRLOG("Unable to add namespace\n"); 963 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 964 "Invalid parameters"); 965 ctx->response_sent = true; 966 goto resume; 967 } 968 969 resume: 970 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) { 971 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 972 nvmf_rpc_ns_ctx_free(ctx); 973 return; 974 } 975 } 976 977 static void 978 spdk_rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request, 979 const struct spdk_json_val *params) 980 { 981 struct nvmf_rpc_ns_ctx *ctx; 982 struct spdk_nvmf_subsystem *subsystem; 983 struct spdk_nvmf_tgt *tgt; 984 985 ctx = calloc(1, sizeof(*ctx)); 986 if (!ctx) { 987 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 988 return; 989 } 990 991 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ns_decoder, 992 SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder), 993 ctx)) { 994 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 995 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 996 nvmf_rpc_ns_ctx_free(ctx); 997 return; 998 } 999 1000 ctx->request = request; 1001 ctx->response_sent = false; 1002 1003 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1004 if (!tgt) { 1005 SPDK_ERRLOG("Unable to find a target object.\n"); 1006 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1007 "Unable to find a target."); 1008 nvmf_rpc_ns_ctx_free(ctx); 1009 return; 1010 } 1011 1012 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1013 if (!subsystem) { 1014 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1015 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1016 nvmf_rpc_ns_ctx_free(ctx); 1017 return; 1018 } 1019 1020 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_ns_paused, ctx)) { 1021 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1022 nvmf_rpc_ns_ctx_free(ctx); 1023 return; 1024 } 1025 } 1026 SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", spdk_rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME) 1027 1028 struct nvmf_rpc_remove_ns_ctx { 1029 char *nqn; 1030 char *tgt_name; 1031 uint32_t nsid; 1032 1033 struct spdk_jsonrpc_request *request; 1034 bool response_sent; 1035 }; 1036 1037 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = { 1038 {"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string}, 1039 {"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32}, 1040 {"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1041 }; 1042 1043 static void 1044 nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx) 1045 { 1046 free(ctx->nqn); 1047 free(ctx->tgt_name); 1048 free(ctx); 1049 } 1050 1051 static void 1052 nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1053 void *cb_arg, int status) 1054 { 1055 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1056 struct spdk_jsonrpc_request *request = ctx->request; 1057 bool response_sent = ctx->response_sent; 1058 struct spdk_json_write_ctx *w; 1059 1060 nvmf_rpc_remove_ns_ctx_free(ctx); 1061 1062 if (response_sent) { 1063 return; 1064 } 1065 1066 w = spdk_jsonrpc_begin_result(request); 1067 spdk_json_write_bool(w, true); 1068 spdk_jsonrpc_end_result(request, w); 1069 } 1070 1071 static void 1072 nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1073 void *cb_arg, int status) 1074 { 1075 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1076 int ret; 1077 1078 ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid); 1079 if (ret < 0) { 1080 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid); 1081 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1082 "Invalid parameters"); 1083 ctx->response_sent = true; 1084 } 1085 1086 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) { 1087 if (!ctx->response_sent) { 1088 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1089 } 1090 nvmf_rpc_remove_ns_ctx_free(ctx); 1091 return; 1092 } 1093 } 1094 1095 static void 1096 spdk_rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request, 1097 const struct spdk_json_val *params) 1098 { 1099 struct nvmf_rpc_remove_ns_ctx *ctx; 1100 struct spdk_nvmf_subsystem *subsystem; 1101 struct spdk_nvmf_tgt *tgt; 1102 1103 ctx = calloc(1, sizeof(*ctx)); 1104 if (!ctx) { 1105 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1106 return; 1107 } 1108 1109 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder, 1110 SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder), 1111 ctx)) { 1112 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1113 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1114 nvmf_rpc_remove_ns_ctx_free(ctx); 1115 return; 1116 } 1117 1118 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1119 if (!tgt) { 1120 SPDK_ERRLOG("Unable to find a target object.\n"); 1121 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1122 "Unable to find a target."); 1123 nvmf_rpc_remove_ns_ctx_free(ctx); 1124 return; 1125 } 1126 1127 ctx->request = request; 1128 ctx->response_sent = false; 1129 1130 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1131 if (!subsystem) { 1132 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1133 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1134 nvmf_rpc_remove_ns_ctx_free(ctx); 1135 return; 1136 } 1137 1138 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_remove_ns_paused, ctx)) { 1139 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1140 nvmf_rpc_remove_ns_ctx_free(ctx); 1141 return; 1142 } 1143 } 1144 SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", spdk_rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME) 1145 1146 enum nvmf_rpc_host_op { 1147 NVMF_RPC_HOST_ADD, 1148 NVMF_RPC_HOST_REMOVE, 1149 NVMF_RPC_HOST_ALLOW_ANY, 1150 }; 1151 1152 struct nvmf_rpc_host_ctx { 1153 struct spdk_jsonrpc_request *request; 1154 1155 char *nqn; 1156 char *host; 1157 char *tgt_name; 1158 1159 enum nvmf_rpc_host_op op; 1160 1161 bool allow_any_host; 1162 1163 bool response_sent; 1164 }; 1165 1166 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = { 1167 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1168 {"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string}, 1169 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1170 }; 1171 1172 static void 1173 nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx) 1174 { 1175 free(ctx->nqn); 1176 free(ctx->host); 1177 free(ctx->tgt_name); 1178 free(ctx); 1179 } 1180 1181 static void 1182 nvmf_rpc_host_resumed(struct spdk_nvmf_subsystem *subsystem, 1183 void *cb_arg, int status) 1184 { 1185 struct nvmf_rpc_host_ctx *ctx = cb_arg; 1186 struct spdk_jsonrpc_request *request; 1187 struct spdk_json_write_ctx *w; 1188 bool response_sent = ctx->response_sent; 1189 1190 request = ctx->request; 1191 nvmf_rpc_host_ctx_free(ctx); 1192 1193 if (response_sent) { 1194 return; 1195 } 1196 1197 w = spdk_jsonrpc_begin_result(request); 1198 spdk_json_write_bool(w, true); 1199 spdk_jsonrpc_end_result(request, w); 1200 } 1201 1202 static void 1203 nvmf_rpc_host_paused(struct spdk_nvmf_subsystem *subsystem, 1204 void *cb_arg, int status) 1205 { 1206 struct nvmf_rpc_host_ctx *ctx = cb_arg; 1207 int rc = -1; 1208 1209 switch (ctx->op) { 1210 case NVMF_RPC_HOST_ADD: 1211 rc = spdk_nvmf_subsystem_add_host(subsystem, ctx->host); 1212 break; 1213 case NVMF_RPC_HOST_REMOVE: 1214 rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host); 1215 break; 1216 case NVMF_RPC_HOST_ALLOW_ANY: 1217 rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx->allow_any_host); 1218 break; 1219 } 1220 1221 if (rc != 0) { 1222 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1223 ctx->response_sent = true; 1224 } 1225 1226 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_host_resumed, ctx)) { 1227 if (!ctx->response_sent) { 1228 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1229 } 1230 nvmf_rpc_host_ctx_free(ctx); 1231 return; 1232 } 1233 } 1234 1235 static void 1236 spdk_rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request, 1237 const struct spdk_json_val *params) 1238 { 1239 struct nvmf_rpc_host_ctx *ctx; 1240 struct spdk_nvmf_subsystem *subsystem; 1241 struct spdk_nvmf_tgt *tgt; 1242 1243 ctx = calloc(1, sizeof(*ctx)); 1244 if (!ctx) { 1245 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1246 return; 1247 } 1248 1249 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 1250 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1251 ctx)) { 1252 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1253 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1254 nvmf_rpc_host_ctx_free(ctx); 1255 return; 1256 } 1257 1258 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1259 if (!tgt) { 1260 SPDK_ERRLOG("Unable to find a target object.\n"); 1261 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1262 "Unable to find a target."); 1263 nvmf_rpc_host_ctx_free(ctx); 1264 return; 1265 } 1266 1267 ctx->request = request; 1268 ctx->op = NVMF_RPC_HOST_ADD; 1269 ctx->response_sent = false; 1270 1271 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1272 if (!subsystem) { 1273 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1274 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1275 nvmf_rpc_host_ctx_free(ctx); 1276 return; 1277 } 1278 1279 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) { 1280 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1281 nvmf_rpc_host_ctx_free(ctx); 1282 return; 1283 } 1284 } 1285 SPDK_RPC_REGISTER("nvmf_subsystem_add_host", spdk_rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME) 1286 1287 static void 1288 spdk_rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request, 1289 const struct spdk_json_val *params) 1290 { 1291 struct nvmf_rpc_host_ctx *ctx; 1292 struct spdk_nvmf_subsystem *subsystem; 1293 struct spdk_nvmf_tgt *tgt; 1294 1295 ctx = calloc(1, sizeof(*ctx)); 1296 if (!ctx) { 1297 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1298 return; 1299 } 1300 1301 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 1302 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1303 ctx)) { 1304 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1305 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1306 nvmf_rpc_host_ctx_free(ctx); 1307 return; 1308 } 1309 1310 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1311 if (!tgt) { 1312 SPDK_ERRLOG("Unable to find a target object.\n"); 1313 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1314 "Unable to find a target."); 1315 nvmf_rpc_host_ctx_free(ctx); 1316 return; 1317 } 1318 1319 ctx->request = request; 1320 ctx->op = NVMF_RPC_HOST_REMOVE; 1321 ctx->response_sent = false; 1322 1323 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1324 if (!subsystem) { 1325 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1326 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1327 nvmf_rpc_host_ctx_free(ctx); 1328 return; 1329 } 1330 1331 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) { 1332 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1333 nvmf_rpc_host_ctx_free(ctx); 1334 return; 1335 } 1336 } 1337 SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", spdk_rpc_nvmf_subsystem_remove_host, 1338 SPDK_RPC_RUNTIME) 1339 1340 1341 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = { 1342 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1343 {"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool}, 1344 {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 1345 }; 1346 1347 static void 1348 spdk_rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request, 1349 const struct spdk_json_val *params) 1350 { 1351 struct nvmf_rpc_host_ctx *ctx; 1352 struct spdk_nvmf_subsystem *subsystem; 1353 struct spdk_nvmf_tgt *tgt; 1354 1355 ctx = calloc(1, sizeof(*ctx)); 1356 if (!ctx) { 1357 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1358 return; 1359 } 1360 1361 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder, 1362 SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder), 1363 ctx)) { 1364 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1365 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1366 nvmf_rpc_host_ctx_free(ctx); 1367 return; 1368 } 1369 1370 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1371 if (!tgt) { 1372 SPDK_ERRLOG("Unable to find a target object.\n"); 1373 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1374 "Unable to find a target."); 1375 nvmf_rpc_host_ctx_free(ctx); 1376 return; 1377 } 1378 1379 ctx->request = request; 1380 ctx->op = NVMF_RPC_HOST_ALLOW_ANY; 1381 ctx->response_sent = false; 1382 1383 subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1384 if (!subsystem) { 1385 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1386 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1387 nvmf_rpc_host_ctx_free(ctx); 1388 return; 1389 } 1390 1391 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) { 1392 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1393 nvmf_rpc_host_ctx_free(ctx); 1394 return; 1395 } 1396 } 1397 SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", spdk_rpc_nvmf_subsystem_allow_any_host, 1398 SPDK_RPC_RUNTIME) 1399 1400 struct nvmf_rpc_create_transport_ctx { 1401 char *trtype; 1402 char *tgt_name; 1403 struct spdk_nvmf_transport_opts opts; 1404 struct spdk_jsonrpc_request *request; 1405 }; 1406 1407 static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = { 1408 { "trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string}, 1409 { 1410 "max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth), 1411 spdk_json_decode_uint16, true 1412 }, 1413 { 1414 "max_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr), 1415 spdk_json_decode_uint16, true 1416 }, 1417 { 1418 "in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size), 1419 spdk_json_decode_uint32, true 1420 }, 1421 { 1422 "max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size), 1423 spdk_json_decode_uint32, true 1424 }, 1425 { 1426 "io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size), 1427 spdk_json_decode_uint32, true 1428 }, 1429 { 1430 "max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth), 1431 spdk_json_decode_uint32, true 1432 }, 1433 { 1434 "num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers), 1435 spdk_json_decode_uint32, true 1436 }, 1437 { 1438 "buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size), 1439 spdk_json_decode_uint32, true 1440 }, 1441 { 1442 "max_srq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_srq_depth), 1443 spdk_json_decode_uint32, true 1444 }, 1445 { 1446 "no_srq", offsetof(struct nvmf_rpc_create_transport_ctx, opts.no_srq), 1447 spdk_json_decode_bool, true 1448 }, 1449 { 1450 "c2h_success", offsetof(struct nvmf_rpc_create_transport_ctx, opts.c2h_success), 1451 spdk_json_decode_bool, true 1452 }, 1453 { 1454 "dif_insert_or_strip", offsetof(struct nvmf_rpc_create_transport_ctx, opts.dif_insert_or_strip), 1455 spdk_json_decode_bool, true 1456 }, 1457 { 1458 "sock_priority", offsetof(struct nvmf_rpc_create_transport_ctx, opts.sock_priority), 1459 spdk_json_decode_uint32, true 1460 }, 1461 { 1462 "tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name), 1463 spdk_json_decode_string, true 1464 }, 1465 }; 1466 1467 static void 1468 nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx) 1469 { 1470 free(ctx->trtype); 1471 free(ctx->tgt_name); 1472 free(ctx); 1473 } 1474 1475 static void 1476 nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status) 1477 { 1478 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 1479 struct spdk_jsonrpc_request *request; 1480 struct spdk_json_write_ctx *w; 1481 1482 request = ctx->request; 1483 nvmf_rpc_create_transport_ctx_free(ctx); 1484 1485 if (status) { 1486 SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status); 1487 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1488 "Failed to add transport to tgt.(%d)\n", 1489 status); 1490 return; 1491 } 1492 1493 w = spdk_jsonrpc_begin_result(request); 1494 spdk_json_write_bool(w, true); 1495 spdk_jsonrpc_end_result(request, w); 1496 } 1497 1498 static void 1499 spdk_rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request, 1500 const struct spdk_json_val *params) 1501 { 1502 struct nvmf_rpc_create_transport_ctx *ctx; 1503 enum spdk_nvme_transport_type trtype; 1504 struct spdk_nvmf_transport *transport; 1505 struct spdk_nvmf_tgt *tgt; 1506 1507 ctx = calloc(1, sizeof(*ctx)); 1508 if (!ctx) { 1509 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1510 return; 1511 } 1512 1513 /* Decode parameters the first time to get the transport type */ 1514 if (spdk_json_decode_object(params, nvmf_rpc_create_transport_decoder, 1515 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 1516 ctx)) { 1517 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1518 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1519 nvmf_rpc_create_transport_ctx_free(ctx); 1520 return; 1521 } 1522 1523 tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1524 if (!tgt) { 1525 SPDK_ERRLOG("Unable to find a target object.\n"); 1526 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1527 "Unable to find a target."); 1528 nvmf_rpc_create_transport_ctx_free(ctx); 1529 return; 1530 } 1531 1532 if (spdk_nvme_transport_id_parse_trtype(&trtype, ctx->trtype)) { 1533 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype); 1534 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1535 "Invalid transport type '%s'\n", ctx->trtype); 1536 nvmf_rpc_create_transport_ctx_free(ctx); 1537 return; 1538 } 1539 1540 /* Initialize all the transport options (based on transport type) and decode the 1541 * parameters again to update any options passed in rpc create transport call. 1542 */ 1543 if (!spdk_nvmf_transport_opts_init(trtype, &ctx->opts)) { 1544 /* This can happen if user specifies PCIE transport type which isn't valid for 1545 * NVMe-oF. 1546 */ 1547 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype); 1548 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1549 "Invalid transport type '%s'\n", ctx->trtype); 1550 nvmf_rpc_create_transport_ctx_free(ctx); 1551 return; 1552 } 1553 1554 if (spdk_json_decode_object(params, nvmf_rpc_create_transport_decoder, 1555 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 1556 ctx)) { 1557 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1558 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1559 nvmf_rpc_create_transport_ctx_free(ctx); 1560 return; 1561 } 1562 1563 if (spdk_nvmf_tgt_get_transport(tgt, trtype)) { 1564 SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype); 1565 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1566 "Transport type '%s' already exists\n", ctx->trtype); 1567 nvmf_rpc_create_transport_ctx_free(ctx); 1568 return; 1569 } 1570 1571 transport = spdk_nvmf_transport_create(trtype, &ctx->opts); 1572 1573 if (!transport) { 1574 SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype); 1575 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1576 "Transport type '%s' create failed\n", ctx->trtype); 1577 nvmf_rpc_create_transport_ctx_free(ctx); 1578 return; 1579 } 1580 1581 /* add transport to target */ 1582 ctx->request = request; 1583 spdk_nvmf_tgt_add_transport(tgt, transport, nvmf_rpc_tgt_add_transport_done, ctx); 1584 } 1585 1586 SPDK_RPC_REGISTER("nvmf_create_transport", spdk_rpc_nvmf_create_transport, SPDK_RPC_RUNTIME) 1587 1588 static void 1589 dump_nvmf_transport(struct spdk_json_write_ctx *w, struct spdk_nvmf_transport *transport) 1590 { 1591 const struct spdk_nvmf_transport_opts *opts = spdk_nvmf_get_transport_opts(transport); 1592 spdk_nvme_transport_type_t type = spdk_nvmf_get_transport_type(transport); 1593 1594 spdk_json_write_object_begin(w); 1595 1596 spdk_json_write_named_string(w, "trtype", spdk_nvme_transport_id_trtype_str(type)); 1597 spdk_json_write_named_uint32(w, "max_queue_depth", opts->max_queue_depth); 1598 spdk_json_write_named_uint32(w, "max_qpairs_per_ctrlr", opts->max_qpairs_per_ctrlr); 1599 spdk_json_write_named_uint32(w, "in_capsule_data_size", opts->in_capsule_data_size); 1600 spdk_json_write_named_uint32(w, "max_io_size", opts->max_io_size); 1601 spdk_json_write_named_uint32(w, "io_unit_size", opts->io_unit_size); 1602 spdk_json_write_named_uint32(w, "max_aq_depth", opts->max_aq_depth); 1603 spdk_json_write_named_uint32(w, "num_shared_buffers", opts->num_shared_buffers); 1604 spdk_json_write_named_uint32(w, "buf_cache_size", opts->buf_cache_size); 1605 if (type == SPDK_NVME_TRANSPORT_RDMA) { 1606 spdk_json_write_named_uint32(w, "max_srq_depth", opts->max_srq_depth); 1607 spdk_json_write_named_bool(w, "no_srq", opts->no_srq); 1608 } else if (type == SPDK_NVME_TRANSPORT_TCP) { 1609 spdk_json_write_named_bool(w, "c2h_success", opts->c2h_success); 1610 spdk_json_write_named_bool(w, "dif_insert_or_strip", opts->dif_insert_or_strip); 1611 spdk_json_write_named_uint32(w, "sock_priority", opts->sock_priority); 1612 } 1613 1614 spdk_json_write_object_end(w); 1615 } 1616 1617 struct rpc_get_transport { 1618 char *tgt_name; 1619 }; 1620 1621 static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = { 1622 {"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true}, 1623 }; 1624 1625 static void 1626 spdk_rpc_get_nvmf_transports(struct spdk_jsonrpc_request *request, 1627 const struct spdk_json_val *params) 1628 { 1629 struct rpc_get_transport req = { 0 }; 1630 struct spdk_json_write_ctx *w; 1631 struct spdk_nvmf_transport *transport; 1632 struct spdk_nvmf_tgt *tgt; 1633 1634 if (params) { 1635 if (spdk_json_decode_object(params, rpc_get_transport_decoders, 1636 SPDK_COUNTOF(rpc_get_transport_decoders), 1637 &req)) { 1638 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1639 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1640 return; 1641 } 1642 } 1643 1644 tgt = spdk_nvmf_get_tgt(req.tgt_name); 1645 if (!tgt) { 1646 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1647 "Unable to find a target."); 1648 free(req.tgt_name); 1649 return; 1650 } 1651 1652 w = spdk_jsonrpc_begin_result(request); 1653 spdk_json_write_array_begin(w); 1654 transport = spdk_nvmf_transport_get_first(tgt); 1655 while (transport) { 1656 dump_nvmf_transport(w, transport); 1657 transport = spdk_nvmf_transport_get_next(transport); 1658 } 1659 spdk_json_write_array_end(w); 1660 spdk_jsonrpc_end_result(request, w); 1661 free(req.tgt_name); 1662 } 1663 SPDK_RPC_REGISTER("get_nvmf_transports", spdk_rpc_get_nvmf_transports, SPDK_RPC_RUNTIME) 1664 1665 struct rpc_nvmf_get_stats_ctx { 1666 char *tgt_name; 1667 struct spdk_nvmf_tgt *tgt; 1668 struct spdk_jsonrpc_request *request; 1669 struct spdk_json_write_ctx *w; 1670 }; 1671 1672 static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = { 1673 {"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true}, 1674 }; 1675 1676 static void 1677 free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx) 1678 { 1679 free(ctx->tgt_name); 1680 free(ctx); 1681 } 1682 1683 static void 1684 rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status) 1685 { 1686 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1687 1688 spdk_json_write_array_end(ctx->w); 1689 spdk_json_write_object_end(ctx->w); 1690 spdk_jsonrpc_end_result(ctx->request, ctx->w); 1691 free_get_stats_ctx(ctx); 1692 } 1693 1694 static void 1695 write_nvmf_transport_stats(struct spdk_json_write_ctx *w, 1696 struct spdk_nvmf_transport_poll_group_stat *stat) 1697 { 1698 uint64_t i; 1699 1700 spdk_json_write_object_begin(w); 1701 spdk_json_write_named_string(w, "trtype", 1702 spdk_nvme_transport_id_trtype_str(stat->trtype)); 1703 switch (stat->trtype) { 1704 case SPDK_NVME_TRANSPORT_RDMA: 1705 spdk_json_write_named_uint64(w, "pending_data_buffer", stat->rdma.pending_data_buffer); 1706 spdk_json_write_named_array_begin(w, "devices"); 1707 for (i = 0; i < stat->rdma.num_devices; ++i) { 1708 spdk_json_write_object_begin(w); 1709 spdk_json_write_named_string(w, "name", stat->rdma.devices[i].name); 1710 spdk_json_write_named_uint64(w, "polls", stat->rdma.devices[i].polls); 1711 spdk_json_write_named_uint64(w, "completions", stat->rdma.devices[i].completions); 1712 spdk_json_write_named_uint64(w, "requests", 1713 stat->rdma.devices[i].requests); 1714 spdk_json_write_named_uint64(w, "request_latency", 1715 stat->rdma.devices[i].request_latency); 1716 spdk_json_write_named_uint64(w, "pending_free_request", 1717 stat->rdma.devices[i].pending_free_request); 1718 spdk_json_write_named_uint64(w, "pending_rdma_read", 1719 stat->rdma.devices[i].pending_rdma_read); 1720 spdk_json_write_named_uint64(w, "pending_rdma_write", 1721 stat->rdma.devices[i].pending_rdma_write); 1722 spdk_json_write_object_end(w); 1723 } 1724 spdk_json_write_array_end(w); 1725 break; 1726 default: 1727 break; 1728 } 1729 spdk_json_write_object_end(w); 1730 } 1731 1732 static void 1733 rpc_nvmf_get_stats(struct spdk_io_channel_iter *i) 1734 { 1735 struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1736 struct spdk_nvmf_transport *transport; 1737 struct spdk_nvmf_poll_group_stat stat; 1738 struct spdk_nvmf_transport_poll_group_stat *trstat; 1739 int rc; 1740 1741 if (0 == spdk_nvmf_poll_group_get_stat(ctx->tgt, &stat)) { 1742 spdk_json_write_object_begin(ctx->w); 1743 spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(spdk_get_thread())); 1744 spdk_json_write_named_uint32(ctx->w, "admin_qpairs", stat.admin_qpairs); 1745 spdk_json_write_named_uint32(ctx->w, "io_qpairs", stat.io_qpairs); 1746 spdk_json_write_named_uint64(ctx->w, "pending_bdev_io", stat.pending_bdev_io); 1747 1748 spdk_json_write_named_array_begin(ctx->w, "transports"); 1749 transport = spdk_nvmf_transport_get_first(ctx->tgt); 1750 while (transport) { 1751 rc = spdk_nvmf_transport_poll_group_get_stat(ctx->tgt, transport, &trstat); 1752 if (0 == rc) { 1753 write_nvmf_transport_stats(ctx->w, trstat); 1754 spdk_nvmf_transport_poll_group_free_stat(transport, trstat); 1755 } else if (-ENOTSUP != rc) { 1756 SPDK_ERRLOG("Failed to get poll group statistics for transport %s, errno %d\n", 1757 spdk_nvme_transport_id_trtype_str(spdk_nvmf_get_transport_type(transport)), 1758 rc); 1759 } 1760 transport = spdk_nvmf_transport_get_next(transport); 1761 } 1762 spdk_json_write_array_end(ctx->w); 1763 spdk_json_write_object_end(ctx->w); 1764 } 1765 1766 spdk_for_each_channel_continue(i, 0); 1767 } 1768 1769 1770 static void 1771 spdk_rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request, 1772 const struct spdk_json_val *params) 1773 { 1774 struct rpc_nvmf_get_stats_ctx *ctx; 1775 1776 ctx = calloc(1, sizeof(*ctx)); 1777 if (!ctx) { 1778 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1779 "Memory allocation error"); 1780 return; 1781 } 1782 ctx->request = request; 1783 1784 if (params) { 1785 if (spdk_json_decode_object(params, rpc_get_stats_decoders, 1786 SPDK_COUNTOF(rpc_get_stats_decoders), 1787 ctx)) { 1788 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1789 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1790 free_get_stats_ctx(ctx); 1791 return; 1792 } 1793 } 1794 1795 ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1796 if (!ctx->tgt) { 1797 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1798 "Unable to find a target."); 1799 free_get_stats_ctx(ctx); 1800 return; 1801 } 1802 1803 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 1804 if (NULL == ctx->w) { 1805 free_get_stats_ctx(ctx); 1806 return; 1807 } 1808 1809 spdk_json_write_object_begin(ctx->w); 1810 spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz()); 1811 spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 1812 1813 spdk_for_each_channel(ctx->tgt, 1814 rpc_nvmf_get_stats, 1815 ctx, 1816 rpc_nvmf_get_stats_done); 1817 } 1818 1819 SPDK_RPC_REGISTER("nvmf_get_stats", spdk_rpc_nvmf_get_stats, SPDK_RPC_RUNTIME) 1820