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