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