1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2019 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 45 #include "spdk/log.h" 46 #include "spdk/bdev_module.h" 47 48 struct open_descriptors { 49 void *desc; 50 struct spdk_bdev *bdev; 51 TAILQ_ENTRY(open_descriptors) tqlst; 52 struct spdk_thread *thread; 53 }; 54 typedef TAILQ_HEAD(, open_descriptors) open_descriptors_t; 55 56 static int 57 rpc_decode_action_on_timeout(const struct spdk_json_val *val, void *out) 58 { 59 enum spdk_bdev_timeout_action *action = out; 60 61 if (spdk_json_strequal(val, "none") == true) { 62 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE; 63 } else if (spdk_json_strequal(val, "abort") == true) { 64 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT; 65 } else if (spdk_json_strequal(val, "reset") == true) { 66 *action = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET; 67 } else { 68 SPDK_NOTICELOG("Invalid parameter value: action_on_timeout\n"); 69 return -EINVAL; 70 } 71 72 return 0; 73 } 74 75 static const struct spdk_json_object_decoder rpc_bdev_nvme_options_decoders[] = { 76 {"action_on_timeout", offsetof(struct spdk_bdev_nvme_opts, action_on_timeout), rpc_decode_action_on_timeout, true}, 77 {"timeout_us", offsetof(struct spdk_bdev_nvme_opts, timeout_us), spdk_json_decode_uint64, true}, 78 {"retry_count", offsetof(struct spdk_bdev_nvme_opts, retry_count), spdk_json_decode_uint32, true}, 79 {"arbitration_burst", offsetof(struct spdk_bdev_nvme_opts, arbitration_burst), spdk_json_decode_uint32, true}, 80 {"low_priority_weight", offsetof(struct spdk_bdev_nvme_opts, low_priority_weight), spdk_json_decode_uint32, true}, 81 {"medium_priority_weight", offsetof(struct spdk_bdev_nvme_opts, medium_priority_weight), spdk_json_decode_uint32, true}, 82 {"high_priority_weight", offsetof(struct spdk_bdev_nvme_opts, high_priority_weight), spdk_json_decode_uint32, true}, 83 {"nvme_adminq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_adminq_poll_period_us), spdk_json_decode_uint64, true}, 84 {"nvme_ioq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_ioq_poll_period_us), spdk_json_decode_uint64, true}, 85 {"io_queue_requests", offsetof(struct spdk_bdev_nvme_opts, io_queue_requests), spdk_json_decode_uint32, true}, 86 {"delay_cmd_submit", offsetof(struct spdk_bdev_nvme_opts, delay_cmd_submit), spdk_json_decode_bool, true}, 87 }; 88 89 static void 90 rpc_bdev_nvme_set_options(struct spdk_jsonrpc_request *request, 91 const struct spdk_json_val *params) 92 { 93 struct spdk_bdev_nvme_opts opts; 94 int rc; 95 96 bdev_nvme_get_opts(&opts); 97 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_options_decoders, 98 SPDK_COUNTOF(rpc_bdev_nvme_options_decoders), 99 &opts)) { 100 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 101 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 102 "spdk_json_decode_object failed"); 103 return; 104 } 105 106 rc = bdev_nvme_set_opts(&opts); 107 if (rc) { 108 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 109 return; 110 } 111 112 spdk_jsonrpc_send_bool_response(request, true); 113 114 return; 115 } 116 SPDK_RPC_REGISTER("bdev_nvme_set_options", rpc_bdev_nvme_set_options, 117 SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) 118 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_options, set_bdev_nvme_options) 119 120 struct rpc_bdev_nvme_hotplug { 121 bool enabled; 122 uint64_t period_us; 123 }; 124 125 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders[] = { 126 {"enable", offsetof(struct rpc_bdev_nvme_hotplug, enabled), spdk_json_decode_bool, false}, 127 {"period_us", offsetof(struct rpc_bdev_nvme_hotplug, period_us), spdk_json_decode_uint64, true}, 128 }; 129 130 static void 131 rpc_bdev_nvme_set_hotplug_done(void *ctx) 132 { 133 struct spdk_jsonrpc_request *request = ctx; 134 135 spdk_jsonrpc_send_bool_response(request, true); 136 } 137 138 static void 139 rpc_bdev_nvme_set_hotplug(struct spdk_jsonrpc_request *request, 140 const struct spdk_json_val *params) 141 { 142 struct rpc_bdev_nvme_hotplug req = {false, 0}; 143 int rc; 144 145 if (spdk_json_decode_object(params, rpc_bdev_nvme_hotplug_decoders, 146 SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders), &req)) { 147 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 148 rc = -EINVAL; 149 goto invalid; 150 } 151 152 rc = bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_bdev_nvme_set_hotplug_done, 153 request); 154 if (rc) { 155 goto invalid; 156 } 157 158 return; 159 invalid: 160 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc)); 161 } 162 SPDK_RPC_REGISTER("bdev_nvme_set_hotplug", rpc_bdev_nvme_set_hotplug, SPDK_RPC_RUNTIME) 163 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_hotplug, set_bdev_nvme_hotplug) 164 165 struct rpc_bdev_nvme_attach_controller { 166 char *name; 167 char *trtype; 168 char *adrfam; 169 char *traddr; 170 char *trsvcid; 171 char *priority; 172 char *subnqn; 173 char *hostnqn; 174 char *hostaddr; 175 char *hostsvcid; 176 bool prchk_reftag; 177 bool prchk_guard; 178 }; 179 180 static void 181 free_rpc_bdev_nvme_attach_controller(struct rpc_bdev_nvme_attach_controller *req) 182 { 183 free(req->name); 184 free(req->trtype); 185 free(req->adrfam); 186 free(req->traddr); 187 free(req->trsvcid); 188 free(req->priority); 189 free(req->subnqn); 190 free(req->hostnqn); 191 free(req->hostaddr); 192 free(req->hostsvcid); 193 } 194 195 static const struct spdk_json_object_decoder rpc_bdev_nvme_attach_controller_decoders[] = { 196 {"name", offsetof(struct rpc_bdev_nvme_attach_controller, name), spdk_json_decode_string}, 197 {"trtype", offsetof(struct rpc_bdev_nvme_attach_controller, trtype), spdk_json_decode_string}, 198 {"traddr", offsetof(struct rpc_bdev_nvme_attach_controller, traddr), spdk_json_decode_string}, 199 200 {"adrfam", offsetof(struct rpc_bdev_nvme_attach_controller, adrfam), spdk_json_decode_string, true}, 201 {"trsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, trsvcid), spdk_json_decode_string, true}, 202 {"priority", offsetof(struct rpc_bdev_nvme_attach_controller, priority), spdk_json_decode_string, true}, 203 {"subnqn", offsetof(struct rpc_bdev_nvme_attach_controller, subnqn), spdk_json_decode_string, true}, 204 {"hostnqn", offsetof(struct rpc_bdev_nvme_attach_controller, hostnqn), spdk_json_decode_string, true}, 205 {"hostaddr", offsetof(struct rpc_bdev_nvme_attach_controller, hostaddr), spdk_json_decode_string, true}, 206 {"hostsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, hostsvcid), spdk_json_decode_string, true}, 207 208 {"prchk_reftag", offsetof(struct rpc_bdev_nvme_attach_controller, prchk_reftag), spdk_json_decode_bool, true}, 209 {"prchk_guard", offsetof(struct rpc_bdev_nvme_attach_controller, prchk_guard), spdk_json_decode_bool, true} 210 }; 211 212 #define NVME_MAX_BDEVS_PER_RPC 128 213 214 struct rpc_bdev_nvme_attach_controller_ctx { 215 struct rpc_bdev_nvme_attach_controller req; 216 uint32_t count; 217 const char *names[NVME_MAX_BDEVS_PER_RPC]; 218 struct spdk_jsonrpc_request *request; 219 }; 220 221 static void 222 rpc_bdev_nvme_attach_controller_done(void *cb_ctx, size_t bdev_count, int rc) 223 { 224 struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx; 225 struct spdk_jsonrpc_request *request = ctx->request; 226 struct spdk_json_write_ctx *w; 227 size_t i; 228 229 if (rc < 0) { 230 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 231 goto exit; 232 } 233 234 w = spdk_jsonrpc_begin_result(request); 235 spdk_json_write_array_begin(w); 236 for (i = 0; i < bdev_count; i++) { 237 spdk_json_write_string(w, ctx->names[i]); 238 } 239 spdk_json_write_array_end(w); 240 spdk_jsonrpc_end_result(request, w); 241 242 exit: 243 free_rpc_bdev_nvme_attach_controller(&ctx->req); 244 free(ctx); 245 } 246 247 static void 248 rpc_bdev_nvme_attach_controller(struct spdk_jsonrpc_request *request, 249 const struct spdk_json_val *params) 250 { 251 struct rpc_bdev_nvme_attach_controller_ctx *ctx; 252 struct spdk_nvme_transport_id trid = {}; 253 struct spdk_nvme_host_id hostid = {}; 254 uint32_t prchk_flags = 0; 255 struct nvme_bdev_ctrlr *ctrlr = NULL; 256 size_t len, maxlen; 257 int rc; 258 259 ctx = calloc(1, sizeof(*ctx)); 260 if (!ctx) { 261 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 262 return; 263 } 264 265 if (spdk_json_decode_object(params, rpc_bdev_nvme_attach_controller_decoders, 266 SPDK_COUNTOF(rpc_bdev_nvme_attach_controller_decoders), 267 &ctx->req)) { 268 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 269 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 270 "spdk_json_decode_object failed"); 271 goto cleanup; 272 } 273 274 /* Parse trstring */ 275 rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype); 276 if (rc < 0) { 277 SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype); 278 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 279 ctx->req.trtype); 280 goto cleanup; 281 } 282 283 /* Parse trtype */ 284 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype); 285 assert(rc == 0); 286 287 ctrlr = nvme_bdev_ctrlr_get_by_name(ctx->req.name); 288 289 /* Parse traddr */ 290 maxlen = sizeof(trid.traddr); 291 len = strnlen(ctx->req.traddr, maxlen); 292 if (len == maxlen) { 293 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s", 294 ctx->req.traddr); 295 goto cleanup; 296 } 297 memcpy(trid.traddr, ctx->req.traddr, len + 1); 298 299 /* Parse adrfam */ 300 if (ctx->req.adrfam) { 301 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam); 302 if (rc < 0) { 303 SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam); 304 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 305 ctx->req.adrfam); 306 goto cleanup; 307 } 308 } 309 310 /* Parse trsvcid */ 311 if (ctx->req.trsvcid) { 312 maxlen = sizeof(trid.trsvcid); 313 len = strnlen(ctx->req.trsvcid, maxlen); 314 if (len == maxlen) { 315 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s", 316 ctx->req.trsvcid); 317 goto cleanup; 318 } 319 memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1); 320 } 321 322 /* Parse priority for the NVMe-oF transport connection */ 323 if (ctx->req.priority) { 324 trid.priority = spdk_strtol(ctx->req.priority, 10); 325 } 326 327 /* Parse subnqn */ 328 if (ctx->req.subnqn) { 329 maxlen = sizeof(trid.subnqn); 330 len = strnlen(ctx->req.subnqn, maxlen); 331 if (len == maxlen) { 332 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s", 333 ctx->req.subnqn); 334 goto cleanup; 335 } 336 memcpy(trid.subnqn, ctx->req.subnqn, len + 1); 337 } 338 339 if (ctrlr && (ctx->req.hostaddr || ctx->req.hostnqn || ctx->req.hostsvcid || ctx->req.prchk_guard || 340 ctx->req.prchk_reftag)) { 341 goto conflicting_arguments; 342 } 343 344 if (ctx->req.hostaddr) { 345 maxlen = sizeof(hostid.hostaddr); 346 len = strnlen(ctx->req.hostaddr, maxlen); 347 if (len == maxlen) { 348 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s", 349 ctx->req.hostaddr); 350 goto cleanup; 351 } 352 memcpy(hostid.hostaddr, ctx->req.hostaddr, len + 1); 353 } 354 355 if (ctx->req.hostsvcid) { 356 maxlen = sizeof(hostid.hostsvcid); 357 len = strnlen(ctx->req.hostsvcid, maxlen); 358 if (len == maxlen) { 359 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s", 360 ctx->req.hostsvcid); 361 goto cleanup; 362 } 363 memcpy(hostid.hostsvcid, ctx->req.hostsvcid, len + 1); 364 } 365 366 if (ctx->req.prchk_reftag) { 367 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG; 368 } 369 370 if (ctx->req.prchk_guard) { 371 prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD; 372 } 373 374 ctx->request = request; 375 ctx->count = NVME_MAX_BDEVS_PER_RPC; 376 rc = bdev_nvme_create(&trid, &hostid, ctx->req.name, ctx->names, ctx->count, ctx->req.hostnqn, 377 prchk_flags, rpc_bdev_nvme_attach_controller_done, ctx); 378 if (rc) { 379 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 380 goto cleanup; 381 } 382 383 return; 384 385 conflicting_arguments: 386 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 387 "Invalid agrgument list. Existing controller name cannot be combined with host information or PI options.\n"); 388 cleanup: 389 free_rpc_bdev_nvme_attach_controller(&ctx->req); 390 free(ctx); 391 } 392 SPDK_RPC_REGISTER("bdev_nvme_attach_controller", rpc_bdev_nvme_attach_controller, 393 SPDK_RPC_RUNTIME) 394 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_attach_controller, construct_nvme_bdev) 395 396 static void 397 rpc_dump_nvme_controller_info(struct spdk_json_write_ctx *w, 398 struct nvme_bdev_ctrlr *nvme_bdev_ctrlr) 399 { 400 struct spdk_nvme_transport_id *trid; 401 402 trid = nvme_bdev_ctrlr->connected_trid; 403 404 spdk_json_write_object_begin(w); 405 spdk_json_write_named_string(w, "name", nvme_bdev_ctrlr->name); 406 407 #ifdef SPDK_CONFIG_NVME_CUSE 408 size_t cuse_name_size = 128; 409 char cuse_name[cuse_name_size]; 410 411 int rc = spdk_nvme_cuse_get_ctrlr_name(nvme_bdev_ctrlr->ctrlr, cuse_name, &cuse_name_size); 412 if (rc == 0) { 413 spdk_json_write_named_string(w, "cuse_device", cuse_name); 414 } 415 #endif 416 417 spdk_json_write_named_object_begin(w, "trid"); 418 nvme_bdev_dump_trid_json(trid, w); 419 spdk_json_write_object_end(w); 420 421 spdk_json_write_object_end(w); 422 } 423 424 struct rpc_bdev_nvme_get_controllers { 425 char *name; 426 }; 427 428 static void 429 free_rpc_bdev_nvme_get_controllers(struct rpc_bdev_nvme_get_controllers *r) 430 { 431 free(r->name); 432 } 433 434 static const struct spdk_json_object_decoder rpc_bdev_nvme_get_controllers_decoders[] = { 435 {"name", offsetof(struct rpc_bdev_nvme_get_controllers, name), spdk_json_decode_string, true}, 436 }; 437 438 static void 439 rpc_bdev_nvme_get_controllers(struct spdk_jsonrpc_request *request, 440 const struct spdk_json_val *params) 441 { 442 struct rpc_bdev_nvme_get_controllers req = {}; 443 struct spdk_json_write_ctx *w; 444 struct nvme_bdev_ctrlr *ctrlr = NULL; 445 446 if (params && spdk_json_decode_object(params, rpc_bdev_nvme_get_controllers_decoders, 447 SPDK_COUNTOF(rpc_bdev_nvme_get_controllers_decoders), 448 &req)) { 449 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 450 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 451 "spdk_json_decode_object failed"); 452 goto cleanup; 453 } 454 455 if (req.name) { 456 ctrlr = nvme_bdev_ctrlr_get_by_name(req.name); 457 if (ctrlr == NULL) { 458 SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name); 459 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Controller %s does not exist", req.name); 460 goto cleanup; 461 } 462 } 463 464 w = spdk_jsonrpc_begin_result(request); 465 spdk_json_write_array_begin(w); 466 467 if (ctrlr != NULL) { 468 rpc_dump_nvme_controller_info(w, ctrlr); 469 } else { 470 for (ctrlr = nvme_bdev_first_ctrlr(); ctrlr; ctrlr = nvme_bdev_next_ctrlr(ctrlr)) { 471 rpc_dump_nvme_controller_info(w, ctrlr); 472 } 473 } 474 475 spdk_json_write_array_end(w); 476 477 spdk_jsonrpc_end_result(request, w); 478 479 cleanup: 480 free_rpc_bdev_nvme_get_controllers(&req); 481 } 482 SPDK_RPC_REGISTER("bdev_nvme_get_controllers", rpc_bdev_nvme_get_controllers, SPDK_RPC_RUNTIME) 483 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_get_controllers, get_nvme_controllers) 484 485 struct rpc_bdev_nvme_detach_controller { 486 char *name; 487 char *trtype; 488 char *adrfam; 489 char *traddr; 490 char *trsvcid; 491 char *subnqn; 492 }; 493 494 static void 495 free_rpc_bdev_nvme_detach_controller(struct rpc_bdev_nvme_detach_controller *req) 496 { 497 free(req->name); 498 free(req->trtype); 499 free(req->adrfam); 500 free(req->traddr); 501 free(req->trsvcid); 502 free(req->subnqn); 503 } 504 505 static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_decoders[] = { 506 {"name", offsetof(struct rpc_bdev_nvme_detach_controller, name), spdk_json_decode_string}, 507 {"trtype", offsetof(struct rpc_bdev_nvme_detach_controller, trtype), spdk_json_decode_string, true}, 508 {"traddr", offsetof(struct rpc_bdev_nvme_detach_controller, traddr), spdk_json_decode_string, true}, 509 {"adrfam", offsetof(struct rpc_bdev_nvme_detach_controller, adrfam), spdk_json_decode_string, true}, 510 {"trsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, trsvcid), spdk_json_decode_string, true}, 511 {"subnqn", offsetof(struct rpc_bdev_nvme_detach_controller, subnqn), spdk_json_decode_string, true}, 512 }; 513 514 static void 515 rpc_bdev_nvme_detach_controller(struct spdk_jsonrpc_request *request, 516 const struct spdk_json_val *params) 517 { 518 struct rpc_bdev_nvme_detach_controller req = {NULL}; 519 struct spdk_nvme_transport_id trid = {}; 520 size_t len, maxlen; 521 int rc = 0; 522 bool all_trid_entries, one_trid_entry; 523 524 if (spdk_json_decode_object(params, rpc_bdev_nvme_detach_controller_decoders, 525 SPDK_COUNTOF(rpc_bdev_nvme_detach_controller_decoders), 526 &req)) { 527 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 528 "spdk_json_decode_object failed"); 529 goto cleanup; 530 } 531 532 all_trid_entries = req.trtype && req.traddr && req.adrfam && req.trsvcid && req.subnqn; 533 one_trid_entry = req.trtype || req.traddr || req.adrfam || req.trsvcid || req.subnqn; 534 535 if (all_trid_entries ^ one_trid_entry) { 536 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 537 "trtype, traddr, adrfam, trsvcid, subnqn must all be provided together or not at all."); 538 goto cleanup; 539 } 540 541 if (all_trid_entries) { 542 /* Parse trtype */ 543 rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, req.trtype); 544 if (rc < 0) { 545 SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype); 546 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s", 547 req.trtype); 548 goto cleanup; 549 } 550 551 /* Parse traddr */ 552 maxlen = sizeof(trid.traddr); 553 len = strnlen(req.traddr, maxlen); 554 if (len == maxlen) { 555 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s", 556 req.traddr); 557 goto cleanup; 558 } 559 memcpy(trid.traddr, req.traddr, len + 1); 560 561 rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, req.adrfam); 562 if (rc < 0) { 563 SPDK_ERRLOG("Failed to parse adrfam: %s\n", req.adrfam); 564 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s", 565 req.adrfam); 566 goto cleanup; 567 } 568 569 maxlen = sizeof(trid.trsvcid); 570 len = strnlen(req.trsvcid, maxlen); 571 if (len == maxlen) { 572 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s", 573 req.trsvcid); 574 goto cleanup; 575 } 576 memcpy(trid.trsvcid, req.trsvcid, len + 1); 577 578 maxlen = sizeof(trid.subnqn); 579 len = strnlen(req.subnqn, maxlen); 580 if (len == maxlen) { 581 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s", 582 req.subnqn); 583 goto cleanup; 584 } 585 memcpy(trid.subnqn, req.subnqn, len + 1); 586 rc = bdev_nvme_remove_trid(req.name, &trid); 587 } else { 588 rc = bdev_nvme_delete(req.name); 589 } 590 591 if (rc != 0) { 592 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 593 goto cleanup; 594 } 595 596 spdk_jsonrpc_send_bool_response(request, true); 597 598 cleanup: 599 free_rpc_bdev_nvme_detach_controller(&req); 600 } 601 SPDK_RPC_REGISTER("bdev_nvme_detach_controller", rpc_bdev_nvme_detach_controller, 602 SPDK_RPC_RUNTIME) 603 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_detach_controller, delete_nvme_controller) 604 605 struct rpc_apply_firmware { 606 char *filename; 607 char *bdev_name; 608 }; 609 610 static void 611 free_rpc_apply_firmware(struct rpc_apply_firmware *req) 612 { 613 free(req->filename); 614 free(req->bdev_name); 615 } 616 617 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders[] = { 618 {"filename", offsetof(struct rpc_apply_firmware, filename), spdk_json_decode_string}, 619 {"bdev_name", offsetof(struct rpc_apply_firmware, bdev_name), spdk_json_decode_string}, 620 }; 621 622 struct firmware_update_info { 623 void *fw_image; 624 void *p; 625 unsigned int size; 626 unsigned int size_remaining; 627 unsigned int offset; 628 unsigned int transfer; 629 630 void *desc; 631 struct spdk_io_channel *ch; 632 struct spdk_jsonrpc_request *request; 633 struct spdk_nvme_ctrlr *ctrlr; 634 open_descriptors_t desc_head; 635 struct rpc_apply_firmware *req; 636 }; 637 638 static void 639 _apply_firmware_cleanup(void *ctx) 640 { 641 struct spdk_bdev_desc *desc = ctx; 642 643 spdk_bdev_close(desc); 644 } 645 646 static void 647 apply_firmware_cleanup(void *cb_arg) 648 { 649 struct open_descriptors *opt, *tmp; 650 struct firmware_update_info *firm_ctx = cb_arg; 651 652 if (!firm_ctx) { 653 return; 654 } 655 656 if (firm_ctx->fw_image) { 657 spdk_free(firm_ctx->fw_image); 658 } 659 660 if (firm_ctx->req) { 661 free_rpc_apply_firmware(firm_ctx->req); 662 free(firm_ctx->req); 663 } 664 665 if (firm_ctx->ch) { 666 spdk_put_io_channel(firm_ctx->ch); 667 } 668 669 TAILQ_FOREACH_SAFE(opt, &firm_ctx->desc_head, tqlst, tmp) { 670 TAILQ_REMOVE(&firm_ctx->desc_head, opt, tqlst); 671 /* Close the underlying bdev on its same opened thread. */ 672 if (opt->thread && opt->thread != spdk_get_thread()) { 673 spdk_thread_send_msg(opt->thread, _apply_firmware_cleanup, opt->desc); 674 } else { 675 spdk_bdev_close(opt->desc); 676 } 677 free(opt); 678 } 679 free(firm_ctx); 680 } 681 682 static void 683 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 684 { 685 struct spdk_json_write_ctx *w; 686 struct firmware_update_info *firm_ctx = cb_arg; 687 688 spdk_bdev_free_io(bdev_io); 689 690 if (!success) { 691 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 692 "firmware commit failed."); 693 apply_firmware_cleanup(firm_ctx); 694 return; 695 } 696 697 if (spdk_nvme_ctrlr_reset(firm_ctx->ctrlr) != 0) { 698 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 699 "Controller reset failed."); 700 apply_firmware_cleanup(firm_ctx); 701 return; 702 } 703 704 w = spdk_jsonrpc_begin_result(firm_ctx->request); 705 spdk_json_write_string(w, "firmware commit succeeded. Controller reset in progress."); 706 spdk_jsonrpc_end_result(firm_ctx->request, w); 707 apply_firmware_cleanup(firm_ctx); 708 } 709 710 static void 711 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 712 { 713 struct spdk_nvme_cmd cmd = {}; 714 struct spdk_nvme_fw_commit fw_commit; 715 int slot = 0; 716 int rc; 717 struct firmware_update_info *firm_ctx = cb_arg; 718 enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG; 719 720 if (!success) { 721 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 722 "firmware download failed ."); 723 spdk_bdev_free_io(bdev_io); 724 apply_firmware_cleanup(firm_ctx); 725 return; 726 } 727 728 firm_ctx->p += firm_ctx->transfer; 729 firm_ctx->offset += firm_ctx->transfer; 730 firm_ctx->size_remaining -= firm_ctx->transfer; 731 732 switch (firm_ctx->size_remaining) { 733 case 0: 734 /* firmware download completed. Commit firmware */ 735 memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit)); 736 fw_commit.fs = slot; 737 fw_commit.ca = commit_action; 738 739 cmd.opc = SPDK_NVME_OPC_FIRMWARE_COMMIT; 740 memcpy(&cmd.cdw10, &fw_commit, sizeof(uint32_t)); 741 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, NULL, 0, 742 apply_firmware_complete_reset, firm_ctx); 743 if (rc) { 744 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 745 "firmware commit failed."); 746 spdk_bdev_free_io(bdev_io); 747 apply_firmware_cleanup(firm_ctx); 748 return; 749 } 750 break; 751 default: 752 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 753 cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 754 755 cmd.cdw10 = (firm_ctx->transfer >> 2) - 1; 756 cmd.cdw11 = firm_ctx->offset >> 2; 757 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p, 758 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 759 if (rc) { 760 spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 761 "firmware download failed."); 762 spdk_bdev_free_io(bdev_io); 763 apply_firmware_cleanup(firm_ctx); 764 return; 765 } 766 break; 767 } 768 } 769 770 static void 771 rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request, 772 const struct spdk_json_val *params) 773 { 774 int rc; 775 int fd = -1; 776 struct stat fw_stat; 777 struct spdk_nvme_ctrlr *ctrlr; 778 char msg[1024]; 779 struct spdk_bdev *bdev; 780 struct spdk_bdev *bdev2; 781 struct open_descriptors *opt; 782 struct spdk_bdev_desc *desc; 783 struct spdk_nvme_cmd *cmd; 784 struct firmware_update_info *firm_ctx; 785 786 firm_ctx = calloc(1, sizeof(struct firmware_update_info)); 787 if (!firm_ctx) { 788 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 789 "Memory allocation error."); 790 return; 791 } 792 firm_ctx->fw_image = NULL; 793 TAILQ_INIT(&firm_ctx->desc_head); 794 firm_ctx->request = request; 795 796 firm_ctx->req = calloc(1, sizeof(struct rpc_apply_firmware)); 797 if (!firm_ctx->req) { 798 snprintf(msg, sizeof(msg), "Memory allocation error."); 799 goto err; 800 } 801 802 if (spdk_json_decode_object(params, rpc_apply_firmware_decoders, 803 SPDK_COUNTOF(rpc_apply_firmware_decoders), firm_ctx->req)) { 804 snprintf(msg, sizeof(msg), "spdk_json_decode_object failed."); 805 goto err; 806 } 807 808 if ((bdev = spdk_bdev_get_by_name(firm_ctx->req->bdev_name)) == NULL) { 809 snprintf(msg, sizeof(msg), "bdev %s were not found", firm_ctx->req->bdev_name); 810 goto err; 811 } 812 813 if ((ctrlr = bdev_nvme_get_ctrlr(bdev)) == NULL) { 814 snprintf(msg, sizeof(msg), "Controller information for %s were not found.", 815 firm_ctx->req->bdev_name); 816 goto err; 817 } 818 firm_ctx->ctrlr = ctrlr; 819 820 for (bdev2 = spdk_bdev_first(); bdev2; bdev2 = spdk_bdev_next(bdev2)) { 821 822 if (bdev_nvme_get_ctrlr(bdev2) != ctrlr) { 823 continue; 824 } 825 826 if (!(opt = malloc(sizeof(struct open_descriptors)))) { 827 snprintf(msg, sizeof(msg), "Memory allocation error."); 828 goto err; 829 } 830 831 if (spdk_bdev_open(bdev2, true, NULL, NULL, &desc) != 0) { 832 snprintf(msg, sizeof(msg), "Device %s is in use.", firm_ctx->req->bdev_name); 833 free(opt); 834 goto err; 835 } 836 837 /* Save the thread where the base device is opened */ 838 opt->thread = spdk_get_thread(); 839 840 opt->desc = desc; 841 opt->bdev = bdev; 842 TAILQ_INSERT_TAIL(&firm_ctx->desc_head, opt, tqlst); 843 } 844 845 /* 846 * find a descriptor associated with our bdev 847 */ 848 firm_ctx->desc = NULL; 849 TAILQ_FOREACH(opt, &firm_ctx->desc_head, tqlst) { 850 if (opt->bdev == bdev) { 851 firm_ctx->desc = opt->desc; 852 break; 853 } 854 } 855 856 if (!firm_ctx->desc) { 857 snprintf(msg, sizeof(msg), "No descriptor were found."); 858 goto err; 859 } 860 861 firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc); 862 if (!firm_ctx->ch) { 863 snprintf(msg, sizeof(msg), "No channels were found."); 864 goto err; 865 } 866 867 fd = open(firm_ctx->req->filename, O_RDONLY); 868 if (fd < 0) { 869 snprintf(msg, sizeof(msg), "open file failed."); 870 goto err; 871 } 872 873 rc = fstat(fd, &fw_stat); 874 if (rc < 0) { 875 close(fd); 876 snprintf(msg, sizeof(msg), "fstat failed."); 877 goto err; 878 } 879 880 firm_ctx->size = fw_stat.st_size; 881 if (fw_stat.st_size % 4) { 882 close(fd); 883 snprintf(msg, sizeof(msg), "Firmware image size is not multiple of 4."); 884 goto err; 885 } 886 887 firm_ctx->fw_image = spdk_zmalloc(firm_ctx->size, 4096, NULL, 888 SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 889 if (!firm_ctx->fw_image) { 890 close(fd); 891 snprintf(msg, sizeof(msg), "Memory allocation error."); 892 goto err; 893 } 894 firm_ctx->p = firm_ctx->fw_image; 895 896 if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) { 897 close(fd); 898 snprintf(msg, sizeof(msg), "Read firmware image failed!"); 899 goto err; 900 } 901 close(fd); 902 903 firm_ctx->offset = 0; 904 firm_ctx->size_remaining = firm_ctx->size; 905 firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096); 906 907 cmd = malloc(sizeof(struct spdk_nvme_cmd)); 908 if (!cmd) { 909 snprintf(msg, sizeof(msg), "Memory allocation error."); 910 goto err; 911 } 912 memset(cmd, 0, sizeof(struct spdk_nvme_cmd)); 913 cmd->opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; 914 915 cmd->cdw10 = (firm_ctx->transfer >> 2) - 1; 916 cmd->cdw11 = firm_ctx->offset >> 2; 917 918 rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, cmd, firm_ctx->p, 919 firm_ctx->transfer, apply_firmware_complete, firm_ctx); 920 if (rc == 0) { 921 /* normal return here. */ 922 return; 923 } 924 925 free(cmd); 926 snprintf(msg, sizeof(msg), "Read firmware image failed!"); 927 err: 928 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg); 929 apply_firmware_cleanup(firm_ctx); 930 } 931 SPDK_RPC_REGISTER("bdev_nvme_apply_firmware", rpc_bdev_nvme_apply_firmware, SPDK_RPC_RUNTIME) 932 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_apply_firmware, apply_nvme_firmware) 933