1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2016 Intel Corporation. All rights reserved. 3 * Copyright (c) 2019-2021 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 * Copyright (c) 2022 Dell Inc, or its subsidiaries. All rights reserved. 6 */ 7 8 #include "spdk/stdinc.h" 9 10 #include "bdev_nvme.h" 11 12 #include "spdk/config.h" 13 14 #include "spdk/string.h" 15 #include "spdk/rpc.h" 16 #include "spdk/util.h" 17 #include "spdk/env.h" 18 #include "spdk/nvme.h" 19 #include "spdk/nvme_spec.h" 20 21 #include "spdk/log.h" 22 #include "spdk/bdev_module.h" 23 24 #define TCP_PSK_INVALID_PERMISSIONS 0177 25 26 static bool g_tls_log = false; 27 28 static int 29 rpc_decode_action_on_timeout(const struct spdk_json_val *val, void *out) 30 { 31 enum spdk_bdev_timeout_action *action = out; 32 33 if (spdk_json_strequal(val, "none") == true) { 34 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE; 35 } else if (spdk_json_strequal(val, "abort") == true) { 36 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT; 37 } else if (spdk_json_strequal(val, "reset") == true) { 38 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET; 39 } else { 40 SPDK_NOTICELOG("Invalid parameter value: action_on_timeout\n"); 41 return -EINVAL; 42 } 43 44 return 0; 45 } 46 47 static const struct spdk_json_object_decoder rpc_bdev_nvme_options_decoders[] = { 48 {"action_on_timeout", offsetof(struct spdk_bdev_nvme_opts, action_on_timeout), rpc_decode_action_on_timeout, true}, 49 {"timeout_us", offsetof(struct spdk_bdev_nvme_opts, timeout_us), spdk_json_decode_uint64, true}, 50 {"timeout_admin_us", offsetof(struct spdk_bdev_nvme_opts, timeout_admin_us), spdk_json_decode_uint64, true}, 51 {"keep_alive_timeout_ms", offsetof(struct spdk_bdev_nvme_opts, keep_alive_timeout_ms), spdk_json_decode_uint32, true}, 52 {"retry_count", offsetof(struct spdk_bdev_nvme_opts, transport_retry_count), spdk_json_decode_uint32, true}, 53 {"arbitration_burst", offsetof(struct spdk_bdev_nvme_opts, arbitration_burst), spdk_json_decode_uint32, true}, 54 {"low_priority_weight", offsetof(struct spdk_bdev_nvme_opts, low_priority_weight), spdk_json_decode_uint32, true}, 55 {"medium_priority_weight", offsetof(struct spdk_bdev_nvme_opts, medium_priority_weight), spdk_json_decode_uint32, true}, 56 {"high_priority_weight", offsetof(struct spdk_bdev_nvme_opts, high_priority_weight), spdk_json_decode_uint32, true}, 57 {"nvme_adminq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_adminq_poll_period_us), spdk_json_decode_uint64, true}, 58 {"nvme_ioq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_ioq_poll_period_us), spdk_json_decode_uint64, true}, 59 {"io_queue_requests", offsetof(struct spdk_bdev_nvme_opts, io_queue_requests), spdk_json_decode_uint32, true}, 60 {"delay_cmd_submit", offsetof(struct spdk_bdev_nvme_opts, delay_cmd_submit), spdk_json_decode_bool, true}, 61 {"transport_retry_count", offsetof(struct spdk_bdev_nvme_opts, transport_retry_count), spdk_json_decode_uint32, true}, 62 {"bdev_retry_count", offsetof(struct spdk_bdev_nvme_opts, bdev_retry_count), spdk_json_decode_int32, true}, 63 {"transport_ack_timeout", offsetof(struct spdk_bdev_nvme_opts, transport_ack_timeout), spdk_json_decode_uint8, true}, 64 {"ctrlr_loss_timeout_sec", offsetof(struct spdk_bdev_nvme_opts, ctrlr_loss_timeout_sec), spdk_json_decode_int32, true}, 65 {"reconnect_delay_sec", offsetof(struct spdk_bdev_nvme_opts, reconnect_delay_sec), spdk_json_decode_uint32, true}, 66 {"fast_io_fail_timeout_sec", offsetof(struct spdk_bdev_nvme_opts, fast_io_fail_timeout_sec), spdk_json_decode_uint32, true}, 67 {"disable_auto_failback", offsetof(struct spdk_bdev_nvme_opts, disable_auto_failback), spdk_json_decode_bool, true}, 68 {"generate_uuids", offsetof(struct spdk_bdev_nvme_opts, generate_uuids), spdk_json_decode_bool, true}, 69 {"transport_tos", offsetof(struct spdk_bdev_nvme_opts, transport_tos), spdk_json_decode_uint8, true}, 70 {"nvme_error_stat", offsetof(struct spdk_bdev_nvme_opts, nvme_error_stat), spdk_json_decode_bool, true}, 71 {"rdma_srq_size", offsetof(struct spdk_bdev_nvme_opts, rdma_srq_size), spdk_json_decode_uint32, true}, 72 {"io_path_stat", offsetof(struct spdk_bdev_nvme_opts, io_path_stat), spdk_json_decode_bool, true}, 73 }; 74 75 static void 76 rpc_bdev_nvme_set_options(struct spdk_jsonrpc_request *request, 77 const struct spdk_json_val *params) 78 { 79 struct spdk_bdev_nvme_opts opts; 80 int rc; 81 82 bdev_nvme_get_opts(&opts); 83 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_options_decoders, 84 SPDK_COUNTOF(rpc_bdev_nvme_options_decoders), 85 &opts)) { 86 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 87 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 88 "spdk_json_decode_object failed"); 89 return; 90 } 91 92 rc = bdev_nvme_set_opts(&opts); 93 if (rc == -EPERM) { 94 spdk_jsonrpc_send_error_response(request, -EPERM, 95 "RPC not permitted with nvme controllers already attached"); 96 } else if (rc) { 97 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 98 } else { 99 spdk_jsonrpc_send_bool_response(request, true); 100 } 101 102 return; 103 } 104 SPDK_RPC_REGISTER("bdev_nvme_set_options", rpc_bdev_nvme_set_options, 105 SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) 106 107 struct rpc_bdev_nvme_hotplug { 108 bool enabled; 109 uint64_t period_us; 110 }; 111 112 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders[] = { 113 {"enable", offsetof(struct rpc_bdev_nvme_hotplug, enabled), spdk_json_decode_bool, false}, 114 {"period_us", offsetof(struct rpc_bdev_nvme_hotplug, period_us), spdk_json_decode_uint64, true}, 115 }; 116 117 static void 118 rpc_bdev_nvme_set_hotplug_done(void *ctx) 119 { 120 struct spdk_jsonrpc_request *request = ctx; 121 122 spdk_jsonrpc_send_bool_response(request, true); 123 } 124 125 static void 126 rpc_bdev_nvme_set_hotplug(struct spdk_jsonrpc_request *request, 127 const struct spdk_json_val *params) 128 { 129 struct rpc_bdev_nvme_hotplug req = {false, 0}; 130 int rc; 131 132 if (spdk_json_decode_object(params, rpc_bdev_nvme_hotplug_decoders, 133 SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders), &req)) { 134 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 135 rc = -EINVAL; 136 goto invalid; 137 } 138 139 rc = bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_bdev_nvme_set_hotplug_done, 140 request); 141 if (rc) { 142 goto invalid; 143 } 144 145 return; 146 invalid: 147 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc)); 148 } 149 SPDK_RPC_REGISTER("bdev_nvme_set_hotplug", rpc_bdev_nvme_set_hotplug, SPDK_RPC_RUNTIME) 150 151 enum bdev_nvme_multipath_mode { 152 BDEV_NVME_MP_MODE_FAILOVER, 153 BDEV_NVME_MP_MODE_MULTIPATH, 154 BDEV_NVME_MP_MODE_DISABLE, 155 }; 156 157 struct rpc_bdev_nvme_attach_controller { 158 char *name; 159 char *trtype; 160 char *adrfam; 161 char *traddr; 162 char *trsvcid; 163 char *priority; 164 char *subnqn; 165 char *hostnqn; 166 char *hostaddr; 167 char *hostsvcid; 168 char *psk; 169 enum bdev_nvme_multipath_mode multipath; 170 struct nvme_ctrlr_opts bdev_opts; 171 struct spdk_nvme_ctrlr_opts drv_opts; 172 uint32_t max_bdevs; 173 }; 174 175 static void 176 free_rpc_bdev_nvme_attach_controller(struct rpc_bdev_nvme_attach_controller *req) 177 { 178 free(req->name); 179 free(req->trtype); 180 free(req->adrfam); 181 free(req->traddr); 182 free(req->trsvcid); 183 free(req->priority); 184 free(req->subnqn); 185 free(req->hostnqn); 186 free(req->hostaddr); 187 free(req->hostsvcid); 188 free(req->psk); 189 } 190 191 static int 192 bdev_nvme_decode_reftag(const struct spdk_json_val *val, void *out) 193 { 194 uint32_t *flag = out; 195 bool reftag; 196 int rc; 197 198 rc = spdk_json_decode_bool(val, &reftag); 199 if (rc == 0 && reftag == true) { 200 *flag |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG; 201 } 202 203 return rc; 204 } 205 206 static int 207 bdev_nvme_decode_guard(const struct spdk_json_val *val, void *out) 208 { 209 uint32_t *flag = out; 210 bool guard; 211 int rc; 212 213 rc = spdk_json_decode_bool(val, &guard); 214 if (rc == 0 && guard == true) { 215 *flag |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD; 216 } 217 218 return rc; 219 } 220 221 static int 222 bdev_nvme_decode_multipath(const struct spdk_json_val *val, void *out) 223 { 224 enum bdev_nvme_multipath_mode *multipath = out; 225 226 if (spdk_json_strequal(val, "failover") == true) { 227 *multipath = BDEV_NVME_MP_MODE_FAILOVER; 228 } else if (spdk_json_strequal(val, "multipath") == true) { 229 *multipath = BDEV_NVME_MP_MODE_MULTIPATH; 230 } else if (spdk_json_strequal(val, "disable") == true) { 231 *multipath = BDEV_NVME_MP_MODE_DISABLE; 232 } else { 233 SPDK_NOTICELOG("Invalid parameter value: multipath\n"); 234 return -EINVAL; 235 } 236 237 return 0; 238 } 239 240 241 static const struct spdk_json_object_decoder rpc_bdev_nvme_attach_controller_decoders[] = { 242 {"name", offsetof(struct rpc_bdev_nvme_attach_controller, name), spdk_json_decode_string}, 243 {"trtype", offsetof(struct rpc_bdev_nvme_attach_controller, trtype), spdk_json_decode_string}, 244 {"traddr", offsetof(struct rpc_bdev_nvme_attach_controller, traddr), spdk_json_decode_string}, 245 246 {"adrfam", offsetof(struct rpc_bdev_nvme_attach_controller, adrfam), spdk_json_decode_string, true}, 247 {"trsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, trsvcid), spdk_json_decode_string, true}, 248 {"priority", offsetof(struct rpc_bdev_nvme_attach_controller, priority), spdk_json_decode_string, true}, 249 {"subnqn", offsetof(struct rpc_bdev_nvme_attach_controller, subnqn), spdk_json_decode_string, true}, 250 {"hostnqn", offsetof(struct rpc_bdev_nvme_attach_controller, hostnqn), spdk_json_decode_string, true}, 251 {"hostaddr", offsetof(struct rpc_bdev_nvme_attach_controller, hostaddr), spdk_json_decode_string, true}, 252 {"hostsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, hostsvcid), spdk_json_decode_string, true}, 253 254 {"prchk_reftag", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.prchk_flags), bdev_nvme_decode_reftag, true}, 255 {"prchk_guard", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.prchk_flags), bdev_nvme_decode_guard, true}, 256 {"hdgst", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.header_digest), spdk_json_decode_bool, true}, 257 {"ddgst", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.data_digest), spdk_json_decode_bool, true}, 258 {"fabrics_connect_timeout_us", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.fabrics_connect_timeout_us), spdk_json_decode_uint64, true}, 259 {"multipath", offsetof(struct rpc_bdev_nvme_attach_controller, multipath), bdev_nvme_decode_multipath, true}, 260 {"num_io_queues", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.num_io_queues), spdk_json_decode_uint32, true}, 261 {"ctrlr_loss_timeout_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.ctrlr_loss_timeout_sec), spdk_json_decode_int32, true}, 262 {"reconnect_delay_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.reconnect_delay_sec), spdk_json_decode_uint32, true}, 263 {"fast_io_fail_timeout_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.fast_io_fail_timeout_sec), spdk_json_decode_uint32, true}, 264 {"psk", offsetof(struct rpc_bdev_nvme_attach_controller, psk), spdk_json_decode_string, true}, 265 {"max_bdevs", offsetof(struct rpc_bdev_nvme_attach_controller, max_bdevs), spdk_json_decode_uint32, true}, 266 }; 267 268 #define DEFAULT_MAX_BDEVS_PER_RPC 128 269 270 struct rpc_bdev_nvme_attach_controller_ctx { 271 struct rpc_bdev_nvme_attach_controller req; 272 size_t bdev_count; 273 const char **names; 274 struct spdk_jsonrpc_request *request; 275 }; 276 277 static void 278 free_rpc_bdev_nvme_attach_controller_ctx(struct rpc_bdev_nvme_attach_controller_ctx *ctx) 279 { 280 free_rpc_bdev_nvme_attach_controller(&ctx->req); 281 free(ctx->names); 282 free(ctx); 283 } 284 285 static void 286 rpc_bdev_nvme_attach_controller_examined(void *cb_ctx) 287 { 288 struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx; 289 struct spdk_jsonrpc_request *request = ctx->request; 290 struct spdk_json_write_ctx *w; 291 size_t i; 292 293 w = spdk_jsonrpc_begin_result(request); 294 spdk_json_write_array_begin(w); 295 for (i = 0; i < ctx->bdev_count; i++) { 296 spdk_json_write_string(w, ctx->names[i]); 297 } 298 spdk_json_write_array_end(w); 299 spdk_jsonrpc_end_result(request, w); 300 301 free_rpc_bdev_nvme_attach_controller_ctx(ctx); 302 } 303 304 static void 305 rpc_bdev_nvme_attach_controller_done(void *cb_ctx, size_t bdev_count, int rc) 306 { 307 struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx; 308 struct spdk_jsonrpc_request *request = ctx->request; 309 310 if (rc < 0) { 311 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 312 free_rpc_bdev_nvme_attach_controller_ctx(ctx); 313 return; 314 } 315 316 ctx->bdev_count = bdev_count; 317 spdk_bdev_wait_for_examine(rpc_bdev_nvme_attach_controller_examined, ctx); 318 } 319 320 static int 321 tcp_load_psk(const char *fname, char *buf, size_t bufsz) 322 { 323 FILE *psk_file; 324 struct stat statbuf; 325 int rc; 326 327 if (stat(fname, &statbuf) != 0) { 328 SPDK_ERRLOG("Could not read permissions for PSK file\n"); 329 return -EACCES; 330 } 331 332 if ((statbuf.st_mode & TCP_PSK_INVALID_PERMISSIONS) != 0) { 333 SPDK_ERRLOG("Incorrect permissions for PSK file\n"); 334 return -EPERM; 335 } 336 if ((size_t)statbuf.st_size >= bufsz) { 337 SPDK_ERRLOG("Invalid PSK: too long\n"); 338 return -EINVAL; 339 } 340 psk_file = fopen(fname, "r"); 341 if (psk_file == NULL) { 342 SPDK_ERRLOG("Could not open PSK file\n"); 343 return -EINVAL; 344 } 345 346 memset(buf, 0, bufsz); 347 rc = fread(buf, 1, statbuf.st_size, psk_file); 348 if (rc != statbuf.st_size) { 349 SPDK_ERRLOG("Failed to read PSK\n"); 350 fclose(psk_file); 351 return -EINVAL; 352 } 353 354 fclose(psk_file); 355 return 0; 356 } 357 358 static void 359 rpc_bdev_nvme_attach_controller(struct spdk_jsonrpc_request *request, 360 const struct spdk_json_val *params) 361 { 362 struct rpc_bdev_nvme_attach_controller_ctx *ctx; 363 struct spdk_nvme_transport_id trid = {}; 364 const struct spdk_nvme_ctrlr_opts *drv_opts; 365 const struct spdk_nvme_transport_id *ctrlr_trid; 366 struct nvme_ctrlr *ctrlr = NULL; 367 size_t len, maxlen; 368 bool multipath = false; 369 int rc; 370 371 ctx = calloc(1, sizeof(*ctx)); 372 if (!ctx) { 373 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 374 return; 375 } 376 377 spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.drv_opts, sizeof(ctx->req.drv_opts)); 378 bdev_nvme_get_default_ctrlr_opts(&ctx->req.bdev_opts); 379 /* For now, initialize the multipath parameter to add a failover path. This maintains backward 380 * compatibility with past behavior. In the future, this behavior will change to "disable". */ 381 ctx->req.multipath = BDEV_NVME_MP_MODE_FAILOVER; 382 ctx->req.max_bdevs = DEFAULT_MAX_BDEVS_PER_RPC; 383 384 if (spdk_json_decode_object(params, rpc_bdev_nvme_attach_controller_decoders, 385 SPDK_COUNTOF(rpc_bdev_nvme_attach_controller_decoders), 386 &ctx->req)) { 387 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 388 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 389 "spdk_json_decode_object failed"); 390 goto cleanup; 391 } 392 393 if (ctx->req.max_bdevs == 0) { 394 spdk_jsonrpc_send_error_response(request, -EINVAL, "max_bdevs cannot be zero"); 395 goto cleanup; 396 } 397 398 ctx->names = calloc(ctx->req.max_bdevs, sizeof(char *)); 399 if (ctx->names == NULL) { 400 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 401 goto cleanup; 402 } 403 404 /* Parse trstring */ 405 rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype); 406 if (rc < 0) { 407 SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype); 408 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 409 ctx->req.trtype); 410 goto cleanup; 411 } 412 413 /* Parse trtype */ 414 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype); 415 assert(rc == 0); 416 417 /* Parse traddr */ 418 maxlen = sizeof(trid.traddr); 419 len = strnlen(ctx->req.traddr, maxlen); 420 if (len == maxlen) { 421 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s", 422 ctx->req.traddr); 423 goto cleanup; 424 } 425 memcpy(trid.traddr, ctx->req.traddr, len + 1); 426 427 /* Parse adrfam */ 428 if (ctx->req.adrfam) { 429 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam); 430 if (rc < 0) { 431 SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam); 432 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 433 ctx->req.adrfam); 434 goto cleanup; 435 } 436 } 437 438 /* Parse trsvcid */ 439 if (ctx->req.trsvcid) { 440 maxlen = sizeof(trid.trsvcid); 441 len = strnlen(ctx->req.trsvcid, maxlen); 442 if (len == maxlen) { 443 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s", 444 ctx->req.trsvcid); 445 goto cleanup; 446 } 447 memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1); 448 } 449 450 /* Parse priority for the NVMe-oF transport connection */ 451 if (ctx->req.priority) { 452 trid.priority = spdk_strtol(ctx->req.priority, 10); 453 } 454 455 /* Parse subnqn */ 456 if (ctx->req.subnqn) { 457 maxlen = sizeof(trid.subnqn); 458 len = strnlen(ctx->req.subnqn, maxlen); 459 if (len == maxlen) { 460 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s", 461 ctx->req.subnqn); 462 goto cleanup; 463 } 464 memcpy(trid.subnqn, ctx->req.subnqn, len + 1); 465 } 466 467 if (ctx->req.hostnqn) { 468 snprintf(ctx->req.drv_opts.hostnqn, sizeof(ctx->req.drv_opts.hostnqn), "%s", 469 ctx->req.hostnqn); 470 } 471 472 if (ctx->req.psk) { 473 if (!g_tls_log) { 474 SPDK_NOTICELOG("TLS support is considered experimental\n"); 475 g_tls_log = true; 476 } 477 rc = tcp_load_psk(ctx->req.psk, ctx->req.drv_opts.psk, sizeof(ctx->req.drv_opts.psk)); 478 if (rc) { 479 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Could not retrieve PSK from file: %s", 480 ctx->req.psk); 481 goto cleanup; 482 } 483 } 484 485 if (ctx->req.hostaddr) { 486 maxlen = sizeof(ctx->req.drv_opts.src_addr); 487 len = strnlen(ctx->req.hostaddr, maxlen); 488 if (len == maxlen) { 489 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s", 490 ctx->req.hostaddr); 491 goto cleanup; 492 } 493 snprintf(ctx->req.drv_opts.src_addr, maxlen, "%s", ctx->req.hostaddr); 494 } 495 496 if (ctx->req.hostsvcid) { 497 maxlen = sizeof(ctx->req.drv_opts.src_svcid); 498 len = strnlen(ctx->req.hostsvcid, maxlen); 499 if (len == maxlen) { 500 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s", 501 ctx->req.hostsvcid); 502 goto cleanup; 503 } 504 snprintf(ctx->req.drv_opts.src_svcid, maxlen, "%s", ctx->req.hostsvcid); 505 } 506 507 ctrlr = nvme_ctrlr_get_by_name(ctx->req.name); 508 509 if (ctrlr) { 510 /* This controller already exists. Check what the user wants to do. */ 511 if (ctx->req.multipath == BDEV_NVME_MP_MODE_DISABLE) { 512 /* The user does not want to do any form of multipathing. */ 513 spdk_jsonrpc_send_error_response_fmt(request, -EALREADY, 514 "A controller named %s already exists and multipath is disabled\n", 515 ctx->req.name); 516 goto cleanup; 517 } 518 519 assert(ctx->req.multipath == BDEV_NVME_MP_MODE_FAILOVER || 520 ctx->req.multipath == BDEV_NVME_MP_MODE_MULTIPATH); 521 522 /* The user wants to add this as a failover path or add this to create multipath. */ 523 drv_opts = spdk_nvme_ctrlr_get_opts(ctrlr->ctrlr); 524 ctrlr_trid = spdk_nvme_ctrlr_get_transport_id(ctrlr->ctrlr); 525 526 if (strncmp(trid.traddr, ctrlr_trid->traddr, sizeof(trid.traddr)) == 0 && 527 strncmp(trid.trsvcid, ctrlr_trid->trsvcid, sizeof(trid.trsvcid)) == 0 && 528 strncmp(ctx->req.drv_opts.src_addr, drv_opts->src_addr, sizeof(drv_opts->src_addr)) == 0 && 529 strncmp(ctx->req.drv_opts.src_svcid, drv_opts->src_svcid, sizeof(drv_opts->src_svcid)) == 0) { 530 /* Exactly same network path can't be added a second time */ 531 spdk_jsonrpc_send_error_response_fmt(request, -EALREADY, 532 "A controller named %s already exists with the specified network path\n", 533 ctx->req.name); 534 goto cleanup; 535 } 536 537 if (strncmp(trid.subnqn, 538 ctrlr_trid->subnqn, 539 SPDK_NVMF_NQN_MAX_LEN) != 0) { 540 /* Different SUBNQN is not allowed when specifying the same controller name. */ 541 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 542 "A controller named %s already exists, but uses a different subnqn (%s)\n", 543 ctx->req.name, ctrlr_trid->subnqn); 544 goto cleanup; 545 } 546 547 if (strncmp(ctx->req.drv_opts.hostnqn, drv_opts->hostnqn, SPDK_NVMF_NQN_MAX_LEN) != 0) { 548 /* Different HOSTNQN is not allowed when specifying the same controller name. */ 549 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 550 "A controller named %s already exists, but uses a different hostnqn (%s)\n", 551 ctx->req.name, drv_opts->hostnqn); 552 goto cleanup; 553 } 554 555 if (ctx->req.bdev_opts.prchk_flags) { 556 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 557 "A controller named %s already exists. To add a path, do not specify PI options.\n", 558 ctx->req.name); 559 goto cleanup; 560 } 561 562 ctx->req.bdev_opts.prchk_flags = ctrlr->opts.prchk_flags; 563 } 564 565 if (ctx->req.multipath == BDEV_NVME_MP_MODE_MULTIPATH) { 566 multipath = true; 567 } 568 569 if (ctx->req.drv_opts.num_io_queues == 0 || ctx->req.drv_opts.num_io_queues > UINT16_MAX + 1) { 570 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 571 "num_io_queues out of bounds, min: %u max: %u\n", 572 1, UINT16_MAX + 1); 573 goto cleanup; 574 } 575 576 ctx->request = request; 577 /* Should already be zero due to the calloc(), but set explicitly for clarity. */ 578 ctx->req.bdev_opts.from_discovery_service = false; 579 rc = bdev_nvme_create(&trid, ctx->req.name, ctx->names, ctx->req.max_bdevs, 580 rpc_bdev_nvme_attach_controller_done, ctx, &ctx->req.drv_opts, 581 &ctx->req.bdev_opts, multipath); 582 if (rc) { 583 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 584 goto cleanup; 585 } 586 587 return; 588 589 cleanup: 590 free_rpc_bdev_nvme_attach_controller_ctx(ctx); 591 } 592 SPDK_RPC_REGISTER("bdev_nvme_attach_controller", rpc_bdev_nvme_attach_controller, 593 SPDK_RPC_RUNTIME) 594 595 static void 596 rpc_dump_nvme_bdev_controller_info(struct nvme_bdev_ctrlr *nbdev_ctrlr, void *ctx) 597 { 598 struct spdk_json_write_ctx *w = ctx; 599 struct nvme_ctrlr *nvme_ctrlr; 600 601 spdk_json_write_object_begin(w); 602 spdk_json_write_named_string(w, "name", nbdev_ctrlr->name); 603 604 spdk_json_write_named_array_begin(w, "ctrlrs"); 605 TAILQ_FOREACH(nvme_ctrlr, &nbdev_ctrlr->ctrlrs, tailq) { 606 nvme_ctrlr_info_json(w, nvme_ctrlr); 607 } 608 spdk_json_write_array_end(w); 609 spdk_json_write_object_end(w); 610 } 611 612 struct rpc_bdev_nvme_get_controllers { 613 char *name; 614 }; 615 616 static void 617 free_rpc_bdev_nvme_get_controllers(struct rpc_bdev_nvme_get_controllers *r) 618 { 619 free(r->name); 620 } 621 622 static const struct spdk_json_object_decoder rpc_bdev_nvme_get_controllers_decoders[] = { 623 {"name", offsetof(struct rpc_bdev_nvme_get_controllers, name), spdk_json_decode_string, true}, 624 }; 625 626 static void 627 rpc_bdev_nvme_get_controllers(struct spdk_jsonrpc_request *request, 628 const struct spdk_json_val *params) 629 { 630 struct rpc_bdev_nvme_get_controllers req = {}; 631 struct spdk_json_write_ctx *w; 632 struct nvme_bdev_ctrlr *nbdev_ctrlr = NULL; 633 634 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_get_controllers_decoders, 635 SPDK_COUNTOF(rpc_bdev_nvme_get_controllers_decoders), 636 &req)) { 637 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 638 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 639 "spdk_json_decode_object failed"); 640 goto cleanup; 641 } 642 643 if (req.name) { 644 nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name(req.name); 645 if (nbdev_ctrlr == NULL) { 646 SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name); 647 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Controller %s does not exist", req.name); 648 goto cleanup; 649 } 650 } 651 652 w = spdk_jsonrpc_begin_result(request); 653 spdk_json_write_array_begin(w); 654 655 if (nbdev_ctrlr != NULL) { 656 rpc_dump_nvme_bdev_controller_info(nbdev_ctrlr, w); 657 } else { 658 nvme_bdev_ctrlr_for_each(rpc_dump_nvme_bdev_controller_info, w); 659 } 660 661 spdk_json_write_array_end(w); 662 663 spdk_jsonrpc_end_result(request, w); 664 665 cleanup: 666 free_rpc_bdev_nvme_get_controllers(&req); 667 } 668 SPDK_RPC_REGISTER("bdev_nvme_get_controllers", rpc_bdev_nvme_get_controllers, SPDK_RPC_RUNTIME) 669 670 struct rpc_bdev_nvme_detach_controller { 671 char *name; 672 char *trtype; 673 char *adrfam; 674 char *traddr; 675 char *trsvcid; 676 char *subnqn; 677 char *hostaddr; 678 char *hostsvcid; 679 }; 680 681 static void 682 free_rpc_bdev_nvme_detach_controller(struct rpc_bdev_nvme_detach_controller *req) 683 { 684 free(req->name); 685 free(req->trtype); 686 free(req->adrfam); 687 free(req->traddr); 688 free(req->trsvcid); 689 free(req->subnqn); 690 free(req->hostaddr); 691 free(req->hostsvcid); 692 } 693 694 static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_decoders[] = { 695 {"name", offsetof(struct rpc_bdev_nvme_detach_controller, name), spdk_json_decode_string}, 696 {"trtype", offsetof(struct rpc_bdev_nvme_detach_controller, trtype), spdk_json_decode_string, true}, 697 {"traddr", offsetof(struct rpc_bdev_nvme_detach_controller, traddr), spdk_json_decode_string, true}, 698 {"adrfam", offsetof(struct rpc_bdev_nvme_detach_controller, adrfam), spdk_json_decode_string, true}, 699 {"trsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, trsvcid), spdk_json_decode_string, true}, 700 {"subnqn", offsetof(struct rpc_bdev_nvme_detach_controller, subnqn), spdk_json_decode_string, true}, 701 {"hostaddr", offsetof(struct rpc_bdev_nvme_detach_controller, hostaddr), spdk_json_decode_string, true}, 702 {"hostsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, hostsvcid), spdk_json_decode_string, true}, 703 }; 704 705 static void 706 rpc_bdev_nvme_detach_controller(struct spdk_jsonrpc_request *request, 707 const struct spdk_json_val *params) 708 { 709 struct rpc_bdev_nvme_detach_controller req = {NULL}; 710 struct nvme_path_id path = {}; 711 size_t len, maxlen; 712 int rc = 0; 713 714 if (spdk_json_decode_object(params, rpc_bdev_nvme_detach_controller_decoders, 715 SPDK_COUNTOF(rpc_bdev_nvme_detach_controller_decoders), 716 &req)) { 717 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 718 "spdk_json_decode_object failed"); 719 goto cleanup; 720 } 721 722 if (req.trtype != NULL) { 723 rc = spdk_nvme_transport_id_populate_trstring(&path.trid, req.trtype); 724 if (rc < 0) { 725 SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype); 726 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 727 req.trtype); 728 goto cleanup; 729 } 730 731 rc = spdk_nvme_transport_id_parse_trtype(&path.trid.trtype, req.trtype); 732 if (rc < 0) { 733 SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype); 734 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 735 req.trtype); 736 goto cleanup; 737 } 738 } 739 740 if (req.traddr != NULL) { 741 maxlen = sizeof(path.trid.traddr); 742 len = strnlen(req.traddr, maxlen); 743 if (len == maxlen) { 744 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s", 745 req.traddr); 746 goto cleanup; 747 } 748 memcpy(path.trid.traddr, req.traddr, len + 1); 749 } 750 751 if (req.adrfam != NULL) { 752 rc = spdk_nvme_transport_id_parse_adrfam(&path.trid.adrfam, req.adrfam); 753 if (rc < 0) { 754 SPDK_ERRLOG("Failed to parse adrfam: %s\n", req.adrfam); 755 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 756 req.adrfam); 757 goto cleanup; 758 } 759 } 760 761 if (req.trsvcid != NULL) { 762 maxlen = sizeof(path.trid.trsvcid); 763 len = strnlen(req.trsvcid, maxlen); 764 if (len == maxlen) { 765 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s", 766 req.trsvcid); 767 goto cleanup; 768 } 769 memcpy(path.trid.trsvcid, req.trsvcid, len + 1); 770 } 771 772 /* Parse subnqn */ 773 if (req.subnqn != NULL) { 774 maxlen = sizeof(path.trid.subnqn); 775 len = strnlen(req.subnqn, maxlen); 776 if (len == maxlen) { 777 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s", 778 req.subnqn); 779 goto cleanup; 780 } 781 memcpy(path.trid.subnqn, req.subnqn, len + 1); 782 } 783 784 if (req.hostaddr) { 785 maxlen = sizeof(path.hostid.hostaddr); 786 len = strnlen(req.hostaddr, maxlen); 787 if (len == maxlen) { 788 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s", 789 req.hostaddr); 790 goto cleanup; 791 } 792 snprintf(path.hostid.hostaddr, maxlen, "%s", req.hostaddr); 793 } 794 795 if (req.hostsvcid) { 796 maxlen = sizeof(path.hostid.hostsvcid); 797 len = strnlen(req.hostsvcid, maxlen); 798 if (len == maxlen) { 799 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s", 800 req.hostsvcid); 801 goto cleanup; 802 } 803 snprintf(path.hostid.hostsvcid, maxlen, "%s", req.hostsvcid); 804 } 805 806 rc = bdev_nvme_delete(req.name, &path); 807 808 if (rc != 0) { 809 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 810 goto cleanup; 811 } 812 813 spdk_jsonrpc_send_bool_response(request, true); 814 815 cleanup: 816 free_rpc_bdev_nvme_detach_controller(&req); 817 } 818 SPDK_RPC_REGISTER("bdev_nvme_detach_controller", rpc_bdev_nvme_detach_controller, 819 SPDK_RPC_RUNTIME) 820 821 struct rpc_apply_firmware { 822 char *filename; 823 char *bdev_name; 824 }; 825 826 static void 827 free_rpc_apply_firmware(struct rpc_apply_firmware *req) 828 { 829 free(req->filename); 830 free(req->bdev_name); 831 } 832 833 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders[] = { 834 {"filename", offsetof(struct rpc_apply_firmware, filename), spdk_json_decode_string}, 835 {"bdev_name", offsetof(struct rpc_apply_firmware, bdev_name), spdk_json_decode_string}, 836 }; 837 838 struct firmware_update_info { 839 void *fw_image; 840 void *p; 841 unsigned int size; 842 unsigned int size_remaining; 843 unsigned int offset; 844 unsigned int transfer; 845 bool success; 846 847 struct spdk_bdev_desc *desc; 848 struct spdk_io_channel *ch; 849 struct spdk_thread *orig_thread; 850 struct spdk_jsonrpc_request *request; 851 struct spdk_nvme_ctrlr *ctrlr; 852 struct rpc_apply_firmware req; 853 }; 854 855 static void 856 apply_firmware_cleanup(struct firmware_update_info *firm_ctx) 857 { 858 assert(firm_ctx != NULL); 859 assert(firm_ctx->orig_thread == spdk_get_thread()); 860 861 if (firm_ctx->fw_image) { 862 spdk_free(firm_ctx->fw_image); 863 } 864 865 free_rpc_apply_firmware(&firm_ctx->req); 866 867 if (firm_ctx->ch) { 868 spdk_put_io_channel(firm_ctx->ch); 869 } 870 871 if (firm_ctx->desc) { 872 spdk_bdev_close(firm_ctx->desc); 873 } 874 875 free(firm_ctx); 876 } 877 878 static void 879 _apply_firmware_complete_reset(void *ctx) 880 { 881 struct spdk_json_write_ctx *w; 882 struct firmware_update_info *firm_ctx = ctx; 883 884 assert(firm_ctx->orig_thread == spdk_get_thread()); 885 886 if (!firm_ctx->success) { 887 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 888 "firmware commit failed."); 889 apply_firmware_cleanup(firm_ctx); 890 return; 891 } 892 893 if (spdk_nvme_ctrlr_reset(firm_ctx->ctrlr) != 0) { 894 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 895 "Controller reset failed."); 896 apply_firmware_cleanup(firm_ctx); 897 return; 898 } 899 900 w = spdk_jsonrpc_begin_result(firm_ctx->request); 901 spdk_json_write_string(w, "firmware commit succeeded. Controller reset in progress."); 902 spdk_jsonrpc_end_result(firm_ctx->request, w); 903 apply_firmware_cleanup(firm_ctx); 904 } 905 906 static void 907 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 908 { 909 struct firmware_update_info *firm_ctx = cb_arg; 910 911 spdk_bdev_free_io(bdev_io); 912 913 firm_ctx->success = success; 914 915 spdk_thread_exec_msg(firm_ctx->orig_thread, _apply_firmware_complete_reset, firm_ctx); 916 } 917 918 static void apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); 919 920 static void 921 _apply_firmware_complete(void *ctx) 922 { 923 struct spdk_nvme_cmd cmd = {}; 924 struct spdk_nvme_fw_commit fw_commit; 925 int slot = 0; 926 int rc; 927 struct firmware_update_info *firm_ctx = ctx; 928 enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG; 929 930 assert(firm_ctx->orig_thread == spdk_get_thread()); 931 932 if (!firm_ctx->success) { 933 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 934 "firmware download failed ."); 935 apply_firmware_cleanup(firm_ctx); 936 return; 937 } 938 939 firm_ctx->p += firm_ctx->transfer; 940 firm_ctx->offset += firm_ctx->transfer; 941 firm_ctx->size_remaining -= firm_ctx->transfer; 942 943 switch (firm_ctx->size_remaining) { 944 case 0: 945 /* firmware download completed. Commit firmware */ 946 memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit)); 947 fw_commit.fs = slot; 948 fw_commit.ca = commit_action; 949 950 cmd.opc = SPDK_NVME_OPC_FIRMWARE_COMMIT; 951 memcpy(&cmd.cdw10, &fw_commit, sizeof(uint32_t)); 952 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, NULL, 0, 953 apply_firmware_complete_reset, firm_ctx); 954 if (rc) { 955 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 956 "firmware commit failed."); 957 apply_firmware_cleanup(firm_ctx); 958 return; 959 } 960 break; 961 default: 962 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 963 cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 964 965 cmd.cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer); 966 cmd.cdw11 = firm_ctx->offset >> 2; 967 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p, 968 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 969 if (rc) { 970 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 971 "firmware download failed."); 972 apply_firmware_cleanup(firm_ctx); 973 return; 974 } 975 break; 976 } 977 } 978 979 static void 980 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 981 { 982 struct firmware_update_info *firm_ctx = cb_arg; 983 984 spdk_bdev_free_io(bdev_io); 985 986 firm_ctx->success = success; 987 988 spdk_thread_exec_msg(firm_ctx->orig_thread, _apply_firmware_complete, firm_ctx); 989 } 990 991 static void 992 apply_firmware_open_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 993 { 994 } 995 996 static void 997 rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request, 998 const struct spdk_json_val *params) 999 { 1000 int rc; 1001 int fd = -1; 1002 struct stat fw_stat; 1003 struct spdk_bdev *bdev; 1004 struct spdk_nvme_cmd cmd = {}; 1005 struct firmware_update_info *firm_ctx; 1006 1007 firm_ctx = calloc(1, sizeof(struct firmware_update_info)); 1008 if (!firm_ctx) { 1009 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1010 "Memory allocation error."); 1011 return; 1012 } 1013 firm_ctx->fw_image = NULL; 1014 firm_ctx->request = request; 1015 firm_ctx->orig_thread = spdk_get_thread(); 1016 1017 if (spdk_json_decode_object(params, rpc_apply_firmware_decoders, 1018 SPDK_COUNTOF(rpc_apply_firmware_decoders), &firm_ctx->req)) { 1019 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1020 "spdk_json_decode_object failed."); 1021 goto err; 1022 } 1023 1024 if (spdk_bdev_open_ext(firm_ctx->req.bdev_name, true, apply_firmware_open_cb, NULL, 1025 &firm_ctx->desc) != 0) { 1026 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1027 "bdev %s could not be opened", 1028 firm_ctx->req.bdev_name); 1029 goto err; 1030 } 1031 bdev = spdk_bdev_desc_get_bdev(firm_ctx->desc); 1032 1033 if ((firm_ctx->ctrlr = bdev_nvme_get_ctrlr(bdev)) == NULL) { 1034 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1035 "Controller information for %s were not found.", 1036 firm_ctx->req.bdev_name); 1037 goto err; 1038 } 1039 1040 firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc); 1041 if (!firm_ctx->ch) { 1042 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1043 "No channels were found."); 1044 goto err; 1045 } 1046 1047 fd = open(firm_ctx->req.filename, O_RDONLY); 1048 if (fd < 0) { 1049 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1050 "open file failed."); 1051 goto err; 1052 } 1053 1054 rc = fstat(fd, &fw_stat); 1055 if (rc < 0) { 1056 close(fd); 1057 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1058 "fstat failed."); 1059 goto err; 1060 } 1061 1062 firm_ctx->size = fw_stat.st_size; 1063 if (fw_stat.st_size % 4) { 1064 close(fd); 1065 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1066 "Firmware image size is not multiple of 4."); 1067 goto err; 1068 } 1069 1070 firm_ctx->fw_image = spdk_zmalloc(firm_ctx->size, 4096, NULL, 1071 SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 1072 if (!firm_ctx->fw_image) { 1073 close(fd); 1074 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1075 "Memory allocation error."); 1076 goto err; 1077 } 1078 firm_ctx->p = firm_ctx->fw_image; 1079 1080 if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) { 1081 close(fd); 1082 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1083 "Read firmware image failed!"); 1084 goto err; 1085 } 1086 close(fd); 1087 1088 firm_ctx->offset = 0; 1089 firm_ctx->size_remaining = firm_ctx->size; 1090 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 1091 1092 cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 1093 cmd.cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer); 1094 cmd.cdw11 = firm_ctx->offset >> 2; 1095 1096 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p, 1097 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 1098 if (rc == 0) { 1099 /* normal return here. */ 1100 return; 1101 } 1102 1103 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1104 "Read firmware image failed!"); 1105 err: 1106 apply_firmware_cleanup(firm_ctx); 1107 } 1108 SPDK_RPC_REGISTER("bdev_nvme_apply_firmware", rpc_bdev_nvme_apply_firmware, SPDK_RPC_RUNTIME) 1109 1110 struct rpc_bdev_nvme_transport_stat_ctx { 1111 struct spdk_jsonrpc_request *request; 1112 struct spdk_json_write_ctx *w; 1113 }; 1114 1115 static void 1116 rpc_bdev_nvme_rdma_stats(struct spdk_json_write_ctx *w, 1117 struct spdk_nvme_transport_poll_group_stat *stat) 1118 { 1119 struct spdk_nvme_rdma_device_stat *device_stats; 1120 uint32_t i; 1121 1122 spdk_json_write_named_array_begin(w, "devices"); 1123 1124 for (i = 0; i < stat->rdma.num_devices; i++) { 1125 device_stats = &stat->rdma.device_stats[i]; 1126 spdk_json_write_object_begin(w); 1127 spdk_json_write_named_string(w, "dev_name", device_stats->name); 1128 spdk_json_write_named_uint64(w, "polls", device_stats->polls); 1129 spdk_json_write_named_uint64(w, "idle_polls", device_stats->idle_polls); 1130 spdk_json_write_named_uint64(w, "completions", device_stats->completions); 1131 spdk_json_write_named_uint64(w, "queued_requests", device_stats->queued_requests); 1132 spdk_json_write_named_uint64(w, "total_send_wrs", device_stats->total_send_wrs); 1133 spdk_json_write_named_uint64(w, "send_doorbell_updates", device_stats->send_doorbell_updates); 1134 spdk_json_write_named_uint64(w, "total_recv_wrs", device_stats->total_recv_wrs); 1135 spdk_json_write_named_uint64(w, "recv_doorbell_updates", device_stats->recv_doorbell_updates); 1136 spdk_json_write_object_end(w); 1137 } 1138 spdk_json_write_array_end(w); 1139 } 1140 1141 static void 1142 rpc_bdev_nvme_pcie_stats(struct spdk_json_write_ctx *w, 1143 struct spdk_nvme_transport_poll_group_stat *stat) 1144 { 1145 spdk_json_write_named_uint64(w, "polls", stat->pcie.polls); 1146 spdk_json_write_named_uint64(w, "idle_polls", stat->pcie.idle_polls); 1147 spdk_json_write_named_uint64(w, "completions", stat->pcie.completions); 1148 spdk_json_write_named_uint64(w, "cq_mmio_doorbell_updates", stat->pcie.cq_mmio_doorbell_updates); 1149 spdk_json_write_named_uint64(w, "cq_shadow_doorbell_updates", 1150 stat->pcie.cq_shadow_doorbell_updates); 1151 spdk_json_write_named_uint64(w, "queued_requests", stat->pcie.queued_requests); 1152 spdk_json_write_named_uint64(w, "submitted_requests", stat->pcie.submitted_requests); 1153 spdk_json_write_named_uint64(w, "sq_mmio_doorbell_updates", stat->pcie.sq_mmio_doorbell_updates); 1154 spdk_json_write_named_uint64(w, "sq_shadow_doorbell_updates", 1155 stat->pcie.sq_shadow_doorbell_updates); 1156 } 1157 1158 static void 1159 rpc_bdev_nvme_tcp_stats(struct spdk_json_write_ctx *w, 1160 struct spdk_nvme_transport_poll_group_stat *stat) 1161 { 1162 spdk_json_write_named_uint64(w, "polls", stat->tcp.polls); 1163 spdk_json_write_named_uint64(w, "idle_polls", stat->tcp.idle_polls); 1164 spdk_json_write_named_uint64(w, "socket_completions", stat->tcp.socket_completions); 1165 spdk_json_write_named_uint64(w, "nvme_completions", stat->tcp.nvme_completions); 1166 spdk_json_write_named_uint64(w, "queued_requests", stat->tcp.queued_requests); 1167 spdk_json_write_named_uint64(w, "submitted_requests", stat->tcp.submitted_requests); 1168 } 1169 1170 static void 1171 rpc_bdev_nvme_stats_per_channel(struct spdk_io_channel_iter *i) 1172 { 1173 struct rpc_bdev_nvme_transport_stat_ctx *ctx; 1174 struct spdk_io_channel *ch; 1175 struct nvme_poll_group *group; 1176 struct spdk_nvme_poll_group_stat *stat; 1177 struct spdk_nvme_transport_poll_group_stat *tr_stat; 1178 uint32_t j; 1179 int rc; 1180 1181 ctx = spdk_io_channel_iter_get_ctx(i); 1182 ch = spdk_io_channel_iter_get_channel(i); 1183 group = spdk_io_channel_get_ctx(ch); 1184 1185 rc = spdk_nvme_poll_group_get_stats(group->group, &stat); 1186 if (rc) { 1187 spdk_for_each_channel_continue(i, rc); 1188 return; 1189 } 1190 1191 spdk_json_write_object_begin(ctx->w); 1192 spdk_json_write_named_string(ctx->w, "thread", spdk_thread_get_name(spdk_get_thread())); 1193 spdk_json_write_named_array_begin(ctx->w, "transports"); 1194 1195 for (j = 0; j < stat->num_transports; j++) { 1196 tr_stat = stat->transport_stat[j]; 1197 spdk_json_write_object_begin(ctx->w); 1198 spdk_json_write_named_string(ctx->w, "trname", spdk_nvme_transport_id_trtype_str(tr_stat->trtype)); 1199 1200 switch (stat->transport_stat[j]->trtype) { 1201 case SPDK_NVME_TRANSPORT_RDMA: 1202 rpc_bdev_nvme_rdma_stats(ctx->w, tr_stat); 1203 break; 1204 case SPDK_NVME_TRANSPORT_PCIE: 1205 case SPDK_NVME_TRANSPORT_VFIOUSER: 1206 rpc_bdev_nvme_pcie_stats(ctx->w, tr_stat); 1207 break; 1208 case SPDK_NVME_TRANSPORT_TCP: 1209 rpc_bdev_nvme_tcp_stats(ctx->w, tr_stat); 1210 break; 1211 default: 1212 SPDK_WARNLOG("Can't handle trtype %d %s\n", tr_stat->trtype, 1213 spdk_nvme_transport_id_trtype_str(tr_stat->trtype)); 1214 } 1215 spdk_json_write_object_end(ctx->w); 1216 } 1217 /* transports array */ 1218 spdk_json_write_array_end(ctx->w); 1219 spdk_json_write_object_end(ctx->w); 1220 1221 spdk_nvme_poll_group_free_stats(group->group, stat); 1222 spdk_for_each_channel_continue(i, 0); 1223 } 1224 1225 static void 1226 rpc_bdev_nvme_stats_done(struct spdk_io_channel_iter *i, int status) 1227 { 1228 struct rpc_bdev_nvme_transport_stat_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1229 1230 spdk_json_write_array_end(ctx->w); 1231 spdk_json_write_object_end(ctx->w); 1232 spdk_jsonrpc_end_result(ctx->request, ctx->w); 1233 free(ctx); 1234 } 1235 1236 static void 1237 rpc_bdev_nvme_get_transport_statistics(struct spdk_jsonrpc_request *request, 1238 const struct spdk_json_val *params) 1239 { 1240 struct rpc_bdev_nvme_transport_stat_ctx *ctx; 1241 1242 if (params) { 1243 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1244 "'bdev_nvme_get_transport_statistics' requires no arguments"); 1245 return; 1246 } 1247 1248 ctx = calloc(1, sizeof(*ctx)); 1249 if (!ctx) { 1250 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1251 "Memory allocation error"); 1252 return; 1253 } 1254 ctx->request = request; 1255 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 1256 spdk_json_write_object_begin(ctx->w); 1257 spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 1258 1259 spdk_for_each_channel(&g_nvme_bdev_ctrlrs, 1260 rpc_bdev_nvme_stats_per_channel, 1261 ctx, 1262 rpc_bdev_nvme_stats_done); 1263 } 1264 SPDK_RPC_REGISTER("bdev_nvme_get_transport_statistics", rpc_bdev_nvme_get_transport_statistics, 1265 SPDK_RPC_RUNTIME) 1266 1267 struct rpc_bdev_nvme_controller_op_req { 1268 char *name; 1269 uint16_t cntlid; 1270 }; 1271 1272 static void 1273 free_rpc_bdev_nvme_controller_op_req(struct rpc_bdev_nvme_controller_op_req *r) 1274 { 1275 free(r->name); 1276 } 1277 1278 static const struct spdk_json_object_decoder rpc_bdev_nvme_controller_op_req_decoders[] = { 1279 {"name", offsetof(struct rpc_bdev_nvme_controller_op_req, name), spdk_json_decode_string}, 1280 {"cntlid", offsetof(struct rpc_bdev_nvme_controller_op_req, cntlid), spdk_json_decode_uint16, true}, 1281 }; 1282 1283 static void 1284 rpc_bdev_nvme_controller_op_cb(void *cb_arg, int rc) 1285 { 1286 struct spdk_jsonrpc_request *request = cb_arg; 1287 1288 if (rc == 0) { 1289 spdk_jsonrpc_send_bool_response(request, true); 1290 } else { 1291 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1292 } 1293 } 1294 1295 static void 1296 rpc_bdev_nvme_controller_op(struct spdk_jsonrpc_request *request, 1297 const struct spdk_json_val *params, 1298 enum nvme_ctrlr_op op) 1299 { 1300 struct rpc_bdev_nvme_controller_op_req req = {NULL}; 1301 struct nvme_bdev_ctrlr *nbdev_ctrlr; 1302 struct nvme_ctrlr *nvme_ctrlr; 1303 1304 if (spdk_json_decode_object(params, rpc_bdev_nvme_controller_op_req_decoders, 1305 SPDK_COUNTOF(rpc_bdev_nvme_controller_op_req_decoders), 1306 &req)) { 1307 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1308 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(EINVAL)); 1309 goto exit; 1310 } 1311 1312 nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name(req.name); 1313 if (nbdev_ctrlr == NULL) { 1314 SPDK_ERRLOG("Failed at NVMe bdev controller lookup\n"); 1315 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1316 goto exit; 1317 } 1318 1319 if (req.cntlid == 0) { 1320 nvme_bdev_ctrlr_op_rpc(nbdev_ctrlr, op, rpc_bdev_nvme_controller_op_cb, request); 1321 } else { 1322 nvme_ctrlr = nvme_bdev_ctrlr_get_ctrlr_by_id(nbdev_ctrlr, req.cntlid); 1323 if (nvme_ctrlr == NULL) { 1324 SPDK_ERRLOG("Failed at NVMe controller lookup\n"); 1325 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1326 goto exit; 1327 } 1328 nvme_ctrlr_op_rpc(nvme_ctrlr, op, rpc_bdev_nvme_controller_op_cb, request); 1329 } 1330 1331 exit: 1332 free_rpc_bdev_nvme_controller_op_req(&req); 1333 } 1334 1335 static void 1336 rpc_bdev_nvme_reset_controller(struct spdk_jsonrpc_request *request, 1337 const struct spdk_json_val *params) 1338 { 1339 rpc_bdev_nvme_controller_op(request, params, NVME_CTRLR_OP_RESET); 1340 } 1341 SPDK_RPC_REGISTER("bdev_nvme_reset_controller", rpc_bdev_nvme_reset_controller, SPDK_RPC_RUNTIME) 1342 1343 static void 1344 rpc_bdev_nvme_enable_controller(struct spdk_jsonrpc_request *request, 1345 const struct spdk_json_val *params) 1346 { 1347 rpc_bdev_nvme_controller_op(request, params, NVME_CTRLR_OP_ENABLE); 1348 } 1349 SPDK_RPC_REGISTER("bdev_nvme_enable_controller", rpc_bdev_nvme_enable_controller, SPDK_RPC_RUNTIME) 1350 1351 static void 1352 rpc_bdev_nvme_disable_controller(struct spdk_jsonrpc_request *request, 1353 const struct spdk_json_val *params) 1354 { 1355 rpc_bdev_nvme_controller_op(request, params, NVME_CTRLR_OP_DISABLE); 1356 } 1357 SPDK_RPC_REGISTER("bdev_nvme_disable_controller", rpc_bdev_nvme_disable_controller, 1358 SPDK_RPC_RUNTIME) 1359 1360 struct rpc_get_controller_health_info { 1361 char *name; 1362 }; 1363 1364 struct spdk_nvme_health_info_context { 1365 struct spdk_jsonrpc_request *request; 1366 struct spdk_nvme_ctrlr *ctrlr; 1367 struct spdk_nvme_health_information_page health_page; 1368 }; 1369 1370 static void 1371 free_rpc_get_controller_health_info(struct rpc_get_controller_health_info *r) 1372 { 1373 free(r->name); 1374 } 1375 1376 static const struct spdk_json_object_decoder rpc_get_controller_health_info_decoders[] = { 1377 {"name", offsetof(struct rpc_get_controller_health_info, name), spdk_json_decode_string, true}, 1378 }; 1379 1380 static void 1381 nvme_health_info_cleanup(struct spdk_nvme_health_info_context *context, bool response) 1382 { 1383 if (response == true) { 1384 spdk_jsonrpc_send_error_response(context->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1385 "Internal error."); 1386 } 1387 1388 free(context); 1389 } 1390 1391 static void 1392 get_health_log_page_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl) 1393 { 1394 int i; 1395 char buf[128]; 1396 struct spdk_nvme_health_info_context *context = cb_arg; 1397 struct spdk_jsonrpc_request *request = context->request; 1398 struct spdk_json_write_ctx *w; 1399 struct spdk_nvme_ctrlr *ctrlr = context->ctrlr; 1400 const struct spdk_nvme_transport_id *trid = NULL; 1401 const struct spdk_nvme_ctrlr_data *cdata = NULL; 1402 struct spdk_nvme_health_information_page *health_page = NULL; 1403 1404 if (spdk_nvme_cpl_is_error(cpl)) { 1405 nvme_health_info_cleanup(context, true); 1406 SPDK_ERRLOG("get log page failed\n"); 1407 return; 1408 } 1409 1410 if (ctrlr == NULL) { 1411 nvme_health_info_cleanup(context, true); 1412 SPDK_ERRLOG("ctrlr is NULL\n"); 1413 return; 1414 } else { 1415 trid = spdk_nvme_ctrlr_get_transport_id(ctrlr); 1416 cdata = spdk_nvme_ctrlr_get_data(ctrlr); 1417 health_page = &(context->health_page); 1418 } 1419 1420 w = spdk_jsonrpc_begin_result(request); 1421 1422 spdk_json_write_object_begin(w); 1423 snprintf(buf, sizeof(cdata->mn) + 1, "%s", cdata->mn); 1424 spdk_str_trim(buf); 1425 spdk_json_write_named_string(w, "model_number", buf); 1426 snprintf(buf, sizeof(cdata->sn) + 1, "%s", cdata->sn); 1427 spdk_str_trim(buf); 1428 spdk_json_write_named_string(w, "serial_number", buf); 1429 snprintf(buf, sizeof(cdata->fr) + 1, "%s", cdata->fr); 1430 spdk_str_trim(buf); 1431 spdk_json_write_named_string(w, "firmware_revision", buf); 1432 spdk_json_write_named_string(w, "traddr", trid->traddr); 1433 spdk_json_write_named_uint64(w, "temperature_celsius", health_page->temperature - 273); 1434 spdk_json_write_named_uint64(w, "available_spare_percentage", health_page->available_spare); 1435 spdk_json_write_named_uint64(w, "available_spare_threshold_percentage", 1436 health_page->available_spare_threshold); 1437 spdk_json_write_named_uint64(w, "percentage_used", health_page->percentage_used); 1438 spdk_json_write_named_uint128(w, "data_units_read", 1439 health_page->data_units_read[0], health_page->data_units_read[1]); 1440 spdk_json_write_named_uint128(w, "data_units_written", 1441 health_page->data_units_written[0], health_page->data_units_written[1]); 1442 spdk_json_write_named_uint128(w, "host_read_commands", 1443 health_page->host_read_commands[0], health_page->host_read_commands[1]); 1444 spdk_json_write_named_uint128(w, "host_write_commands", 1445 health_page->host_write_commands[0], health_page->host_write_commands[1]); 1446 spdk_json_write_named_uint128(w, "controller_busy_time", 1447 health_page->controller_busy_time[0], health_page->controller_busy_time[1]); 1448 spdk_json_write_named_uint128(w, "power_cycles", 1449 health_page->power_cycles[0], health_page->power_cycles[1]); 1450 spdk_json_write_named_uint128(w, "power_on_hours", 1451 health_page->power_on_hours[0], health_page->power_on_hours[1]); 1452 spdk_json_write_named_uint128(w, "unsafe_shutdowns", 1453 health_page->unsafe_shutdowns[0], health_page->unsafe_shutdowns[1]); 1454 spdk_json_write_named_uint128(w, "media_errors", 1455 health_page->media_errors[0], health_page->media_errors[1]); 1456 spdk_json_write_named_uint128(w, "num_err_log_entries", 1457 health_page->num_error_info_log_entries[0], health_page->num_error_info_log_entries[1]); 1458 spdk_json_write_named_uint64(w, "warning_temperature_time_minutes", health_page->warning_temp_time); 1459 spdk_json_write_named_uint64(w, "critical_composite_temperature_time_minutes", 1460 health_page->critical_temp_time); 1461 for (i = 0; i < 8; i++) { 1462 if (health_page->temp_sensor[i] != 0) { 1463 spdk_json_write_named_uint64(w, "temperature_sensor_celsius", health_page->temp_sensor[i] - 273); 1464 } 1465 } 1466 spdk_json_write_object_end(w); 1467 1468 spdk_jsonrpc_end_result(request, w); 1469 nvme_health_info_cleanup(context, false); 1470 } 1471 1472 static void 1473 get_health_log_page(struct spdk_nvme_health_info_context *context) 1474 { 1475 struct spdk_nvme_ctrlr *ctrlr = context->ctrlr; 1476 1477 if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_HEALTH_INFORMATION, 1478 SPDK_NVME_GLOBAL_NS_TAG, 1479 &(context->health_page), sizeof(context->health_page), 0, 1480 get_health_log_page_completion, context)) { 1481 nvme_health_info_cleanup(context, true); 1482 SPDK_ERRLOG("spdk_nvme_ctrlr_cmd_get_log_page() failed\n"); 1483 } 1484 } 1485 1486 static void 1487 get_temperature_threshold_feature_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl) 1488 { 1489 struct spdk_nvme_health_info_context *context = cb_arg; 1490 1491 if (spdk_nvme_cpl_is_error(cpl)) { 1492 nvme_health_info_cleanup(context, true); 1493 SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed in completion\n"); 1494 } else { 1495 get_health_log_page(context); 1496 } 1497 } 1498 1499 static int 1500 get_temperature_threshold_feature(struct spdk_nvme_health_info_context *context) 1501 { 1502 struct spdk_nvme_cmd cmd = {}; 1503 1504 cmd.opc = SPDK_NVME_OPC_GET_FEATURES; 1505 cmd.cdw10 = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD; 1506 1507 return spdk_nvme_ctrlr_cmd_admin_raw(context->ctrlr, &cmd, NULL, 0, 1508 get_temperature_threshold_feature_completion, context); 1509 } 1510 1511 static void 1512 get_controller_health_info(struct spdk_jsonrpc_request *request, struct spdk_nvme_ctrlr *ctrlr) 1513 { 1514 struct spdk_nvme_health_info_context *context; 1515 1516 context = calloc(1, sizeof(struct spdk_nvme_health_info_context)); 1517 if (!context) { 1518 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1519 "Memory allocation error."); 1520 return; 1521 } 1522 1523 context->request = request; 1524 context->ctrlr = ctrlr; 1525 1526 if (get_temperature_threshold_feature(context)) { 1527 nvme_health_info_cleanup(context, true); 1528 SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed to submit\n"); 1529 } 1530 1531 return; 1532 } 1533 1534 static void 1535 rpc_bdev_nvme_get_controller_health_info(struct spdk_jsonrpc_request *request, 1536 const struct spdk_json_val *params) 1537 { 1538 struct rpc_get_controller_health_info req = {}; 1539 struct nvme_ctrlr *nvme_ctrlr = NULL; 1540 1541 if (!params) { 1542 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1543 "Missing device name"); 1544 1545 return; 1546 } 1547 if (spdk_json_decode_object(params, rpc_get_controller_health_info_decoders, 1548 SPDK_COUNTOF(rpc_get_controller_health_info_decoders), &req)) { 1549 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1550 free_rpc_get_controller_health_info(&req); 1551 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1552 "Invalid parameters"); 1553 1554 return; 1555 } 1556 1557 nvme_ctrlr = nvme_ctrlr_get_by_name(req.name); 1558 1559 if (!nvme_ctrlr) { 1560 SPDK_ERRLOG("nvme ctrlr name '%s' does not exist\n", req.name); 1561 free_rpc_get_controller_health_info(&req); 1562 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1563 "Device not found"); 1564 return; 1565 } 1566 1567 get_controller_health_info(request, nvme_ctrlr->ctrlr); 1568 free_rpc_get_controller_health_info(&req); 1569 1570 return; 1571 } 1572 SPDK_RPC_REGISTER("bdev_nvme_get_controller_health_info", 1573 rpc_bdev_nvme_get_controller_health_info, SPDK_RPC_RUNTIME) 1574 1575 struct rpc_bdev_nvme_start_discovery { 1576 char *name; 1577 char *trtype; 1578 char *adrfam; 1579 char *traddr; 1580 char *trsvcid; 1581 char *hostnqn; 1582 bool wait_for_attach; 1583 uint64_t attach_timeout_ms; 1584 struct spdk_nvme_ctrlr_opts opts; 1585 struct nvme_ctrlr_opts bdev_opts; 1586 }; 1587 1588 static void 1589 free_rpc_bdev_nvme_start_discovery(struct rpc_bdev_nvme_start_discovery *req) 1590 { 1591 free(req->name); 1592 free(req->trtype); 1593 free(req->adrfam); 1594 free(req->traddr); 1595 free(req->trsvcid); 1596 free(req->hostnqn); 1597 } 1598 1599 static const struct spdk_json_object_decoder rpc_bdev_nvme_start_discovery_decoders[] = { 1600 {"name", offsetof(struct rpc_bdev_nvme_start_discovery, name), spdk_json_decode_string}, 1601 {"trtype", offsetof(struct rpc_bdev_nvme_start_discovery, trtype), spdk_json_decode_string}, 1602 {"traddr", offsetof(struct rpc_bdev_nvme_start_discovery, traddr), spdk_json_decode_string}, 1603 {"adrfam", offsetof(struct rpc_bdev_nvme_start_discovery, adrfam), spdk_json_decode_string, true}, 1604 {"trsvcid", offsetof(struct rpc_bdev_nvme_start_discovery, trsvcid), spdk_json_decode_string, true}, 1605 {"hostnqn", offsetof(struct rpc_bdev_nvme_start_discovery, hostnqn), spdk_json_decode_string, true}, 1606 {"wait_for_attach", offsetof(struct rpc_bdev_nvme_start_discovery, wait_for_attach), spdk_json_decode_bool, true}, 1607 {"attach_timeout_ms", offsetof(struct rpc_bdev_nvme_start_discovery, attach_timeout_ms), spdk_json_decode_uint64, true}, 1608 {"ctrlr_loss_timeout_sec", offsetof(struct rpc_bdev_nvme_start_discovery, bdev_opts.ctrlr_loss_timeout_sec), spdk_json_decode_int32, true}, 1609 {"reconnect_delay_sec", offsetof(struct rpc_bdev_nvme_start_discovery, bdev_opts.reconnect_delay_sec), spdk_json_decode_uint32, true}, 1610 {"fast_io_fail_timeout_sec", offsetof(struct rpc_bdev_nvme_start_discovery, bdev_opts.fast_io_fail_timeout_sec), spdk_json_decode_uint32, true}, 1611 }; 1612 1613 struct rpc_bdev_nvme_start_discovery_ctx { 1614 struct rpc_bdev_nvme_start_discovery req; 1615 struct spdk_jsonrpc_request *request; 1616 }; 1617 1618 static void 1619 rpc_bdev_nvme_start_discovery_done(void *ctx, int status) 1620 { 1621 struct spdk_jsonrpc_request *request = ctx; 1622 1623 if (status != 0) { 1624 spdk_jsonrpc_send_error_response(request, status, spdk_strerror(-status)); 1625 } else { 1626 spdk_jsonrpc_send_bool_response(request, true); 1627 } 1628 } 1629 1630 static void 1631 rpc_bdev_nvme_start_discovery(struct spdk_jsonrpc_request *request, 1632 const struct spdk_json_val *params) 1633 { 1634 struct rpc_bdev_nvme_start_discovery_ctx *ctx; 1635 struct spdk_nvme_transport_id trid = {}; 1636 size_t len, maxlen; 1637 int rc; 1638 spdk_bdev_nvme_start_discovery_fn cb_fn; 1639 void *cb_ctx; 1640 1641 ctx = calloc(1, sizeof(*ctx)); 1642 if (!ctx) { 1643 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1644 return; 1645 } 1646 1647 spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.opts, sizeof(ctx->req.opts)); 1648 1649 if (spdk_json_decode_object(params, rpc_bdev_nvme_start_discovery_decoders, 1650 SPDK_COUNTOF(rpc_bdev_nvme_start_discovery_decoders), 1651 &ctx->req)) { 1652 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1653 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1654 "spdk_json_decode_object failed"); 1655 goto cleanup; 1656 } 1657 1658 /* Parse trstring */ 1659 rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype); 1660 if (rc < 0) { 1661 SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype); 1662 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 1663 ctx->req.trtype); 1664 goto cleanup; 1665 } 1666 1667 /* Parse trtype */ 1668 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype); 1669 assert(rc == 0); 1670 1671 /* Parse traddr */ 1672 maxlen = sizeof(trid.traddr); 1673 len = strnlen(ctx->req.traddr, maxlen); 1674 if (len == maxlen) { 1675 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s", 1676 ctx->req.traddr); 1677 goto cleanup; 1678 } 1679 memcpy(trid.traddr, ctx->req.traddr, len + 1); 1680 1681 /* Parse adrfam */ 1682 if (ctx->req.adrfam) { 1683 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam); 1684 if (rc < 0) { 1685 SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam); 1686 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 1687 ctx->req.adrfam); 1688 goto cleanup; 1689 } 1690 } 1691 1692 /* Parse trsvcid */ 1693 if (ctx->req.trsvcid) { 1694 maxlen = sizeof(trid.trsvcid); 1695 len = strnlen(ctx->req.trsvcid, maxlen); 1696 if (len == maxlen) { 1697 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s", 1698 ctx->req.trsvcid); 1699 goto cleanup; 1700 } 1701 memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1); 1702 } 1703 1704 if (ctx->req.hostnqn) { 1705 snprintf(ctx->req.opts.hostnqn, sizeof(ctx->req.opts.hostnqn), "%s", 1706 ctx->req.hostnqn); 1707 } 1708 1709 if (ctx->req.attach_timeout_ms != 0) { 1710 ctx->req.wait_for_attach = true; 1711 } 1712 1713 ctx->request = request; 1714 cb_fn = ctx->req.wait_for_attach ? rpc_bdev_nvme_start_discovery_done : NULL; 1715 cb_ctx = ctx->req.wait_for_attach ? request : NULL; 1716 rc = bdev_nvme_start_discovery(&trid, ctx->req.name, &ctx->req.opts, &ctx->req.bdev_opts, 1717 ctx->req.attach_timeout_ms, false, cb_fn, cb_ctx); 1718 if (rc) { 1719 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1720 } else if (!ctx->req.wait_for_attach) { 1721 rpc_bdev_nvme_start_discovery_done(request, 0); 1722 } 1723 1724 cleanup: 1725 free_rpc_bdev_nvme_start_discovery(&ctx->req); 1726 free(ctx); 1727 } 1728 SPDK_RPC_REGISTER("bdev_nvme_start_discovery", rpc_bdev_nvme_start_discovery, 1729 SPDK_RPC_RUNTIME) 1730 1731 struct rpc_bdev_nvme_stop_discovery { 1732 char *name; 1733 }; 1734 1735 static const struct spdk_json_object_decoder rpc_bdev_nvme_stop_discovery_decoders[] = { 1736 {"name", offsetof(struct rpc_bdev_nvme_stop_discovery, name), spdk_json_decode_string}, 1737 }; 1738 1739 struct rpc_bdev_nvme_stop_discovery_ctx { 1740 struct rpc_bdev_nvme_stop_discovery req; 1741 struct spdk_jsonrpc_request *request; 1742 }; 1743 1744 static void 1745 rpc_bdev_nvme_stop_discovery_done(void *cb_ctx) 1746 { 1747 struct rpc_bdev_nvme_stop_discovery_ctx *ctx = cb_ctx; 1748 1749 spdk_jsonrpc_send_bool_response(ctx->request, true); 1750 free(ctx->req.name); 1751 free(ctx); 1752 } 1753 1754 static void 1755 rpc_bdev_nvme_stop_discovery(struct spdk_jsonrpc_request *request, 1756 const struct spdk_json_val *params) 1757 { 1758 struct rpc_bdev_nvme_stop_discovery_ctx *ctx; 1759 int rc; 1760 1761 ctx = calloc(1, sizeof(*ctx)); 1762 if (!ctx) { 1763 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1764 return; 1765 } 1766 1767 if (spdk_json_decode_object(params, rpc_bdev_nvme_stop_discovery_decoders, 1768 SPDK_COUNTOF(rpc_bdev_nvme_stop_discovery_decoders), 1769 &ctx->req)) { 1770 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1771 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1772 "spdk_json_decode_object failed"); 1773 goto cleanup; 1774 } 1775 1776 ctx->request = request; 1777 rc = bdev_nvme_stop_discovery(ctx->req.name, rpc_bdev_nvme_stop_discovery_done, ctx); 1778 if (rc) { 1779 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1780 goto cleanup; 1781 } 1782 1783 return; 1784 1785 cleanup: 1786 free(ctx->req.name); 1787 free(ctx); 1788 } 1789 SPDK_RPC_REGISTER("bdev_nvme_stop_discovery", rpc_bdev_nvme_stop_discovery, 1790 SPDK_RPC_RUNTIME) 1791 1792 static void 1793 rpc_bdev_nvme_get_discovery_info(struct spdk_jsonrpc_request *request, 1794 const struct spdk_json_val *params) 1795 { 1796 struct spdk_json_write_ctx *w; 1797 1798 w = spdk_jsonrpc_begin_result(request); 1799 bdev_nvme_get_discovery_info(w); 1800 spdk_jsonrpc_end_result(request, w); 1801 } 1802 SPDK_RPC_REGISTER("bdev_nvme_get_discovery_info", rpc_bdev_nvme_get_discovery_info, 1803 SPDK_RPC_RUNTIME) 1804 1805 enum error_injection_cmd_type { 1806 NVME_ADMIN_CMD = 1, 1807 NVME_IO_CMD, 1808 }; 1809 1810 struct rpc_add_error_injection { 1811 char *name; 1812 enum error_injection_cmd_type cmd_type; 1813 uint8_t opc; 1814 bool do_not_submit; 1815 uint64_t timeout_in_us; 1816 uint32_t err_count; 1817 uint8_t sct; 1818 uint8_t sc; 1819 }; 1820 1821 static void 1822 free_rpc_add_error_injection(struct rpc_add_error_injection *req) 1823 { 1824 free(req->name); 1825 } 1826 1827 static int 1828 rpc_error_injection_decode_cmd_type(const struct spdk_json_val *val, void *out) 1829 { 1830 int *cmd_type = out; 1831 1832 if (spdk_json_strequal(val, "admin")) { 1833 *cmd_type = NVME_ADMIN_CMD; 1834 } else if (spdk_json_strequal(val, "io")) { 1835 *cmd_type = NVME_IO_CMD; 1836 } else { 1837 SPDK_ERRLOG("Invalid parameter value: cmd_type\n"); 1838 return -EINVAL; 1839 } 1840 1841 return 0; 1842 } 1843 1844 static const struct spdk_json_object_decoder rpc_add_error_injection_decoders[] = { 1845 { "name", offsetof(struct rpc_add_error_injection, name), spdk_json_decode_string }, 1846 { "cmd_type", offsetof(struct rpc_add_error_injection, cmd_type), rpc_error_injection_decode_cmd_type }, 1847 { "opc", offsetof(struct rpc_add_error_injection, opc), spdk_json_decode_uint8 }, 1848 { "do_not_submit", offsetof(struct rpc_add_error_injection, do_not_submit), spdk_json_decode_bool, true }, 1849 { "timeout_in_us", offsetof(struct rpc_add_error_injection, timeout_in_us), spdk_json_decode_uint64, true }, 1850 { "err_count", offsetof(struct rpc_add_error_injection, err_count), spdk_json_decode_uint32, true }, 1851 { "sct", offsetof(struct rpc_add_error_injection, sct), spdk_json_decode_uint8, true}, 1852 { "sc", offsetof(struct rpc_add_error_injection, sc), spdk_json_decode_uint8, true}, 1853 }; 1854 1855 struct rpc_add_error_injection_ctx { 1856 struct spdk_jsonrpc_request *request; 1857 struct rpc_add_error_injection rpc; 1858 }; 1859 1860 static void 1861 rpc_add_error_injection_done(struct spdk_io_channel_iter *i, int status) 1862 { 1863 struct rpc_add_error_injection_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1864 1865 if (status) { 1866 spdk_jsonrpc_send_error_response(ctx->request, status, 1867 "Failed to add the error injection."); 1868 } else { 1869 spdk_jsonrpc_send_bool_response(ctx->request, true); 1870 } 1871 1872 free_rpc_add_error_injection(&ctx->rpc); 1873 free(ctx); 1874 } 1875 1876 static void 1877 rpc_add_error_injection_per_channel(struct spdk_io_channel_iter *i) 1878 { 1879 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 1880 struct rpc_add_error_injection_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1881 struct nvme_ctrlr_channel *ctrlr_ch = spdk_io_channel_get_ctx(ch); 1882 struct spdk_nvme_qpair *qpair = ctrlr_ch->qpair->qpair; 1883 struct spdk_nvme_ctrlr *ctrlr = ctrlr_ch->qpair->ctrlr->ctrlr; 1884 int rc = 0; 1885 1886 if (qpair != NULL) { 1887 rc = spdk_nvme_qpair_add_cmd_error_injection(ctrlr, qpair, ctx->rpc.opc, 1888 ctx->rpc.do_not_submit, ctx->rpc.timeout_in_us, ctx->rpc.err_count, 1889 ctx->rpc.sct, ctx->rpc.sc); 1890 } 1891 1892 spdk_for_each_channel_continue(i, rc); 1893 } 1894 1895 static void 1896 rpc_bdev_nvme_add_error_injection( 1897 struct spdk_jsonrpc_request *request, 1898 const struct spdk_json_val *params) 1899 { 1900 struct rpc_add_error_injection_ctx *ctx; 1901 struct nvme_ctrlr *nvme_ctrlr; 1902 int rc; 1903 1904 ctx = calloc(1, sizeof(*ctx)); 1905 if (!ctx) { 1906 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1907 return; 1908 } 1909 ctx->rpc.err_count = 1; 1910 ctx->request = request; 1911 1912 if (spdk_json_decode_object(params, 1913 rpc_add_error_injection_decoders, 1914 SPDK_COUNTOF(rpc_add_error_injection_decoders), 1915 &ctx->rpc)) { 1916 spdk_jsonrpc_send_error_response(request, -EINVAL, 1917 "Failed to parse the request"); 1918 goto cleanup; 1919 } 1920 1921 nvme_ctrlr = nvme_ctrlr_get_by_name(ctx->rpc.name); 1922 if (nvme_ctrlr == NULL) { 1923 SPDK_ERRLOG("No controller with specified name was found.\n"); 1924 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1925 goto cleanup; 1926 } 1927 1928 if (ctx->rpc.cmd_type == NVME_IO_CMD) { 1929 spdk_for_each_channel(nvme_ctrlr, 1930 rpc_add_error_injection_per_channel, 1931 ctx, 1932 rpc_add_error_injection_done); 1933 1934 return; 1935 } else { 1936 rc = spdk_nvme_qpair_add_cmd_error_injection(nvme_ctrlr->ctrlr, NULL, ctx->rpc.opc, 1937 ctx->rpc.do_not_submit, ctx->rpc.timeout_in_us, ctx->rpc.err_count, 1938 ctx->rpc.sct, ctx->rpc.sc); 1939 if (rc) { 1940 spdk_jsonrpc_send_error_response(request, -rc, 1941 "Failed to add the error injection"); 1942 } else { 1943 spdk_jsonrpc_send_bool_response(ctx->request, true); 1944 } 1945 } 1946 1947 cleanup: 1948 free_rpc_add_error_injection(&ctx->rpc); 1949 free(ctx); 1950 } 1951 SPDK_RPC_REGISTER("bdev_nvme_add_error_injection", rpc_bdev_nvme_add_error_injection, 1952 SPDK_RPC_RUNTIME) 1953 1954 struct rpc_remove_error_injection { 1955 char *name; 1956 enum error_injection_cmd_type cmd_type; 1957 uint8_t opc; 1958 }; 1959 1960 static void 1961 free_rpc_remove_error_injection(struct rpc_remove_error_injection *req) 1962 { 1963 free(req->name); 1964 } 1965 1966 static const struct spdk_json_object_decoder rpc_remove_error_injection_decoders[] = { 1967 { "name", offsetof(struct rpc_remove_error_injection, name), spdk_json_decode_string }, 1968 { "cmd_type", offsetof(struct rpc_remove_error_injection, cmd_type), rpc_error_injection_decode_cmd_type }, 1969 { "opc", offsetof(struct rpc_remove_error_injection, opc), spdk_json_decode_uint8 }, 1970 }; 1971 1972 struct rpc_remove_error_injection_ctx { 1973 struct spdk_jsonrpc_request *request; 1974 struct rpc_remove_error_injection rpc; 1975 }; 1976 1977 static void 1978 rpc_remove_error_injection_done(struct spdk_io_channel_iter *i, int status) 1979 { 1980 struct rpc_remove_error_injection_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1981 1982 if (status) { 1983 spdk_jsonrpc_send_error_response(ctx->request, status, 1984 "Failed to remove the error injection."); 1985 } else { 1986 spdk_jsonrpc_send_bool_response(ctx->request, true); 1987 } 1988 1989 free_rpc_remove_error_injection(&ctx->rpc); 1990 free(ctx); 1991 } 1992 1993 static void 1994 rpc_remove_error_injection_per_channel(struct spdk_io_channel_iter *i) 1995 { 1996 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 1997 struct rpc_remove_error_injection_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1998 struct nvme_ctrlr_channel *ctrlr_ch = spdk_io_channel_get_ctx(ch); 1999 struct spdk_nvme_qpair *qpair = ctrlr_ch->qpair->qpair; 2000 struct spdk_nvme_ctrlr *ctrlr = ctrlr_ch->qpair->ctrlr->ctrlr; 2001 2002 if (qpair != NULL) { 2003 spdk_nvme_qpair_remove_cmd_error_injection(ctrlr, qpair, ctx->rpc.opc); 2004 } 2005 2006 spdk_for_each_channel_continue(i, 0); 2007 } 2008 2009 static void 2010 rpc_bdev_nvme_remove_error_injection(struct spdk_jsonrpc_request *request, 2011 const struct spdk_json_val *params) 2012 { 2013 struct rpc_remove_error_injection_ctx *ctx; 2014 struct nvme_ctrlr *nvme_ctrlr; 2015 2016 ctx = calloc(1, sizeof(*ctx)); 2017 if (!ctx) { 2018 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 2019 return; 2020 } 2021 ctx->request = request; 2022 2023 if (spdk_json_decode_object(params, 2024 rpc_remove_error_injection_decoders, 2025 SPDK_COUNTOF(rpc_remove_error_injection_decoders), 2026 &ctx->rpc)) { 2027 spdk_jsonrpc_send_error_response(request, -EINVAL, 2028 "Failed to parse the request"); 2029 goto cleanup; 2030 } 2031 2032 nvme_ctrlr = nvme_ctrlr_get_by_name(ctx->rpc.name); 2033 if (nvme_ctrlr == NULL) { 2034 SPDK_ERRLOG("No controller with specified name was found.\n"); 2035 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 2036 goto cleanup; 2037 } 2038 2039 if (ctx->rpc.cmd_type == NVME_IO_CMD) { 2040 spdk_for_each_channel(nvme_ctrlr, 2041 rpc_remove_error_injection_per_channel, 2042 ctx, 2043 rpc_remove_error_injection_done); 2044 return; 2045 } else { 2046 spdk_nvme_qpair_remove_cmd_error_injection(nvme_ctrlr->ctrlr, NULL, ctx->rpc.opc); 2047 spdk_jsonrpc_send_bool_response(ctx->request, true); 2048 } 2049 2050 cleanup: 2051 free_rpc_remove_error_injection(&ctx->rpc); 2052 free(ctx); 2053 } 2054 SPDK_RPC_REGISTER("bdev_nvme_remove_error_injection", rpc_bdev_nvme_remove_error_injection, 2055 SPDK_RPC_RUNTIME) 2056 2057 struct rpc_get_io_paths { 2058 char *name; 2059 }; 2060 2061 static void 2062 free_rpc_get_io_paths(struct rpc_get_io_paths *r) 2063 { 2064 free(r->name); 2065 } 2066 2067 static const struct spdk_json_object_decoder rpc_get_io_paths_decoders[] = { 2068 {"name", offsetof(struct rpc_get_io_paths, name), spdk_json_decode_string, true}, 2069 }; 2070 2071 struct rpc_get_io_paths_ctx { 2072 struct rpc_get_io_paths req; 2073 struct spdk_jsonrpc_request *request; 2074 struct spdk_json_write_ctx *w; 2075 }; 2076 2077 static void 2078 rpc_bdev_nvme_get_io_paths_done(struct spdk_io_channel_iter *i, int status) 2079 { 2080 struct rpc_get_io_paths_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2081 2082 spdk_json_write_array_end(ctx->w); 2083 2084 spdk_json_write_object_end(ctx->w); 2085 2086 spdk_jsonrpc_end_result(ctx->request, ctx->w); 2087 2088 free_rpc_get_io_paths(&ctx->req); 2089 free(ctx); 2090 } 2091 2092 static void 2093 _rpc_bdev_nvme_get_io_paths(struct spdk_io_channel_iter *i) 2094 { 2095 struct spdk_io_channel *_ch = spdk_io_channel_iter_get_channel(i); 2096 struct nvme_poll_group *group = spdk_io_channel_get_ctx(_ch); 2097 struct rpc_get_io_paths_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2098 struct nvme_qpair *qpair; 2099 struct nvme_io_path *io_path; 2100 struct nvme_bdev *nbdev; 2101 2102 spdk_json_write_object_begin(ctx->w); 2103 2104 spdk_json_write_named_string(ctx->w, "thread", spdk_thread_get_name(spdk_get_thread())); 2105 2106 spdk_json_write_named_array_begin(ctx->w, "io_paths"); 2107 2108 TAILQ_FOREACH(qpair, &group->qpair_list, tailq) { 2109 TAILQ_FOREACH(io_path, &qpair->io_path_list, tailq) { 2110 nbdev = io_path->nvme_ns->bdev; 2111 2112 if (ctx->req.name != NULL && 2113 strcmp(ctx->req.name, nbdev->disk.name) != 0) { 2114 continue; 2115 } 2116 2117 nvme_io_path_info_json(ctx->w, io_path); 2118 } 2119 } 2120 2121 spdk_json_write_array_end(ctx->w); 2122 2123 spdk_json_write_object_end(ctx->w); 2124 2125 spdk_for_each_channel_continue(i, 0); 2126 } 2127 2128 static void 2129 rpc_bdev_nvme_get_io_paths(struct spdk_jsonrpc_request *request, 2130 const struct spdk_json_val *params) 2131 { 2132 struct rpc_get_io_paths_ctx *ctx; 2133 2134 ctx = calloc(1, sizeof(*ctx)); 2135 if (ctx == NULL) { 2136 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 2137 return; 2138 } 2139 2140 if (params != NULL && 2141 spdk_json_decode_object(params, rpc_get_io_paths_decoders, 2142 SPDK_COUNTOF(rpc_get_io_paths_decoders), 2143 &ctx->req)) { 2144 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2145 "bdev_nvme_get_io_paths requires no parameters"); 2146 2147 free_rpc_get_io_paths(&ctx->req); 2148 free(ctx); 2149 return; 2150 } 2151 2152 ctx->request = request; 2153 ctx->w = spdk_jsonrpc_begin_result(request); 2154 2155 spdk_json_write_object_begin(ctx->w); 2156 2157 spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 2158 2159 spdk_for_each_channel(&g_nvme_bdev_ctrlrs, 2160 _rpc_bdev_nvme_get_io_paths, 2161 ctx, 2162 rpc_bdev_nvme_get_io_paths_done); 2163 } 2164 SPDK_RPC_REGISTER("bdev_nvme_get_io_paths", rpc_bdev_nvme_get_io_paths, SPDK_RPC_RUNTIME) 2165 2166 struct rpc_bdev_nvme_set_preferred_path { 2167 char *name; 2168 uint16_t cntlid; 2169 }; 2170 2171 static void 2172 free_rpc_bdev_nvme_set_preferred_path(struct rpc_bdev_nvme_set_preferred_path *req) 2173 { 2174 free(req->name); 2175 } 2176 2177 static const struct spdk_json_object_decoder rpc_bdev_nvme_set_preferred_path_decoders[] = { 2178 {"name", offsetof(struct rpc_bdev_nvme_set_preferred_path, name), spdk_json_decode_string}, 2179 {"cntlid", offsetof(struct rpc_bdev_nvme_set_preferred_path, cntlid), spdk_json_decode_uint16}, 2180 }; 2181 2182 struct rpc_bdev_nvme_set_preferred_path_ctx { 2183 struct rpc_bdev_nvme_set_preferred_path req; 2184 struct spdk_jsonrpc_request *request; 2185 }; 2186 2187 static void 2188 rpc_bdev_nvme_set_preferred_path_done(void *cb_arg, int rc) 2189 { 2190 struct rpc_bdev_nvme_set_preferred_path_ctx *ctx = cb_arg; 2191 2192 if (rc == 0) { 2193 spdk_jsonrpc_send_bool_response(ctx->request, true); 2194 } else { 2195 spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc)); 2196 } 2197 2198 free_rpc_bdev_nvme_set_preferred_path(&ctx->req); 2199 free(ctx); 2200 } 2201 2202 static void 2203 rpc_bdev_nvme_set_preferred_path(struct spdk_jsonrpc_request *request, 2204 const struct spdk_json_val *params) 2205 { 2206 struct rpc_bdev_nvme_set_preferred_path_ctx *ctx; 2207 2208 ctx = calloc(1, sizeof(*ctx)); 2209 if (ctx == NULL) { 2210 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 2211 return; 2212 } 2213 2214 if (spdk_json_decode_object(params, rpc_bdev_nvme_set_preferred_path_decoders, 2215 SPDK_COUNTOF(rpc_bdev_nvme_set_preferred_path_decoders), 2216 &ctx->req)) { 2217 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2218 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2219 "spdk_json_decode_object failed"); 2220 goto cleanup; 2221 } 2222 2223 ctx->request = request; 2224 2225 bdev_nvme_set_preferred_path(ctx->req.name, ctx->req.cntlid, 2226 rpc_bdev_nvme_set_preferred_path_done, ctx); 2227 return; 2228 2229 cleanup: 2230 free_rpc_bdev_nvme_set_preferred_path(&ctx->req); 2231 free(ctx); 2232 } 2233 SPDK_RPC_REGISTER("bdev_nvme_set_preferred_path", rpc_bdev_nvme_set_preferred_path, 2234 SPDK_RPC_RUNTIME) 2235 2236 struct rpc_set_multipath_policy { 2237 char *name; 2238 enum bdev_nvme_multipath_policy policy; 2239 enum bdev_nvme_multipath_selector selector; 2240 uint32_t rr_min_io; 2241 }; 2242 2243 static void 2244 free_rpc_set_multipath_policy(struct rpc_set_multipath_policy *req) 2245 { 2246 free(req->name); 2247 } 2248 2249 static int 2250 rpc_decode_mp_policy(const struct spdk_json_val *val, void *out) 2251 { 2252 enum bdev_nvme_multipath_policy *policy = out; 2253 2254 if (spdk_json_strequal(val, "active_passive") == true) { 2255 *policy = BDEV_NVME_MP_POLICY_ACTIVE_PASSIVE; 2256 } else if (spdk_json_strequal(val, "active_active") == true) { 2257 *policy = BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE; 2258 } else { 2259 SPDK_NOTICELOG("Invalid parameter value: policy\n"); 2260 return -EINVAL; 2261 } 2262 2263 return 0; 2264 } 2265 2266 static int 2267 rpc_decode_mp_selector(const struct spdk_json_val *val, void *out) 2268 { 2269 enum bdev_nvme_multipath_selector *selector = out; 2270 2271 if (spdk_json_strequal(val, "round_robin") == true) { 2272 *selector = BDEV_NVME_MP_SELECTOR_ROUND_ROBIN; 2273 } else if (spdk_json_strequal(val, "queue_depth") == true) { 2274 *selector = BDEV_NVME_MP_SELECTOR_QUEUE_DEPTH; 2275 } else { 2276 SPDK_NOTICELOG("Invalid parameter value: selector\n"); 2277 return -EINVAL; 2278 } 2279 2280 return 0; 2281 } 2282 2283 static const struct spdk_json_object_decoder rpc_set_multipath_policy_decoders[] = { 2284 {"name", offsetof(struct rpc_set_multipath_policy, name), spdk_json_decode_string}, 2285 {"policy", offsetof(struct rpc_set_multipath_policy, policy), rpc_decode_mp_policy}, 2286 {"selector", offsetof(struct rpc_set_multipath_policy, selector), rpc_decode_mp_selector, true}, 2287 {"rr_min_io", offsetof(struct rpc_set_multipath_policy, rr_min_io), spdk_json_decode_uint32, true}, 2288 }; 2289 2290 struct rpc_set_multipath_policy_ctx { 2291 struct rpc_set_multipath_policy req; 2292 struct spdk_jsonrpc_request *request; 2293 }; 2294 2295 static void 2296 rpc_bdev_nvme_set_multipath_policy_done(void *cb_arg, int rc) 2297 { 2298 struct rpc_set_multipath_policy_ctx *ctx = cb_arg; 2299 2300 if (rc == 0) { 2301 spdk_jsonrpc_send_bool_response(ctx->request, true); 2302 } else { 2303 spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc)); 2304 } 2305 2306 free_rpc_set_multipath_policy(&ctx->req); 2307 free(ctx); 2308 } 2309 2310 static void 2311 rpc_bdev_nvme_set_multipath_policy(struct spdk_jsonrpc_request *request, 2312 const struct spdk_json_val *params) 2313 { 2314 struct rpc_set_multipath_policy_ctx *ctx; 2315 2316 ctx = calloc(1, sizeof(*ctx)); 2317 if (ctx == NULL) { 2318 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 2319 return; 2320 } 2321 2322 ctx->req.rr_min_io = UINT32_MAX; 2323 2324 if (spdk_json_decode_object(params, rpc_set_multipath_policy_decoders, 2325 SPDK_COUNTOF(rpc_set_multipath_policy_decoders), 2326 &ctx->req)) { 2327 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2328 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2329 "spdk_json_decode_object failed"); 2330 goto cleanup; 2331 } 2332 2333 ctx->request = request; 2334 2335 if (ctx->req.policy != BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE && ctx->req.selector > 0) { 2336 SPDK_ERRLOG("selector only works in active_active mode\n"); 2337 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2338 "spdk_json_decode_object failed"); 2339 goto cleanup; 2340 } 2341 2342 bdev_nvme_set_multipath_policy(ctx->req.name, ctx->req.policy, ctx->req.selector, 2343 ctx->req.rr_min_io, 2344 rpc_bdev_nvme_set_multipath_policy_done, ctx); 2345 return; 2346 2347 cleanup: 2348 free_rpc_set_multipath_policy(&ctx->req); 2349 free(ctx); 2350 } 2351 SPDK_RPC_REGISTER("bdev_nvme_set_multipath_policy", rpc_bdev_nvme_set_multipath_policy, 2352 SPDK_RPC_RUNTIME) 2353 2354 struct rpc_bdev_nvme_start_mdns_discovery { 2355 char *name; 2356 char *svcname; 2357 char *hostnqn; 2358 struct spdk_nvme_ctrlr_opts opts; 2359 struct nvme_ctrlr_opts bdev_opts; 2360 }; 2361 2362 static void 2363 free_rpc_bdev_nvme_start_mdns_discovery(struct rpc_bdev_nvme_start_mdns_discovery *req) 2364 { 2365 free(req->name); 2366 free(req->svcname); 2367 free(req->hostnqn); 2368 } 2369 2370 static const struct spdk_json_object_decoder rpc_bdev_nvme_start_mdns_discovery_decoders[] = { 2371 {"name", offsetof(struct rpc_bdev_nvme_start_mdns_discovery, name), spdk_json_decode_string}, 2372 {"svcname", offsetof(struct rpc_bdev_nvme_start_mdns_discovery, svcname), spdk_json_decode_string}, 2373 {"hostnqn", offsetof(struct rpc_bdev_nvme_start_mdns_discovery, hostnqn), spdk_json_decode_string, true}, 2374 }; 2375 2376 struct rpc_bdev_nvme_start_mdns_discovery_ctx { 2377 struct rpc_bdev_nvme_start_mdns_discovery req; 2378 struct spdk_jsonrpc_request *request; 2379 }; 2380 2381 static void 2382 rpc_bdev_nvme_start_mdns_discovery(struct spdk_jsonrpc_request *request, 2383 const struct spdk_json_val *params) 2384 { 2385 struct rpc_bdev_nvme_start_mdns_discovery_ctx *ctx; 2386 int rc; 2387 2388 ctx = calloc(1, sizeof(*ctx)); 2389 if (!ctx) { 2390 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 2391 return; 2392 } 2393 2394 spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.opts, sizeof(ctx->req.opts)); 2395 2396 if (spdk_json_decode_object(params, rpc_bdev_nvme_start_mdns_discovery_decoders, 2397 SPDK_COUNTOF(rpc_bdev_nvme_start_mdns_discovery_decoders), 2398 &ctx->req)) { 2399 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2400 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2401 "spdk_json_decode_object failed"); 2402 goto cleanup; 2403 } 2404 2405 if (ctx->req.hostnqn) { 2406 snprintf(ctx->req.opts.hostnqn, sizeof(ctx->req.opts.hostnqn), "%s", 2407 ctx->req.hostnqn); 2408 } 2409 ctx->request = request; 2410 rc = bdev_nvme_start_mdns_discovery(ctx->req.name, ctx->req.svcname, &ctx->req.opts, 2411 &ctx->req.bdev_opts); 2412 if (rc) { 2413 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 2414 } else { 2415 spdk_jsonrpc_send_bool_response(request, true); 2416 } 2417 2418 cleanup: 2419 free_rpc_bdev_nvme_start_mdns_discovery(&ctx->req); 2420 free(ctx); 2421 } 2422 SPDK_RPC_REGISTER("bdev_nvme_start_mdns_discovery", rpc_bdev_nvme_start_mdns_discovery, 2423 SPDK_RPC_RUNTIME) 2424 2425 struct rpc_bdev_nvme_stop_mdns_discovery { 2426 char *name; 2427 }; 2428 2429 static const struct spdk_json_object_decoder rpc_bdev_nvme_stop_mdns_discovery_decoders[] = { 2430 {"name", offsetof(struct rpc_bdev_nvme_stop_mdns_discovery, name), spdk_json_decode_string}, 2431 }; 2432 2433 struct rpc_bdev_nvme_stop_mdns_discovery_ctx { 2434 struct rpc_bdev_nvme_stop_mdns_discovery req; 2435 struct spdk_jsonrpc_request *request; 2436 }; 2437 2438 static void 2439 rpc_bdev_nvme_stop_mdns_discovery(struct spdk_jsonrpc_request *request, 2440 const struct spdk_json_val *params) 2441 { 2442 struct rpc_bdev_nvme_stop_mdns_discovery_ctx *ctx; 2443 int rc; 2444 2445 ctx = calloc(1, sizeof(*ctx)); 2446 if (!ctx) { 2447 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 2448 return; 2449 } 2450 2451 if (spdk_json_decode_object(params, rpc_bdev_nvme_stop_mdns_discovery_decoders, 2452 SPDK_COUNTOF(rpc_bdev_nvme_stop_mdns_discovery_decoders), 2453 &ctx->req)) { 2454 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2455 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2456 "spdk_json_decode_object failed"); 2457 goto cleanup; 2458 } 2459 2460 ctx->request = request; 2461 rc = bdev_nvme_stop_mdns_discovery(ctx->req.name); 2462 2463 if (rc) { 2464 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 2465 goto cleanup; 2466 } 2467 spdk_jsonrpc_send_bool_response(ctx->request, true); 2468 2469 cleanup: 2470 free(ctx->req.name); 2471 free(ctx); 2472 } 2473 SPDK_RPC_REGISTER("bdev_nvme_stop_mdns_discovery", rpc_bdev_nvme_stop_mdns_discovery, 2474 SPDK_RPC_RUNTIME) 2475 2476 static void 2477 rpc_bdev_nvme_get_mdns_discovery_info(struct spdk_jsonrpc_request *request, 2478 const struct spdk_json_val *params) 2479 { 2480 bdev_nvme_get_mdns_discovery_info(request); 2481 } 2482 2483 SPDK_RPC_REGISTER("bdev_nvme_get_mdns_discovery_info", rpc_bdev_nvme_get_mdns_discovery_info, 2484 SPDK_RPC_RUNTIME) 2485 2486 struct rpc_get_path_stat { 2487 char *name; 2488 }; 2489 2490 struct path_stat { 2491 struct spdk_bdev_io_stat stat; 2492 struct spdk_nvme_transport_id trid; 2493 struct nvme_ns *ns; 2494 }; 2495 2496 struct rpc_bdev_nvme_path_stat_ctx { 2497 struct spdk_jsonrpc_request *request; 2498 struct path_stat *path_stat; 2499 uint32_t num_paths; 2500 struct spdk_bdev_desc *desc; 2501 }; 2502 2503 static void 2504 free_rpc_get_path_stat(struct rpc_get_path_stat *req) 2505 { 2506 free(req->name); 2507 } 2508 2509 static const struct spdk_json_object_decoder rpc_get_path_stat_decoders[] = { 2510 {"name", offsetof(struct rpc_get_path_stat, name), spdk_json_decode_string}, 2511 }; 2512 2513 static void 2514 dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx) 2515 { 2516 } 2517 2518 static void 2519 rpc_bdev_nvme_path_stat_per_channel(struct spdk_io_channel_iter *i) 2520 { 2521 struct rpc_bdev_nvme_path_stat_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2522 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 2523 struct nvme_bdev_channel *nbdev_ch = spdk_io_channel_get_ctx(ch); 2524 struct nvme_io_path *io_path; 2525 struct path_stat *path_stat; 2526 uint32_t j; 2527 2528 assert(ctx->num_paths != 0); 2529 2530 for (j = 0; j < ctx->num_paths; j++) { 2531 path_stat = &ctx->path_stat[j]; 2532 2533 STAILQ_FOREACH(io_path, &nbdev_ch->io_path_list, stailq) { 2534 if (path_stat->ns == io_path->nvme_ns) { 2535 assert(io_path->stat != NULL); 2536 spdk_bdev_add_io_stat(&path_stat->stat, io_path->stat); 2537 } 2538 } 2539 } 2540 2541 spdk_for_each_channel_continue(i, 0); 2542 } 2543 2544 static void 2545 rpc_bdev_nvme_path_stat_done(struct spdk_io_channel_iter *i, int status) 2546 { 2547 struct rpc_bdev_nvme_path_stat_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2548 struct nvme_bdev *nbdev = spdk_io_channel_iter_get_io_device(i); 2549 struct spdk_json_write_ctx *w; 2550 struct path_stat *path_stat; 2551 uint32_t j; 2552 2553 assert(ctx->num_paths != 0); 2554 2555 w = spdk_jsonrpc_begin_result(ctx->request); 2556 spdk_json_write_object_begin(w); 2557 spdk_json_write_named_string(w, "name", nbdev->disk.name); 2558 spdk_json_write_named_array_begin(w, "stats"); 2559 2560 for (j = 0; j < ctx->num_paths; j++) { 2561 path_stat = &ctx->path_stat[j]; 2562 spdk_json_write_object_begin(w); 2563 2564 spdk_json_write_named_object_begin(w, "trid"); 2565 nvme_bdev_dump_trid_json(&path_stat->trid, w); 2566 spdk_json_write_object_end(w); 2567 2568 spdk_json_write_named_object_begin(w, "stat"); 2569 spdk_bdev_dump_io_stat_json(&path_stat->stat, w); 2570 spdk_json_write_object_end(w); 2571 2572 spdk_json_write_object_end(w); 2573 } 2574 2575 spdk_json_write_array_end(w); 2576 spdk_json_write_object_end(w); 2577 spdk_jsonrpc_end_result(ctx->request, w); 2578 2579 spdk_bdev_close(ctx->desc); 2580 free(ctx->path_stat); 2581 free(ctx); 2582 } 2583 2584 static void 2585 rpc_bdev_nvme_get_path_iostat(struct spdk_jsonrpc_request *request, 2586 const struct spdk_json_val *params) 2587 { 2588 struct rpc_get_path_stat req = {}; 2589 struct spdk_bdev_desc *desc = NULL; 2590 struct spdk_bdev *bdev; 2591 struct nvme_bdev *nbdev; 2592 struct nvme_ns *nvme_ns; 2593 struct path_stat *path_stat; 2594 struct rpc_bdev_nvme_path_stat_ctx *ctx; 2595 struct spdk_bdev_nvme_opts opts; 2596 uint32_t num_paths = 0, i = 0; 2597 int rc; 2598 2599 bdev_nvme_get_opts(&opts); 2600 if (!opts.io_path_stat) { 2601 SPDK_ERRLOG("RPC not enabled if enable_io_path_stat is false\n"); 2602 spdk_jsonrpc_send_error_response(request, -EPERM, 2603 "RPC not enabled if enable_io_path_stat is false"); 2604 return; 2605 } 2606 2607 if (spdk_json_decode_object(params, rpc_get_path_stat_decoders, 2608 SPDK_COUNTOF(rpc_get_path_stat_decoders), 2609 &req)) { 2610 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2611 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2612 "spdk_json_decode_object failed"); 2613 free_rpc_get_path_stat(&req); 2614 return; 2615 } 2616 2617 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 2618 if (rc != 0) { 2619 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 2620 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 2621 free_rpc_get_path_stat(&req); 2622 return; 2623 } 2624 2625 free_rpc_get_path_stat(&req); 2626 2627 ctx = calloc(1, sizeof(struct rpc_bdev_nvme_path_stat_ctx)); 2628 if (ctx == NULL) { 2629 spdk_bdev_close(desc); 2630 SPDK_ERRLOG("Failed to allocate rpc_bdev_nvme_path_stat_ctx struct\n"); 2631 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 2632 return; 2633 } 2634 2635 bdev = spdk_bdev_desc_get_bdev(desc); 2636 nbdev = bdev->ctxt; 2637 2638 pthread_mutex_lock(&nbdev->mutex); 2639 if (nbdev->ref == 0) { 2640 rc = -ENOENT; 2641 goto err; 2642 } 2643 2644 num_paths = nbdev->ref; 2645 path_stat = calloc(num_paths, sizeof(struct path_stat)); 2646 if (path_stat == NULL) { 2647 rc = -ENOMEM; 2648 SPDK_ERRLOG("Failed to allocate memory for path_stat.\n"); 2649 goto err; 2650 } 2651 2652 /* store the history stat */ 2653 TAILQ_FOREACH(nvme_ns, &nbdev->nvme_ns_list, tailq) { 2654 assert(i < num_paths); 2655 path_stat[i].ns = nvme_ns; 2656 path_stat[i].trid = nvme_ns->ctrlr->active_path_id->trid; 2657 2658 assert(nvme_ns->stat != NULL); 2659 memcpy(&path_stat[i].stat, nvme_ns->stat, sizeof(struct spdk_bdev_io_stat)); 2660 i++; 2661 } 2662 pthread_mutex_unlock(&nbdev->mutex); 2663 2664 ctx->request = request; 2665 ctx->desc = desc; 2666 ctx->path_stat = path_stat; 2667 ctx->num_paths = num_paths; 2668 2669 spdk_for_each_channel(nbdev, 2670 rpc_bdev_nvme_path_stat_per_channel, 2671 ctx, 2672 rpc_bdev_nvme_path_stat_done); 2673 return; 2674 2675 err: 2676 pthread_mutex_unlock(&nbdev->mutex); 2677 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 2678 spdk_bdev_close(desc); 2679 free(ctx); 2680 } 2681 SPDK_RPC_REGISTER("bdev_nvme_get_path_iostat", rpc_bdev_nvme_get_path_iostat, 2682 SPDK_RPC_RUNTIME) 2683