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