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