1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2019-2021 Mellanox Technologies LTD. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "bdev_nvme.h" 37 #include "common.h" 38 39 #include "spdk/config.h" 40 41 #include "spdk/string.h" 42 #include "spdk/rpc.h" 43 #include "spdk/util.h" 44 #include "spdk/env.h" 45 #include "spdk/nvme.h" 46 #include "spdk/nvme_spec.h" 47 48 #include "spdk/log.h" 49 #include "spdk/bdev_module.h" 50 51 struct open_descriptors { 52 void *desc; 53 struct spdk_bdev *bdev; 54 TAILQ_ENTRY(open_descriptors) tqlst; 55 struct spdk_thread *thread; 56 }; 57 typedef TAILQ_HEAD(, open_descriptors) open_descriptors_t; 58 59 static int 60 rpc_decode_action_on_timeout(const struct spdk_json_val *val, void *out) 61 { 62 enum spdk_bdev_timeout_action *action = out; 63 64 if (spdk_json_strequal(val, "none") == true) { 65 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE; 66 } else if (spdk_json_strequal(val, "abort") == true) { 67 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT; 68 } else if (spdk_json_strequal(val, "reset") == true) { 69 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET; 70 } else { 71 SPDK_NOTICELOG("Invalid parameter value: action_on_timeout\n"); 72 return -EINVAL; 73 } 74 75 return 0; 76 } 77 78 static const struct spdk_json_object_decoder rpc_bdev_nvme_options_decoders[] = { 79 {"action_on_timeout", offsetof(struct spdk_bdev_nvme_opts, action_on_timeout), rpc_decode_action_on_timeout, true}, 80 {"timeout_us", offsetof(struct spdk_bdev_nvme_opts, timeout_us), spdk_json_decode_uint64, true}, 81 {"timeout_admin_us", offsetof(struct spdk_bdev_nvme_opts, timeout_admin_us), spdk_json_decode_uint64, true}, 82 {"keep_alive_timeout_ms", offsetof(struct spdk_bdev_nvme_opts, keep_alive_timeout_ms), spdk_json_decode_uint32, true}, 83 {"retry_count", offsetof(struct spdk_bdev_nvme_opts, retry_count), spdk_json_decode_uint32, true}, 84 {"arbitration_burst", offsetof(struct spdk_bdev_nvme_opts, arbitration_burst), spdk_json_decode_uint32, true}, 85 {"low_priority_weight", offsetof(struct spdk_bdev_nvme_opts, low_priority_weight), spdk_json_decode_uint32, true}, 86 {"medium_priority_weight", offsetof(struct spdk_bdev_nvme_opts, medium_priority_weight), spdk_json_decode_uint32, true}, 87 {"high_priority_weight", offsetof(struct spdk_bdev_nvme_opts, high_priority_weight), spdk_json_decode_uint32, true}, 88 {"nvme_adminq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_adminq_poll_period_us), spdk_json_decode_uint64, true}, 89 {"nvme_ioq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_ioq_poll_period_us), spdk_json_decode_uint64, true}, 90 {"io_queue_requests", offsetof(struct spdk_bdev_nvme_opts, io_queue_requests), spdk_json_decode_uint32, true}, 91 {"delay_cmd_submit", offsetof(struct spdk_bdev_nvme_opts, delay_cmd_submit), spdk_json_decode_bool, true}, 92 }; 93 94 static void 95 rpc_bdev_nvme_set_options(struct spdk_jsonrpc_request *request, 96 const struct spdk_json_val *params) 97 { 98 struct spdk_bdev_nvme_opts opts; 99 int rc; 100 101 bdev_nvme_get_opts(&opts); 102 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_options_decoders, 103 SPDK_COUNTOF(rpc_bdev_nvme_options_decoders), 104 &opts)) { 105 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 106 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 107 "spdk_json_decode_object failed"); 108 return; 109 } 110 111 rc = bdev_nvme_set_opts(&opts); 112 if (rc) { 113 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 114 return; 115 } 116 117 spdk_jsonrpc_send_bool_response(request, true); 118 119 return; 120 } 121 SPDK_RPC_REGISTER("bdev_nvme_set_options", rpc_bdev_nvme_set_options, 122 SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) 123 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_options, set_bdev_nvme_options) 124 125 struct rpc_bdev_nvme_hotplug { 126 bool enabled; 127 uint64_t period_us; 128 }; 129 130 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders[] = { 131 {"enable", offsetof(struct rpc_bdev_nvme_hotplug, enabled), spdk_json_decode_bool, false}, 132 {"period_us", offsetof(struct rpc_bdev_nvme_hotplug, period_us), spdk_json_decode_uint64, true}, 133 }; 134 135 static void 136 rpc_bdev_nvme_set_hotplug_done(void *ctx) 137 { 138 struct spdk_jsonrpc_request *request = ctx; 139 140 spdk_jsonrpc_send_bool_response(request, true); 141 } 142 143 static void 144 rpc_bdev_nvme_set_hotplug(struct spdk_jsonrpc_request *request, 145 const struct spdk_json_val *params) 146 { 147 struct rpc_bdev_nvme_hotplug req = {false, 0}; 148 int rc; 149 150 if (spdk_json_decode_object(params, rpc_bdev_nvme_hotplug_decoders, 151 SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders), &req)) { 152 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 153 rc = -EINVAL; 154 goto invalid; 155 } 156 157 rc = bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_bdev_nvme_set_hotplug_done, 158 request); 159 if (rc) { 160 goto invalid; 161 } 162 163 return; 164 invalid: 165 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc)); 166 } 167 SPDK_RPC_REGISTER("bdev_nvme_set_hotplug", rpc_bdev_nvme_set_hotplug, SPDK_RPC_RUNTIME) 168 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_hotplug, set_bdev_nvme_hotplug) 169 170 struct rpc_bdev_nvme_attach_controller { 171 char *name; 172 char *trtype; 173 char *adrfam; 174 char *traddr; 175 char *trsvcid; 176 char *priority; 177 char *subnqn; 178 char *hostnqn; 179 char *hostaddr; 180 char *hostsvcid; 181 bool prchk_reftag; 182 bool prchk_guard; 183 uint64_t fabrics_connect_timeout_us; 184 struct spdk_nvme_ctrlr_opts opts; 185 }; 186 187 static void 188 free_rpc_bdev_nvme_attach_controller(struct rpc_bdev_nvme_attach_controller *req) 189 { 190 free(req->name); 191 free(req->trtype); 192 free(req->adrfam); 193 free(req->traddr); 194 free(req->trsvcid); 195 free(req->priority); 196 free(req->subnqn); 197 free(req->hostnqn); 198 free(req->hostaddr); 199 free(req->hostsvcid); 200 } 201 202 static const struct spdk_json_object_decoder rpc_bdev_nvme_attach_controller_decoders[] = { 203 {"name", offsetof(struct rpc_bdev_nvme_attach_controller, name), spdk_json_decode_string}, 204 {"trtype", offsetof(struct rpc_bdev_nvme_attach_controller, trtype), spdk_json_decode_string}, 205 {"traddr", offsetof(struct rpc_bdev_nvme_attach_controller, traddr), spdk_json_decode_string}, 206 207 {"adrfam", offsetof(struct rpc_bdev_nvme_attach_controller, adrfam), spdk_json_decode_string, true}, 208 {"trsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, trsvcid), spdk_json_decode_string, true}, 209 {"priority", offsetof(struct rpc_bdev_nvme_attach_controller, priority), spdk_json_decode_string, true}, 210 {"subnqn", offsetof(struct rpc_bdev_nvme_attach_controller, subnqn), spdk_json_decode_string, true}, 211 {"hostnqn", offsetof(struct rpc_bdev_nvme_attach_controller, hostnqn), spdk_json_decode_string, true}, 212 {"hostaddr", offsetof(struct rpc_bdev_nvme_attach_controller, hostaddr), spdk_json_decode_string, true}, 213 {"hostsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, hostsvcid), spdk_json_decode_string, true}, 214 215 {"prchk_reftag", offsetof(struct rpc_bdev_nvme_attach_controller, prchk_reftag), spdk_json_decode_bool, true}, 216 {"prchk_guard", offsetof(struct rpc_bdev_nvme_attach_controller, prchk_guard), spdk_json_decode_bool, true}, 217 {"hdgst", offsetof(struct rpc_bdev_nvme_attach_controller, opts.header_digest), spdk_json_decode_bool, true}, 218 {"ddgst", offsetof(struct rpc_bdev_nvme_attach_controller, opts.data_digest), spdk_json_decode_bool, true}, 219 {"fabrics_connect_timeout_us", offsetof(struct rpc_bdev_nvme_attach_controller, opts.fabrics_connect_timeout_us), spdk_json_decode_uint64, true}, 220 }; 221 222 #define NVME_MAX_BDEVS_PER_RPC 128 223 224 struct rpc_bdev_nvme_attach_controller_ctx { 225 struct rpc_bdev_nvme_attach_controller req; 226 uint32_t count; 227 size_t bdev_count; 228 const char *names[NVME_MAX_BDEVS_PER_RPC]; 229 struct spdk_jsonrpc_request *request; 230 }; 231 232 static void 233 rpc_bdev_nvme_attach_controller_examined(void *cb_ctx) 234 { 235 struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx; 236 struct spdk_jsonrpc_request *request = ctx->request; 237 struct spdk_json_write_ctx *w; 238 size_t i; 239 240 w = spdk_jsonrpc_begin_result(request); 241 spdk_json_write_array_begin(w); 242 for (i = 0; i < ctx->bdev_count; i++) { 243 spdk_json_write_string(w, ctx->names[i]); 244 } 245 spdk_json_write_array_end(w); 246 spdk_jsonrpc_end_result(request, w); 247 248 free_rpc_bdev_nvme_attach_controller(&ctx->req); 249 free(ctx); 250 } 251 252 static void 253 rpc_bdev_nvme_attach_controller_done(void *cb_ctx, size_t bdev_count, int rc) 254 { 255 struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx; 256 struct spdk_jsonrpc_request *request = ctx->request; 257 258 if (rc < 0) { 259 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 260 free_rpc_bdev_nvme_attach_controller(&ctx->req); 261 free(ctx); 262 return; 263 } 264 265 ctx->bdev_count = bdev_count; 266 spdk_bdev_wait_for_examine(rpc_bdev_nvme_attach_controller_examined, ctx); 267 } 268 269 static void 270 rpc_bdev_nvme_attach_controller(struct spdk_jsonrpc_request *request, 271 const struct spdk_json_val *params) 272 { 273 struct rpc_bdev_nvme_attach_controller_ctx *ctx; 274 struct spdk_nvme_transport_id trid = {}; 275 struct spdk_nvme_host_id hostid = {}; 276 uint32_t prchk_flags = 0; 277 struct nvme_ctrlr *ctrlr = NULL; 278 size_t len, maxlen; 279 int rc; 280 281 ctx = calloc(1, sizeof(*ctx)); 282 if (!ctx) { 283 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 284 return; 285 } 286 287 spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.opts, sizeof(ctx->req.opts)); 288 289 if (spdk_json_decode_object(params, rpc_bdev_nvme_attach_controller_decoders, 290 SPDK_COUNTOF(rpc_bdev_nvme_attach_controller_decoders), 291 &ctx->req)) { 292 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 293 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 294 "spdk_json_decode_object failed"); 295 goto cleanup; 296 } 297 298 /* Parse trstring */ 299 rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype); 300 if (rc < 0) { 301 SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype); 302 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 303 ctx->req.trtype); 304 goto cleanup; 305 } 306 307 /* Parse trtype */ 308 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype); 309 assert(rc == 0); 310 311 ctrlr = nvme_ctrlr_get_by_name(ctx->req.name); 312 313 /* Parse traddr */ 314 maxlen = sizeof(trid.traddr); 315 len = strnlen(ctx->req.traddr, maxlen); 316 if (len == maxlen) { 317 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s", 318 ctx->req.traddr); 319 goto cleanup; 320 } 321 memcpy(trid.traddr, ctx->req.traddr, len + 1); 322 323 /* Parse adrfam */ 324 if (ctx->req.adrfam) { 325 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam); 326 if (rc < 0) { 327 SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam); 328 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 329 ctx->req.adrfam); 330 goto cleanup; 331 } 332 } 333 334 /* Parse trsvcid */ 335 if (ctx->req.trsvcid) { 336 maxlen = sizeof(trid.trsvcid); 337 len = strnlen(ctx->req.trsvcid, maxlen); 338 if (len == maxlen) { 339 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s", 340 ctx->req.trsvcid); 341 goto cleanup; 342 } 343 memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1); 344 } 345 346 /* Parse priority for the NVMe-oF transport connection */ 347 if (ctx->req.priority) { 348 trid.priority = spdk_strtol(ctx->req.priority, 10); 349 } 350 351 /* Parse subnqn */ 352 if (ctx->req.subnqn) { 353 maxlen = sizeof(trid.subnqn); 354 len = strnlen(ctx->req.subnqn, maxlen); 355 if (len == maxlen) { 356 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s", 357 ctx->req.subnqn); 358 goto cleanup; 359 } 360 memcpy(trid.subnqn, ctx->req.subnqn, len + 1); 361 } 362 363 if (ctrlr && (ctx->req.hostaddr || ctx->req.hostnqn || ctx->req.hostsvcid || ctx->req.prchk_guard || 364 ctx->req.prchk_reftag)) { 365 goto conflicting_arguments; 366 } 367 368 if (ctx->req.hostaddr) { 369 maxlen = sizeof(hostid.hostaddr); 370 len = strnlen(ctx->req.hostaddr, maxlen); 371 if (len == maxlen) { 372 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s", 373 ctx->req.hostaddr); 374 goto cleanup; 375 } 376 memcpy(hostid.hostaddr, ctx->req.hostaddr, len + 1); 377 } 378 379 if (ctx->req.hostsvcid) { 380 maxlen = sizeof(hostid.hostsvcid); 381 len = strnlen(ctx->req.hostsvcid, maxlen); 382 if (len == maxlen) { 383 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s", 384 ctx->req.hostsvcid); 385 goto cleanup; 386 } 387 memcpy(hostid.hostsvcid, ctx->req.hostsvcid, len + 1); 388 } 389 390 if (ctx->req.prchk_reftag) { 391 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG; 392 } 393 394 if (ctx->req.prchk_guard) { 395 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD; 396 } 397 398 ctx->request = request; 399 ctx->count = NVME_MAX_BDEVS_PER_RPC; 400 rc = bdev_nvme_create(&trid, &hostid, ctx->req.name, ctx->names, ctx->count, ctx->req.hostnqn, 401 prchk_flags, rpc_bdev_nvme_attach_controller_done, ctx, &ctx->req.opts); 402 if (rc) { 403 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 404 goto cleanup; 405 } 406 407 return; 408 409 conflicting_arguments: 410 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 411 "Invalid agrgument list. Existing controller name cannot be combined with host information or PI options.\n"); 412 cleanup: 413 free_rpc_bdev_nvme_attach_controller(&ctx->req); 414 free(ctx); 415 } 416 SPDK_RPC_REGISTER("bdev_nvme_attach_controller", rpc_bdev_nvme_attach_controller, 417 SPDK_RPC_RUNTIME) 418 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_attach_controller, construct_nvme_bdev) 419 420 static void 421 rpc_dump_nvme_controller_info(struct nvme_ctrlr *nvme_ctrlr, void *ctx) 422 { 423 struct spdk_json_write_ctx *w = ctx; 424 struct spdk_nvme_transport_id *trid; 425 426 trid = nvme_ctrlr->connected_trid; 427 428 spdk_json_write_object_begin(w); 429 spdk_json_write_named_string(w, "name", nvme_ctrlr->name); 430 431 #ifdef SPDK_CONFIG_NVME_CUSE 432 size_t cuse_name_size = 128; 433 char cuse_name[cuse_name_size]; 434 435 int rc = spdk_nvme_cuse_get_ctrlr_name(nvme_ctrlr->ctrlr, cuse_name, &cuse_name_size); 436 if (rc == 0) { 437 spdk_json_write_named_string(w, "cuse_device", cuse_name); 438 } 439 #endif 440 441 spdk_json_write_named_object_begin(w, "trid"); 442 nvme_bdev_dump_trid_json(trid, w); 443 spdk_json_write_object_end(w); 444 445 spdk_json_write_object_end(w); 446 } 447 448 struct rpc_bdev_nvme_get_controllers { 449 char *name; 450 }; 451 452 static void 453 free_rpc_bdev_nvme_get_controllers(struct rpc_bdev_nvme_get_controllers *r) 454 { 455 free(r->name); 456 } 457 458 static const struct spdk_json_object_decoder rpc_bdev_nvme_get_controllers_decoders[] = { 459 {"name", offsetof(struct rpc_bdev_nvme_get_controllers, name), spdk_json_decode_string, true}, 460 }; 461 462 static void 463 rpc_bdev_nvme_get_controllers(struct spdk_jsonrpc_request *request, 464 const struct spdk_json_val *params) 465 { 466 struct rpc_bdev_nvme_get_controllers req = {}; 467 struct spdk_json_write_ctx *w; 468 struct nvme_ctrlr *ctrlr = NULL; 469 470 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_get_controllers_decoders, 471 SPDK_COUNTOF(rpc_bdev_nvme_get_controllers_decoders), 472 &req)) { 473 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 474 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 475 "spdk_json_decode_object failed"); 476 goto cleanup; 477 } 478 479 if (req.name) { 480 ctrlr = nvme_ctrlr_get_by_name(req.name); 481 if (ctrlr == NULL) { 482 SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name); 483 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Controller %s does not exist", req.name); 484 goto cleanup; 485 } 486 } 487 488 w = spdk_jsonrpc_begin_result(request); 489 spdk_json_write_array_begin(w); 490 491 if (ctrlr != NULL) { 492 rpc_dump_nvme_controller_info(ctrlr, w); 493 } else { 494 nvme_ctrlr_for_each(rpc_dump_nvme_controller_info, w); 495 } 496 497 spdk_json_write_array_end(w); 498 499 spdk_jsonrpc_end_result(request, w); 500 501 cleanup: 502 free_rpc_bdev_nvme_get_controllers(&req); 503 } 504 SPDK_RPC_REGISTER("bdev_nvme_get_controllers", rpc_bdev_nvme_get_controllers, SPDK_RPC_RUNTIME) 505 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_get_controllers, get_nvme_controllers) 506 507 struct rpc_bdev_nvme_detach_controller { 508 char *name; 509 char *trtype; 510 char *adrfam; 511 char *traddr; 512 char *trsvcid; 513 char *subnqn; 514 }; 515 516 static void 517 free_rpc_bdev_nvme_detach_controller(struct rpc_bdev_nvme_detach_controller *req) 518 { 519 free(req->name); 520 free(req->trtype); 521 free(req->adrfam); 522 free(req->traddr); 523 free(req->trsvcid); 524 free(req->subnqn); 525 } 526 527 static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_decoders[] = { 528 {"name", offsetof(struct rpc_bdev_nvme_detach_controller, name), spdk_json_decode_string}, 529 {"trtype", offsetof(struct rpc_bdev_nvme_detach_controller, trtype), spdk_json_decode_string, true}, 530 {"traddr", offsetof(struct rpc_bdev_nvme_detach_controller, traddr), spdk_json_decode_string, true}, 531 {"adrfam", offsetof(struct rpc_bdev_nvme_detach_controller, adrfam), spdk_json_decode_string, true}, 532 {"trsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, trsvcid), spdk_json_decode_string, true}, 533 {"subnqn", offsetof(struct rpc_bdev_nvme_detach_controller, subnqn), spdk_json_decode_string, true}, 534 }; 535 536 static void 537 rpc_bdev_nvme_detach_controller(struct spdk_jsonrpc_request *request, 538 const struct spdk_json_val *params) 539 { 540 struct rpc_bdev_nvme_detach_controller req = {NULL}; 541 struct spdk_nvme_transport_id trid = {}; 542 size_t len, maxlen; 543 int rc = 0; 544 bool all_trid_entries, one_trid_entry; 545 546 if (spdk_json_decode_object(params, rpc_bdev_nvme_detach_controller_decoders, 547 SPDK_COUNTOF(rpc_bdev_nvme_detach_controller_decoders), 548 &req)) { 549 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 550 "spdk_json_decode_object failed"); 551 goto cleanup; 552 } 553 554 all_trid_entries = req.trtype && req.traddr && req.adrfam && req.trsvcid && req.subnqn; 555 one_trid_entry = req.trtype || req.traddr || req.adrfam || req.trsvcid || req.subnqn; 556 557 if (all_trid_entries ^ one_trid_entry) { 558 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 559 "trtype, traddr, adrfam, trsvcid, subnqn must all be provided together or not at all."); 560 goto cleanup; 561 } 562 563 if (all_trid_entries) { 564 /* Parse trtype */ 565 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, req.trtype); 566 if (rc < 0) { 567 SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype); 568 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 569 req.trtype); 570 goto cleanup; 571 } 572 573 /* Parse traddr */ 574 maxlen = sizeof(trid.traddr); 575 len = strnlen(req.traddr, maxlen); 576 if (len == maxlen) { 577 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s", 578 req.traddr); 579 goto cleanup; 580 } 581 memcpy(trid.traddr, req.traddr, len + 1); 582 583 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, req.adrfam); 584 if (rc < 0) { 585 SPDK_ERRLOG("Failed to parse adrfam: %s\n", req.adrfam); 586 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 587 req.adrfam); 588 goto cleanup; 589 } 590 591 maxlen = sizeof(trid.trsvcid); 592 len = strnlen(req.trsvcid, maxlen); 593 if (len == maxlen) { 594 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s", 595 req.trsvcid); 596 goto cleanup; 597 } 598 memcpy(trid.trsvcid, req.trsvcid, len + 1); 599 600 maxlen = sizeof(trid.subnqn); 601 len = strnlen(req.subnqn, maxlen); 602 if (len == maxlen) { 603 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s", 604 req.subnqn); 605 goto cleanup; 606 } 607 memcpy(trid.subnqn, req.subnqn, len + 1); 608 rc = bdev_nvme_delete(req.name, &trid); 609 } else { 610 rc = bdev_nvme_delete(req.name, NULL); 611 } 612 613 if (rc != 0) { 614 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 615 goto cleanup; 616 } 617 618 spdk_jsonrpc_send_bool_response(request, true); 619 620 cleanup: 621 free_rpc_bdev_nvme_detach_controller(&req); 622 } 623 SPDK_RPC_REGISTER("bdev_nvme_detach_controller", rpc_bdev_nvme_detach_controller, 624 SPDK_RPC_RUNTIME) 625 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_detach_controller, delete_nvme_controller) 626 627 struct rpc_apply_firmware { 628 char *filename; 629 char *bdev_name; 630 }; 631 632 static void 633 free_rpc_apply_firmware(struct rpc_apply_firmware *req) 634 { 635 free(req->filename); 636 free(req->bdev_name); 637 } 638 639 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders[] = { 640 {"filename", offsetof(struct rpc_apply_firmware, filename), spdk_json_decode_string}, 641 {"bdev_name", offsetof(struct rpc_apply_firmware, bdev_name), spdk_json_decode_string}, 642 }; 643 644 struct firmware_update_info { 645 void *fw_image; 646 void *p; 647 unsigned int size; 648 unsigned int size_remaining; 649 unsigned int offset; 650 unsigned int transfer; 651 652 void *desc; 653 struct spdk_io_channel *ch; 654 struct spdk_jsonrpc_request *request; 655 struct spdk_nvme_ctrlr *ctrlr; 656 open_descriptors_t desc_head; 657 struct rpc_apply_firmware *req; 658 }; 659 660 static void 661 _apply_firmware_cleanup(void *ctx) 662 { 663 struct spdk_bdev_desc *desc = ctx; 664 665 spdk_bdev_close(desc); 666 } 667 668 static void 669 apply_firmware_cleanup(void *cb_arg) 670 { 671 struct open_descriptors *opt, *tmp; 672 struct firmware_update_info *firm_ctx = cb_arg; 673 674 if (!firm_ctx) { 675 return; 676 } 677 678 if (firm_ctx->fw_image) { 679 spdk_free(firm_ctx->fw_image); 680 } 681 682 if (firm_ctx->req) { 683 free_rpc_apply_firmware(firm_ctx->req); 684 free(firm_ctx->req); 685 } 686 687 if (firm_ctx->ch) { 688 spdk_put_io_channel(firm_ctx->ch); 689 } 690 691 TAILQ_FOREACH_SAFE(opt, &firm_ctx->desc_head, tqlst, tmp) { 692 TAILQ_REMOVE(&firm_ctx->desc_head, opt, tqlst); 693 /* Close the underlying bdev on its same opened thread. */ 694 if (opt->thread && opt->thread != spdk_get_thread()) { 695 spdk_thread_send_msg(opt->thread, _apply_firmware_cleanup, opt->desc); 696 } else { 697 spdk_bdev_close(opt->desc); 698 } 699 free(opt); 700 } 701 free(firm_ctx); 702 } 703 704 static void 705 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 706 { 707 struct spdk_json_write_ctx *w; 708 struct firmware_update_info *firm_ctx = cb_arg; 709 710 spdk_bdev_free_io(bdev_io); 711 712 if (!success) { 713 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 714 "firmware commit failed."); 715 apply_firmware_cleanup(firm_ctx); 716 return; 717 } 718 719 if (spdk_nvme_ctrlr_reset(firm_ctx->ctrlr) != 0) { 720 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 721 "Controller reset failed."); 722 apply_firmware_cleanup(firm_ctx); 723 return; 724 } 725 726 w = spdk_jsonrpc_begin_result(firm_ctx->request); 727 spdk_json_write_string(w, "firmware commit succeeded. Controller reset in progress."); 728 spdk_jsonrpc_end_result(firm_ctx->request, w); 729 apply_firmware_cleanup(firm_ctx); 730 } 731 732 static void 733 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 734 { 735 struct spdk_nvme_cmd cmd = {}; 736 struct spdk_nvme_fw_commit fw_commit; 737 int slot = 0; 738 int rc; 739 struct firmware_update_info *firm_ctx = cb_arg; 740 enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG; 741 742 if (!success) { 743 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 744 "firmware download failed ."); 745 spdk_bdev_free_io(bdev_io); 746 apply_firmware_cleanup(firm_ctx); 747 return; 748 } 749 750 firm_ctx->p += firm_ctx->transfer; 751 firm_ctx->offset += firm_ctx->transfer; 752 firm_ctx->size_remaining -= firm_ctx->transfer; 753 754 switch (firm_ctx->size_remaining) { 755 case 0: 756 /* firmware download completed. Commit firmware */ 757 memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit)); 758 fw_commit.fs = slot; 759 fw_commit.ca = commit_action; 760 761 cmd.opc = SPDK_NVME_OPC_FIRMWARE_COMMIT; 762 memcpy(&cmd.cdw10, &fw_commit, sizeof(uint32_t)); 763 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, NULL, 0, 764 apply_firmware_complete_reset, firm_ctx); 765 if (rc) { 766 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 767 "firmware commit failed."); 768 spdk_bdev_free_io(bdev_io); 769 apply_firmware_cleanup(firm_ctx); 770 return; 771 } 772 break; 773 default: 774 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 775 cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 776 777 cmd.cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer); 778 cmd.cdw11 = firm_ctx->offset >> 2; 779 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p, 780 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 781 if (rc) { 782 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 783 "firmware download failed."); 784 spdk_bdev_free_io(bdev_io); 785 apply_firmware_cleanup(firm_ctx); 786 return; 787 } 788 break; 789 } 790 } 791 792 static void 793 apply_firmware_open_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 794 { 795 } 796 797 static void 798 rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request, 799 const struct spdk_json_val *params) 800 { 801 int rc; 802 int fd = -1; 803 struct stat fw_stat; 804 struct spdk_nvme_ctrlr *ctrlr; 805 char msg[1024]; 806 struct spdk_bdev *bdev; 807 struct spdk_bdev *bdev2; 808 struct open_descriptors *opt; 809 struct spdk_bdev_desc *desc; 810 struct spdk_nvme_cmd *cmd; 811 struct firmware_update_info *firm_ctx; 812 813 firm_ctx = calloc(1, sizeof(struct firmware_update_info)); 814 if (!firm_ctx) { 815 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 816 "Memory allocation error."); 817 return; 818 } 819 firm_ctx->fw_image = NULL; 820 TAILQ_INIT(&firm_ctx->desc_head); 821 firm_ctx->request = request; 822 823 firm_ctx->req = calloc(1, sizeof(struct rpc_apply_firmware)); 824 if (!firm_ctx->req) { 825 snprintf(msg, sizeof(msg), "Memory allocation error."); 826 goto err; 827 } 828 829 if (spdk_json_decode_object(params, rpc_apply_firmware_decoders, 830 SPDK_COUNTOF(rpc_apply_firmware_decoders), firm_ctx->req)) { 831 snprintf(msg, sizeof(msg), "spdk_json_decode_object failed."); 832 goto err; 833 } 834 835 if ((bdev = spdk_bdev_get_by_name(firm_ctx->req->bdev_name)) == NULL) { 836 snprintf(msg, sizeof(msg), "bdev %s were not found", firm_ctx->req->bdev_name); 837 goto err; 838 } 839 840 if ((ctrlr = bdev_nvme_get_ctrlr(bdev)) == NULL) { 841 snprintf(msg, sizeof(msg), "Controller information for %s were not found.", 842 firm_ctx->req->bdev_name); 843 goto err; 844 } 845 firm_ctx->ctrlr = ctrlr; 846 847 for (bdev2 = spdk_bdev_first(); bdev2; bdev2 = spdk_bdev_next(bdev2)) { 848 849 if (bdev_nvme_get_ctrlr(bdev2) != ctrlr) { 850 continue; 851 } 852 853 if (!(opt = malloc(sizeof(struct open_descriptors)))) { 854 snprintf(msg, sizeof(msg), "Memory allocation error."); 855 goto err; 856 } 857 858 if (spdk_bdev_open_ext(spdk_bdev_get_name(bdev2), true, apply_firmware_open_cb, NULL, &desc) != 0) { 859 snprintf(msg, sizeof(msg), "Device %s is in use.", firm_ctx->req->bdev_name); 860 free(opt); 861 goto err; 862 } 863 864 /* Save the thread where the base device is opened */ 865 opt->thread = spdk_get_thread(); 866 867 opt->desc = desc; 868 opt->bdev = bdev; 869 TAILQ_INSERT_TAIL(&firm_ctx->desc_head, opt, tqlst); 870 } 871 872 /* 873 * find a descriptor associated with our bdev 874 */ 875 firm_ctx->desc = NULL; 876 TAILQ_FOREACH(opt, &firm_ctx->desc_head, tqlst) { 877 if (opt->bdev == bdev) { 878 firm_ctx->desc = opt->desc; 879 break; 880 } 881 } 882 883 if (!firm_ctx->desc) { 884 snprintf(msg, sizeof(msg), "No descriptor were found."); 885 goto err; 886 } 887 888 firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc); 889 if (!firm_ctx->ch) { 890 snprintf(msg, sizeof(msg), "No channels were found."); 891 goto err; 892 } 893 894 fd = open(firm_ctx->req->filename, O_RDONLY); 895 if (fd < 0) { 896 snprintf(msg, sizeof(msg), "open file failed."); 897 goto err; 898 } 899 900 rc = fstat(fd, &fw_stat); 901 if (rc < 0) { 902 close(fd); 903 snprintf(msg, sizeof(msg), "fstat failed."); 904 goto err; 905 } 906 907 firm_ctx->size = fw_stat.st_size; 908 if (fw_stat.st_size % 4) { 909 close(fd); 910 snprintf(msg, sizeof(msg), "Firmware image size is not multiple of 4."); 911 goto err; 912 } 913 914 firm_ctx->fw_image = spdk_zmalloc(firm_ctx->size, 4096, NULL, 915 SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 916 if (!firm_ctx->fw_image) { 917 close(fd); 918 snprintf(msg, sizeof(msg), "Memory allocation error."); 919 goto err; 920 } 921 firm_ctx->p = firm_ctx->fw_image; 922 923 if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) { 924 close(fd); 925 snprintf(msg, sizeof(msg), "Read firmware image failed!"); 926 goto err; 927 } 928 close(fd); 929 930 firm_ctx->offset = 0; 931 firm_ctx->size_remaining = firm_ctx->size; 932 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 933 934 cmd = malloc(sizeof(struct spdk_nvme_cmd)); 935 if (!cmd) { 936 snprintf(msg, sizeof(msg), "Memory allocation error."); 937 goto err; 938 } 939 memset(cmd, 0, sizeof(struct spdk_nvme_cmd)); 940 cmd->opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 941 942 cmd->cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer); 943 cmd->cdw11 = firm_ctx->offset >> 2; 944 945 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, cmd, firm_ctx->p, 946 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 947 if (rc == 0) { 948 /* normal return here. */ 949 return; 950 } 951 952 free(cmd); 953 snprintf(msg, sizeof(msg), "Read firmware image failed!"); 954 err: 955 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 956 apply_firmware_cleanup(firm_ctx); 957 } 958 SPDK_RPC_REGISTER("bdev_nvme_apply_firmware", rpc_bdev_nvme_apply_firmware, SPDK_RPC_RUNTIME) 959 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_apply_firmware, apply_nvme_firmware) 960 961 struct rpc_bdev_nvme_transport_stat_ctx { 962 struct spdk_jsonrpc_request *request; 963 struct spdk_json_write_ctx *w; 964 }; 965 966 static void 967 rpc_bdev_nvme_rdma_stats(struct spdk_json_write_ctx *w, 968 struct spdk_nvme_transport_poll_group_stat *stat) 969 { 970 struct spdk_nvme_rdma_device_stat *device_stats; 971 uint32_t i; 972 973 spdk_json_write_named_array_begin(w, "devices"); 974 975 for (i = 0; i < stat->rdma.num_devices; i++) { 976 device_stats = &stat->rdma.device_stats[i]; 977 spdk_json_write_object_begin(w); 978 spdk_json_write_named_string(w, "dev_name", device_stats->name); 979 spdk_json_write_named_uint64(w, "polls", device_stats->polls); 980 spdk_json_write_named_uint64(w, "idle_polls", device_stats->idle_polls); 981 spdk_json_write_named_uint64(w, "completions", device_stats->completions); 982 spdk_json_write_named_uint64(w, "queued_requests", device_stats->queued_requests); 983 spdk_json_write_named_uint64(w, "total_send_wrs", device_stats->total_send_wrs); 984 spdk_json_write_named_uint64(w, "send_doorbell_updates", device_stats->send_doorbell_updates); 985 spdk_json_write_named_uint64(w, "total_recv_wrs", device_stats->total_recv_wrs); 986 spdk_json_write_named_uint64(w, "recv_doorbell_updates", device_stats->recv_doorbell_updates); 987 spdk_json_write_object_end(w); 988 } 989 spdk_json_write_array_end(w); 990 } 991 992 static void 993 rpc_bdev_nvme_pcie_stats(struct spdk_json_write_ctx *w, 994 struct spdk_nvme_transport_poll_group_stat *stat) 995 { 996 spdk_json_write_named_uint64(w, "polls", stat->pcie.polls); 997 spdk_json_write_named_uint64(w, "idle_polls", stat->pcie.idle_polls); 998 spdk_json_write_named_uint64(w, "completions", stat->pcie.completions); 999 spdk_json_write_named_uint64(w, "cq_doorbell_updates", stat->pcie.cq_doorbell_updates); 1000 spdk_json_write_named_uint64(w, "queued_requests", stat->pcie.queued_requests); 1001 spdk_json_write_named_uint64(w, "submitted_requests", stat->pcie.submitted_requests); 1002 spdk_json_write_named_uint64(w, "sq_doobell_updates", stat->pcie.sq_doobell_updates); 1003 } 1004 1005 static void 1006 rpc_bdev_nvme_stats_per_channel(struct spdk_io_channel_iter *i) 1007 { 1008 struct rpc_bdev_nvme_transport_stat_ctx *ctx; 1009 struct spdk_io_channel *ch; 1010 struct nvme_poll_group *group; 1011 struct spdk_nvme_poll_group_stat *stat; 1012 struct spdk_nvme_transport_poll_group_stat *tr_stat; 1013 uint32_t j; 1014 int rc; 1015 1016 ctx = spdk_io_channel_iter_get_ctx(i); 1017 ch = spdk_io_channel_iter_get_channel(i); 1018 group = spdk_io_channel_get_ctx(ch); 1019 1020 rc = spdk_nvme_poll_group_get_stats(group->group, &stat); 1021 if (rc) { 1022 spdk_for_each_channel_continue(i, rc); 1023 return; 1024 } 1025 1026 spdk_json_write_object_begin(ctx->w); 1027 spdk_json_write_named_string(ctx->w, "thread", spdk_thread_get_name(spdk_get_thread())); 1028 spdk_json_write_named_array_begin(ctx->w, "transports"); 1029 1030 for (j = 0; j < stat->num_transports; j++) { 1031 tr_stat = stat->transport_stat[j]; 1032 spdk_json_write_object_begin(ctx->w); 1033 spdk_json_write_named_string(ctx->w, "trname", spdk_nvme_transport_id_trtype_str(tr_stat->trtype)); 1034 1035 switch (stat->transport_stat[j]->trtype) { 1036 case SPDK_NVME_TRANSPORT_RDMA: 1037 rpc_bdev_nvme_rdma_stats(ctx->w, tr_stat); 1038 break; 1039 case SPDK_NVME_TRANSPORT_PCIE: 1040 rpc_bdev_nvme_pcie_stats(ctx->w, tr_stat); 1041 break; 1042 default: 1043 SPDK_WARNLOG("Can't handle trtype %d %s\n", tr_stat->trtype, 1044 spdk_nvme_transport_id_trtype_str(tr_stat->trtype)); 1045 } 1046 spdk_json_write_object_end(ctx->w); 1047 } 1048 /* transports array */ 1049 spdk_json_write_array_end(ctx->w); 1050 spdk_json_write_object_end(ctx->w); 1051 1052 spdk_nvme_poll_group_free_stats(group->group, stat); 1053 spdk_for_each_channel_continue(i, 0); 1054 } 1055 1056 static void 1057 rpc_bdev_nvme_stats_done(struct spdk_io_channel_iter *i, int status) 1058 { 1059 struct rpc_bdev_nvme_transport_stat_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1060 1061 spdk_json_write_array_end(ctx->w); 1062 spdk_json_write_object_end(ctx->w); 1063 spdk_jsonrpc_end_result(ctx->request, ctx->w); 1064 free(ctx); 1065 } 1066 1067 static void 1068 rpc_bdev_nvme_get_transport_statistics(struct spdk_jsonrpc_request *request, 1069 const struct spdk_json_val *params) 1070 { 1071 struct rpc_bdev_nvme_transport_stat_ctx *ctx; 1072 1073 if (params) { 1074 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1075 "'bdev_nvme_get_transport_statistics' requires no arguments"); 1076 return; 1077 } 1078 1079 ctx = calloc(1, sizeof(*ctx)); 1080 if (!ctx) { 1081 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1082 "Memory allocation error"); 1083 return; 1084 } 1085 ctx->request = request; 1086 ctx->w = spdk_jsonrpc_begin_result(ctx->request); 1087 spdk_json_write_object_begin(ctx->w); 1088 spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 1089 1090 spdk_for_each_channel(&g_nvme_ctrlrs, 1091 rpc_bdev_nvme_stats_per_channel, 1092 ctx, 1093 rpc_bdev_nvme_stats_done); 1094 } 1095 SPDK_RPC_REGISTER("bdev_nvme_get_transport_statistics", rpc_bdev_nvme_get_transport_statistics, 1096 SPDK_RPC_RUNTIME) 1097 1098 struct rpc_bdev_nvme_reset_controller_req { 1099 char *name; 1100 }; 1101 1102 static void 1103 free_rpc_bdev_nvme_reset_controller_req(struct rpc_bdev_nvme_reset_controller_req *r) 1104 { 1105 free(r->name); 1106 } 1107 1108 static const struct spdk_json_object_decoder rpc_bdev_nvme_reset_controller_req_decoders[] = { 1109 {"name", offsetof(struct rpc_bdev_nvme_reset_controller_req, name), spdk_json_decode_string}, 1110 }; 1111 1112 static void 1113 _rpc_bdev_nvme_reset_controller_cb(void *cb_arg, int rc) 1114 { 1115 struct spdk_jsonrpc_request *request = cb_arg; 1116 1117 spdk_jsonrpc_send_bool_response(request, rc == 0); 1118 } 1119 1120 static void 1121 rpc_bdev_nvme_reset_controller(struct spdk_jsonrpc_request *request, 1122 const struct spdk_json_val *params) 1123 { 1124 struct rpc_bdev_nvme_reset_controller_req req = {NULL}; 1125 struct nvme_ctrlr *nvme_ctrlr; 1126 int rc; 1127 1128 if (spdk_json_decode_object(params, rpc_bdev_nvme_reset_controller_req_decoders, 1129 SPDK_COUNTOF(rpc_bdev_nvme_reset_controller_req_decoders), 1130 &req)) { 1131 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1132 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(EINVAL)); 1133 goto cleanup; 1134 } 1135 1136 nvme_ctrlr = nvme_ctrlr_get_by_name(req.name); 1137 if (nvme_ctrlr == NULL) { 1138 SPDK_ERRLOG("Failed at device lookup\n"); 1139 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 1140 goto cleanup; 1141 } 1142 1143 rc = bdev_nvme_reset_rpc(nvme_ctrlr, _rpc_bdev_nvme_reset_controller_cb, request); 1144 if (rc != 0) { 1145 SPDK_NOTICELOG("Failed at bdev_nvme_reset_rpc\n"); 1146 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc)); 1147 } 1148 1149 cleanup: 1150 free_rpc_bdev_nvme_reset_controller_req(&req); 1151 } 1152 SPDK_RPC_REGISTER("bdev_nvme_reset_controller", rpc_bdev_nvme_reset_controller, SPDK_RPC_RUNTIME) 1153 1154 struct rpc_get_controller_health_info { 1155 char *name; 1156 }; 1157 1158 struct spdk_nvme_health_info_context { 1159 struct spdk_jsonrpc_request *request; 1160 struct spdk_nvme_ctrlr *ctrlr; 1161 struct spdk_nvme_health_information_page health_page; 1162 }; 1163 1164 static void 1165 free_rpc_get_controller_health_info(struct rpc_get_controller_health_info *r) 1166 { 1167 free(r->name); 1168 } 1169 1170 static const struct spdk_json_object_decoder rpc_get_controller_health_info_decoders[] = { 1171 {"name", offsetof(struct rpc_get_controller_health_info, name), spdk_json_decode_string, true}, 1172 }; 1173 1174 static void nvme_health_info_cleanup(struct spdk_nvme_health_info_context *context, bool response) 1175 { 1176 if (response == true) { 1177 spdk_jsonrpc_send_error_response(context->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1178 "Internal error."); 1179 } 1180 1181 free(context); 1182 } 1183 1184 static void 1185 get_health_log_page_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl) 1186 { 1187 int i; 1188 char buf[128]; 1189 struct spdk_nvme_health_info_context *context = cb_arg; 1190 struct spdk_jsonrpc_request *request = context->request; 1191 struct spdk_json_write_ctx *w; 1192 struct spdk_nvme_ctrlr *ctrlr = context->ctrlr; 1193 const struct spdk_nvme_transport_id *trid = NULL; 1194 const struct spdk_nvme_ctrlr_data *cdata = NULL; 1195 struct spdk_nvme_health_information_page *health_page = NULL; 1196 1197 if (spdk_nvme_cpl_is_error(cpl)) { 1198 nvme_health_info_cleanup(context, true); 1199 SPDK_ERRLOG("get log page failed\n"); 1200 return; 1201 } 1202 1203 if (ctrlr == NULL) { 1204 nvme_health_info_cleanup(context, true); 1205 SPDK_ERRLOG("ctrlr is NULL\n"); 1206 return; 1207 } else { 1208 trid = spdk_nvme_ctrlr_get_transport_id(ctrlr); 1209 cdata = spdk_nvme_ctrlr_get_data(ctrlr); 1210 health_page = &(context->health_page); 1211 } 1212 1213 w = spdk_jsonrpc_begin_result(request); 1214 1215 spdk_json_write_object_begin(w); 1216 snprintf(buf, sizeof(cdata->mn) + 1, "%s", cdata->mn); 1217 spdk_str_trim(buf); 1218 spdk_json_write_named_string(w, "model_number", buf); 1219 snprintf(buf, sizeof(cdata->sn) + 1, "%s", cdata->sn); 1220 spdk_str_trim(buf); 1221 spdk_json_write_named_string(w, "serial_number", buf); 1222 snprintf(buf, sizeof(cdata->fr) + 1, "%s", cdata->fr); 1223 spdk_str_trim(buf); 1224 spdk_json_write_named_string(w, "firmware_revision", buf); 1225 spdk_json_write_named_string(w, "traddr", trid->traddr); 1226 spdk_json_write_named_uint64(w, "temperature_celsius", health_page->temperature - 273); 1227 spdk_json_write_named_uint64(w, "available_spare_percentage", health_page->available_spare); 1228 spdk_json_write_named_uint64(w, "available_spare_threshold_percentage", 1229 health_page->available_spare_threshold); 1230 spdk_json_write_named_uint64(w, "percentage_used", health_page->percentage_used); 1231 spdk_json_write_named_uint128(w, "data_units_read", 1232 health_page->data_units_read[0], health_page->data_units_read[1]); 1233 spdk_json_write_named_uint128(w, "data_units_written", 1234 health_page->data_units_written[0], health_page->data_units_written[1]); 1235 spdk_json_write_named_uint128(w, "host_read_commands", 1236 health_page->host_read_commands[0], health_page->host_read_commands[1]); 1237 spdk_json_write_named_uint128(w, "host_write_commands", 1238 health_page->host_write_commands[0], health_page->host_write_commands[1]); 1239 spdk_json_write_named_uint128(w, "controller_busy_time", 1240 health_page->controller_busy_time[0], health_page->controller_busy_time[1]); 1241 spdk_json_write_named_uint128(w, "power_cycles", 1242 health_page->power_cycles[0], health_page->power_cycles[1]); 1243 spdk_json_write_named_uint128(w, "power_on_hours", 1244 health_page->power_on_hours[0], health_page->power_on_hours[1]); 1245 spdk_json_write_named_uint128(w, "unsafe_shutdowns", 1246 health_page->unsafe_shutdowns[0], health_page->unsafe_shutdowns[1]); 1247 spdk_json_write_named_uint128(w, "media_errors", 1248 health_page->media_errors[0], health_page->media_errors[1]); 1249 spdk_json_write_named_uint128(w, "num_err_log_entries", 1250 health_page->num_error_info_log_entries[0], health_page->num_error_info_log_entries[1]); 1251 spdk_json_write_named_uint64(w, "warning_temperature_time_minutes", health_page->warning_temp_time); 1252 spdk_json_write_named_uint64(w, "critical_composite_temperature_time_minutes", 1253 health_page->critical_temp_time); 1254 for (i = 0; i < 8; i++) { 1255 if (health_page->temp_sensor[i] != 0) { 1256 spdk_json_write_named_uint64(w, "temperature_sensor_celsius", health_page->temp_sensor[i] - 273); 1257 } 1258 } 1259 spdk_json_write_object_end(w); 1260 1261 spdk_jsonrpc_end_result(request, w); 1262 nvme_health_info_cleanup(context, false); 1263 } 1264 1265 static void 1266 get_health_log_page(struct spdk_nvme_health_info_context *context) 1267 { 1268 struct spdk_nvme_ctrlr *ctrlr = context->ctrlr; 1269 1270 if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_HEALTH_INFORMATION, 1271 SPDK_NVME_GLOBAL_NS_TAG, 1272 &(context->health_page), sizeof(context->health_page), 0, 1273 get_health_log_page_completion, context)) { 1274 nvme_health_info_cleanup(context, true); 1275 SPDK_ERRLOG("spdk_nvme_ctrlr_cmd_get_log_page() failed\n"); 1276 } 1277 } 1278 1279 static void 1280 get_temperature_threshold_feature_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl) 1281 { 1282 struct spdk_nvme_health_info_context *context = cb_arg; 1283 1284 if (spdk_nvme_cpl_is_error(cpl)) { 1285 nvme_health_info_cleanup(context, true); 1286 SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed in completion\n"); 1287 } else { 1288 get_health_log_page(context); 1289 } 1290 } 1291 1292 static int 1293 get_temperature_threshold_feature(struct spdk_nvme_health_info_context *context) 1294 { 1295 struct spdk_nvme_cmd cmd = {}; 1296 1297 cmd.opc = SPDK_NVME_OPC_GET_FEATURES; 1298 cmd.cdw10 = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD; 1299 1300 return spdk_nvme_ctrlr_cmd_admin_raw(context->ctrlr, &cmd, NULL, 0, 1301 get_temperature_threshold_feature_completion, context); 1302 } 1303 1304 static void 1305 get_controller_health_info(struct spdk_jsonrpc_request *request, struct spdk_nvme_ctrlr *ctrlr) 1306 { 1307 struct spdk_nvme_health_info_context *context; 1308 1309 context = calloc(1, sizeof(struct spdk_nvme_health_info_context)); 1310 if (!context) { 1311 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1312 "Memory allocation error."); 1313 return; 1314 } 1315 1316 context->request = request; 1317 context->ctrlr = ctrlr; 1318 1319 if (get_temperature_threshold_feature(context)) { 1320 nvme_health_info_cleanup(context, true); 1321 SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed to submit\n"); 1322 } 1323 1324 return; 1325 } 1326 1327 static void 1328 rpc_bdev_nvme_get_controller_health_info(struct spdk_jsonrpc_request *request, 1329 const struct spdk_json_val *params) 1330 { 1331 struct rpc_get_controller_health_info req = {}; 1332 struct nvme_ctrlr *nvme_ctrlr = NULL; 1333 1334 if (!params) { 1335 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1336 "Missing device name"); 1337 1338 return; 1339 } 1340 if (spdk_json_decode_object(params, rpc_get_controller_health_info_decoders, 1341 SPDK_COUNTOF(rpc_get_controller_health_info_decoders), &req)) { 1342 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1343 free_rpc_get_controller_health_info(&req); 1344 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1345 "Invalid parameters"); 1346 1347 return; 1348 } 1349 1350 nvme_ctrlr = nvme_ctrlr_get_by_name(req.name); 1351 1352 if (!nvme_ctrlr) { 1353 SPDK_ERRLOG("nvme ctrlr name '%s' does not exist\n", req.name); 1354 free_rpc_get_controller_health_info(&req); 1355 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1356 "Device not found"); 1357 return; 1358 } 1359 1360 get_controller_health_info(request, nvme_ctrlr->ctrlr); 1361 free_rpc_get_controller_health_info(&req); 1362 1363 return; 1364 } 1365 SPDK_RPC_REGISTER("bdev_nvme_get_controller_health_info", 1366 rpc_bdev_nvme_get_controller_health_info, SPDK_RPC_RUNTIME) 1367