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