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