1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/opal.h" 7 #include "spdk/bdev_module.h" 8 #include "vbdev_opal.h" 9 #include "spdk/log.h" 10 #include "spdk/string.h" 11 12 /* OPAL locking range only supports operations on nsid=1 for now */ 13 #define NSID_SUPPORTED 1 14 15 struct opal_vbdev { 16 char *name; 17 struct nvme_ctrlr *nvme_ctrlr; 18 struct spdk_opal_dev *opal_dev; 19 struct spdk_bdev_part *bdev_part; 20 21 uint8_t locking_range_id; 22 uint64_t range_start; 23 uint64_t range_length; 24 struct vbdev_opal_part_base *opal_base; 25 26 TAILQ_ENTRY(opal_vbdev) tailq; 27 }; 28 29 static TAILQ_HEAD(, opal_vbdev) g_opal_vbdev = 30 TAILQ_HEAD_INITIALIZER(g_opal_vbdev); 31 32 struct vbdev_opal_bdev_io { 33 struct spdk_io_channel *ch; 34 struct spdk_bdev_io *bdev_io; 35 struct spdk_bdev_io_wait_entry bdev_io_wait; 36 }; 37 38 struct vbdev_opal_channel { 39 struct spdk_bdev_part_channel part_ch; 40 }; 41 42 struct vbdev_opal_part_base { 43 char *nvme_ctrlr_name; 44 struct spdk_bdev_part_base *part_base; 45 SPDK_BDEV_PART_TAILQ part_tailq; 46 TAILQ_ENTRY(vbdev_opal_part_base) tailq; 47 }; 48 49 static TAILQ_HEAD(, vbdev_opal_part_base) g_opal_base = TAILQ_HEAD_INITIALIZER(g_opal_base); 50 51 static void _vbdev_opal_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io); 52 53 static void vbdev_opal_examine(struct spdk_bdev *bdev); 54 55 static void 56 vbdev_opal_delete(struct opal_vbdev *opal_bdev) 57 { 58 TAILQ_REMOVE(&g_opal_vbdev, opal_bdev, tailq); 59 free(opal_bdev->name); 60 free(opal_bdev); 61 opal_bdev = NULL; 62 } 63 64 static void 65 vbdev_opal_clear(void) 66 { 67 struct opal_vbdev *opal_bdev, *tmp; 68 69 TAILQ_FOREACH_SAFE(opal_bdev, &g_opal_vbdev, tailq, tmp) { 70 vbdev_opal_delete(opal_bdev); 71 } 72 } 73 74 static int 75 vbdev_opal_init(void) 76 { 77 /* TODO */ 78 return 0; 79 } 80 81 static void 82 vbdev_opal_fini(void) 83 { 84 vbdev_opal_clear(); 85 } 86 87 static int 88 vbdev_opal_get_ctx_size(void) 89 { 90 return sizeof(struct vbdev_opal_bdev_io); 91 } 92 93 /* delete all the config of the same base bdev */ 94 static void 95 vbdev_opal_delete_all_base_config(struct vbdev_opal_part_base *base) 96 { 97 char *nvme_ctrlr_name = base->nvme_ctrlr_name; 98 struct opal_vbdev *bdev, *tmp_bdev; 99 100 TAILQ_FOREACH_SAFE(bdev, &g_opal_vbdev, tailq, tmp_bdev) { 101 if (!strcmp(nvme_ctrlr_name, bdev->nvme_ctrlr->nbdev_ctrlr->name)) { 102 vbdev_opal_delete(bdev); 103 } 104 } 105 } 106 107 static int 108 _vbdev_opal_destruct(void *ctx) 109 { 110 struct spdk_bdev_part *part = ctx; 111 112 return spdk_bdev_part_free(part); 113 } 114 115 static void 116 vbdev_opal_base_free(void *ctx) 117 { 118 struct vbdev_opal_part_base *base = ctx; 119 120 TAILQ_REMOVE(&g_opal_base, base, tailq); 121 122 free(base->nvme_ctrlr_name); 123 free(base); 124 } 125 126 static void 127 vbdev_opal_resubmit_io(void *arg) 128 { 129 struct vbdev_opal_bdev_io *io_ctx = (struct vbdev_opal_bdev_io *)arg; 130 131 _vbdev_opal_submit_request(io_ctx->ch, io_ctx->bdev_io); 132 } 133 134 static void 135 vbdev_opal_queue_io(struct vbdev_opal_bdev_io *io_ctx) 136 { 137 struct vbdev_opal_channel *ch = spdk_io_channel_get_ctx(io_ctx->ch); 138 int rc; 139 140 io_ctx->bdev_io_wait.bdev = io_ctx->bdev_io->bdev; 141 io_ctx->bdev_io_wait.cb_fn = vbdev_opal_resubmit_io; 142 io_ctx->bdev_io_wait.cb_arg = io_ctx; 143 144 rc = spdk_bdev_queue_io_wait(io_ctx->bdev_io->bdev, ch->part_ch.base_ch, &io_ctx->bdev_io_wait); 145 146 if (rc != 0) { 147 SPDK_ERRLOG("Queue io failed in vbdev_opal_queue_io: %d\n", rc); 148 spdk_bdev_io_complete(io_ctx->bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 149 } 150 } 151 152 static void 153 _vbdev_opal_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 154 { 155 struct vbdev_opal_channel *ch = spdk_io_channel_get_ctx(_ch); 156 struct vbdev_opal_bdev_io *io_ctx = (struct vbdev_opal_bdev_io *)bdev_io->driver_ctx; 157 int rc; 158 159 rc = spdk_bdev_part_submit_request(&ch->part_ch, bdev_io); 160 if (rc) { 161 if (rc == -ENOMEM) { 162 SPDK_DEBUGLOG(vbdev_opal, "opal: no memory, queue io.\n"); 163 io_ctx->ch = _ch; 164 io_ctx->bdev_io = bdev_io; 165 vbdev_opal_queue_io(io_ctx); 166 } else { 167 SPDK_ERRLOG("opal: error on io submission, rc=%d.\n", rc); 168 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 169 } 170 } 171 } 172 173 static void 174 vbdev_opal_io_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, bool success) 175 { 176 if (!success) { 177 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 178 return; 179 } 180 181 _vbdev_opal_submit_request(ch, bdev_io); 182 } 183 184 static void 185 vbdev_opal_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 186 { 187 switch (bdev_io->type) { 188 case SPDK_BDEV_IO_TYPE_READ: 189 spdk_bdev_io_get_buf(bdev_io, vbdev_opal_io_get_buf_cb, 190 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen); 191 break; 192 default: 193 _vbdev_opal_submit_request(ch, bdev_io); 194 break; 195 } 196 } 197 198 struct spdk_opal_locking_range_info * 199 vbdev_opal_get_info_from_bdev(const char *opal_bdev_name, const char *password) 200 { 201 struct opal_vbdev *vbdev; 202 struct nvme_ctrlr *nvme_ctrlr; 203 int locking_range_id; 204 int rc; 205 206 TAILQ_FOREACH(vbdev, &g_opal_vbdev, tailq) { 207 if (strcmp(vbdev->name, opal_bdev_name) == 0) { 208 break; 209 } 210 } 211 212 if (vbdev == NULL) { 213 SPDK_ERRLOG("%s not found\n", opal_bdev_name); 214 return NULL; 215 } 216 217 nvme_ctrlr = vbdev->nvme_ctrlr; 218 if (nvme_ctrlr == NULL) { 219 SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", vbdev->name); 220 return NULL; 221 } 222 223 locking_range_id = vbdev->locking_range_id; 224 rc = spdk_opal_cmd_get_locking_range_info(nvme_ctrlr->opal_dev, password, 225 OPAL_ADMIN1, locking_range_id); 226 if (rc) { 227 SPDK_ERRLOG("Get locking range info error: %d\n", rc); 228 return NULL; 229 } 230 231 return spdk_opal_get_locking_range_info(nvme_ctrlr->opal_dev, locking_range_id); 232 } 233 234 static int 235 vbdev_opal_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) 236 { 237 struct spdk_bdev_part *part = ctx; 238 struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(part); 239 uint64_t offset = spdk_bdev_part_get_offset_blocks(part); 240 241 spdk_json_write_named_object_begin(w, "opal"); 242 243 spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(base_bdev)); 244 spdk_json_write_named_uint64(w, "offset_blocks", offset); 245 246 spdk_json_write_object_end(w); 247 248 return 0; 249 } 250 251 static void 252 vbdev_opal_base_bdev_hotremove_cb(void *_part_base) 253 { 254 struct spdk_bdev_part_base *part_base = _part_base; 255 struct vbdev_opal_part_base *base = spdk_bdev_part_base_get_ctx(part_base); 256 257 spdk_bdev_part_base_hotremove(part_base, spdk_bdev_part_base_get_tailq(part_base)); 258 vbdev_opal_delete_all_base_config(base); 259 } 260 261 static bool 262 vbdev_opal_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) 263 { 264 struct spdk_bdev_part *part = ctx; 265 struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(part); 266 267 return spdk_bdev_io_type_supported(base_bdev, io_type); 268 } 269 270 static struct spdk_bdev_fn_table opal_vbdev_fn_table = { 271 .destruct = _vbdev_opal_destruct, 272 .submit_request = vbdev_opal_submit_request, 273 .io_type_supported = vbdev_opal_io_type_supported, 274 .dump_info_json = vbdev_opal_dump_info_json, 275 .write_config_json = NULL, 276 }; 277 278 static struct spdk_bdev_module opal_if = { 279 .name = "opal", 280 .module_init = vbdev_opal_init, 281 .module_fini = vbdev_opal_fini, 282 .get_ctx_size = vbdev_opal_get_ctx_size, 283 .examine_config = vbdev_opal_examine, 284 .config_json = NULL, 285 }; 286 287 SPDK_BDEV_MODULE_REGISTER(opal, &opal_if) 288 289 int 290 vbdev_opal_create(const char *nvme_ctrlr_name, uint32_t nsid, uint8_t locking_range_id, 291 uint64_t range_start, uint64_t range_length, const char *password) 292 { 293 int rc; 294 char *opal_vbdev_name; 295 char *base_bdev_name; 296 struct nvme_ctrlr *nvme_ctrlr; 297 struct opal_vbdev *opal_bdev; 298 struct vbdev_opal_part_base *opal_part_base = NULL; 299 struct spdk_bdev_part *part_bdev; 300 struct nvme_bdev *nvme_bdev; 301 struct nvme_ns *nvme_ns; 302 303 if (nsid != NSID_SUPPORTED) { 304 SPDK_ERRLOG("nsid %d not supported", nsid); 305 return -EINVAL; 306 } 307 308 nvme_ctrlr = nvme_ctrlr_get_by_name(nvme_ctrlr_name); 309 if (!nvme_ctrlr) { 310 SPDK_ERRLOG("get nvme ctrlr failed\n"); 311 return -ENODEV; 312 } 313 314 if (!nvme_ctrlr->opal_dev) { 315 SPDK_ERRLOG("Opal not supported\n"); 316 return -ENOTSUP; 317 } 318 319 opal_bdev = calloc(1, sizeof(struct opal_vbdev)); 320 if (!opal_bdev) { 321 SPDK_ERRLOG("allocation for opal_bdev failed\n"); 322 return -ENOMEM; 323 } 324 325 opal_bdev->locking_range_id = locking_range_id; 326 opal_bdev->range_start = range_start; 327 opal_bdev->range_length = range_length; 328 329 opal_bdev->nvme_ctrlr = nvme_ctrlr; 330 opal_bdev->opal_dev = nvme_ctrlr->opal_dev; 331 332 nvme_ns = nvme_ctrlr_get_ns(nvme_ctrlr, nsid); 333 if (nvme_ns == NULL) { 334 free(opal_bdev); 335 return -ENODEV; 336 } 337 338 nvme_bdev = nvme_ns->bdev; 339 assert(nvme_bdev != NULL); 340 base_bdev_name = nvme_bdev->disk.name; 341 342 /* traverse base list to see if part_base is already create for this base bdev */ 343 TAILQ_FOREACH(opal_part_base, &g_opal_base, tailq) { 344 if (!strcmp(spdk_bdev_part_base_get_bdev_name(opal_part_base->part_base), base_bdev_name)) { 345 break; 346 } 347 } 348 349 /* If there is not a corresponding opal_part_base, a new opal_part_base will be created. 350 For each new part_base, there will be one tailq to store all the parts of this base */ 351 if (opal_part_base == NULL) { 352 opal_part_base = calloc(1, sizeof(*opal_part_base)); 353 if (opal_part_base == NULL) { 354 SPDK_ERRLOG("Could not allocate opal_part_base\n"); 355 free(opal_bdev); 356 return -ENOMEM; 357 } 358 TAILQ_INIT(&opal_part_base->part_tailq); 359 360 rc = spdk_bdev_part_base_construct_ext(base_bdev_name, 361 vbdev_opal_base_bdev_hotremove_cb, &opal_if, 362 &opal_vbdev_fn_table, &opal_part_base->part_tailq, 363 vbdev_opal_base_free, opal_part_base, 364 sizeof(struct vbdev_opal_channel), NULL, NULL, 365 &opal_part_base->part_base); 366 if (rc != 0) { 367 if (rc != -ENODEV) { 368 SPDK_ERRLOG("Could not allocate part_base\n"); 369 } 370 free(opal_bdev); 371 free(opal_part_base); 372 return rc; 373 } 374 opal_part_base->nvme_ctrlr_name = strdup(nvme_ctrlr_name); 375 if (opal_part_base->nvme_ctrlr_name == NULL) { 376 free(opal_bdev); 377 spdk_bdev_part_base_free(opal_part_base->part_base); 378 return -ENOMEM; 379 } 380 381 TAILQ_INSERT_TAIL(&g_opal_base, opal_part_base, tailq); 382 } 383 assert(opal_part_base != NULL); 384 opal_bdev->opal_base = opal_part_base; 385 386 part_bdev = calloc(1, sizeof(struct spdk_bdev_part)); 387 if (!part_bdev) { 388 SPDK_ERRLOG("Could not allocate part_bdev\n"); 389 free(opal_bdev); 390 return -ENOMEM; 391 } 392 393 TAILQ_INSERT_TAIL(&g_opal_vbdev, opal_bdev, tailq); 394 opal_vbdev_name = spdk_sprintf_alloc("%sr%" PRIu8, base_bdev_name, 395 opal_bdev->locking_range_id); /* e.g.: nvme0n1r1 */ 396 if (opal_vbdev_name == NULL) { 397 SPDK_ERRLOG("Could not allocate opal_vbdev_name\n"); 398 rc = -ENOMEM; 399 goto err; 400 } 401 402 opal_bdev->name = opal_vbdev_name; 403 rc = spdk_opal_cmd_setup_locking_range(opal_bdev->opal_dev, OPAL_ADMIN1, 404 opal_bdev->locking_range_id, opal_bdev->range_start, 405 opal_bdev->range_length, password); 406 if (rc) { 407 SPDK_ERRLOG("Error construct %s\n", opal_vbdev_name); 408 goto err; 409 } 410 411 rc = spdk_bdev_part_construct(part_bdev, opal_bdev->opal_base->part_base, opal_vbdev_name, 412 opal_bdev->range_start, opal_bdev->range_length, "Opal locking range"); 413 if (rc) { 414 SPDK_ERRLOG("Could not allocate bdev part\n"); 415 goto err; 416 } 417 418 /* lock this bdev initially */ 419 rc = spdk_opal_cmd_lock_unlock(opal_bdev->opal_dev, OPAL_ADMIN1, OPAL_RWLOCK, locking_range_id, 420 password); 421 if (rc) { 422 SPDK_ERRLOG("Error lock %s\n", opal_vbdev_name); 423 goto err; 424 } 425 426 opal_bdev->bdev_part = part_bdev; 427 return 0; 428 429 err: 430 vbdev_opal_delete(opal_bdev); 431 free(part_bdev); 432 return rc; 433 } 434 435 static void 436 vbdev_opal_destruct_bdev(struct opal_vbdev *opal_bdev) 437 { 438 struct spdk_bdev_part *part = opal_bdev->bdev_part; 439 440 assert(opal_bdev->opal_base != NULL); 441 assert(part != NULL); 442 443 if (opal_bdev->range_start == spdk_bdev_part_get_offset_blocks(part)) { 444 spdk_bdev_unregister(spdk_bdev_part_get_bdev(part), NULL, NULL); 445 } 446 vbdev_opal_delete(opal_bdev); 447 } 448 449 int 450 vbdev_opal_destruct(const char *bdev_name, const char *password) 451 { 452 struct nvme_ctrlr *nvme_ctrlr; 453 int locking_range_id; 454 int rc; 455 struct opal_vbdev *opal_bdev; 456 457 TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) { 458 if (strcmp(opal_bdev->name, bdev_name) == 0) { 459 break; 460 } 461 } 462 463 if (opal_bdev == NULL) { 464 SPDK_ERRLOG("%s not found\n", bdev_name); 465 rc = -ENODEV; 466 goto err; 467 } 468 469 locking_range_id = opal_bdev->locking_range_id; 470 471 nvme_ctrlr = opal_bdev->nvme_ctrlr; 472 if (nvme_ctrlr == NULL) { 473 SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", bdev_name); 474 return -ENODEV; 475 } 476 477 /* secure erase locking range */ 478 rc = spdk_opal_cmd_secure_erase_locking_range(nvme_ctrlr->opal_dev, OPAL_ADMIN1, locking_range_id, 479 password); 480 if (rc) { 481 SPDK_ERRLOG("opal erase locking range failed\n"); 482 goto err; 483 } 484 485 /* reset the locking range to 0 */ 486 rc = spdk_opal_cmd_setup_locking_range(nvme_ctrlr->opal_dev, OPAL_ADMIN1, locking_range_id, 0, 487 0, password); 488 if (rc) { 489 SPDK_ERRLOG("opal reset locking range failed\n"); 490 goto err; 491 } 492 493 spdk_opal_free_locking_range_info(opal_bdev->opal_dev, locking_range_id); 494 vbdev_opal_destruct_bdev(opal_bdev); 495 return 0; 496 497 err: 498 return rc; 499 } 500 501 static void 502 vbdev_opal_examine(struct spdk_bdev *bdev) 503 { 504 /* TODO */ 505 spdk_bdev_module_examine_done(&opal_if); 506 } 507 508 int 509 vbdev_opal_set_lock_state(const char *bdev_name, uint16_t user_id, const char *password, 510 const char *lock_state) 511 { 512 struct nvme_ctrlr *nvme_ctrlr; 513 int locking_range_id; 514 int rc; 515 enum spdk_opal_lock_state state_flag; 516 struct opal_vbdev *opal_bdev; 517 518 TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) { 519 if (strcmp(opal_bdev->name, bdev_name) == 0) { 520 break; 521 } 522 } 523 524 if (opal_bdev == NULL) { 525 SPDK_ERRLOG("%s not found\n", bdev_name); 526 return -ENODEV; 527 } 528 529 nvme_ctrlr = opal_bdev->nvme_ctrlr; 530 if (nvme_ctrlr == NULL) { 531 SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", opal_bdev->name); 532 return -ENODEV; 533 } 534 535 if (strcasecmp(lock_state, "READWRITE") == 0) { 536 state_flag = OPAL_READWRITE; 537 } else if (strcasecmp(lock_state, "READONLY") == 0) { 538 state_flag = OPAL_READONLY; 539 } else if (strcasecmp(lock_state, "RWLOCK") == 0) { 540 state_flag = OPAL_RWLOCK; 541 } else { 542 SPDK_ERRLOG("Invalid OPAL lock state input\n"); 543 return -EINVAL; 544 } 545 546 locking_range_id = opal_bdev->locking_range_id; 547 rc = spdk_opal_cmd_lock_unlock(nvme_ctrlr->opal_dev, user_id, state_flag, locking_range_id, 548 password); 549 if (rc) { 550 SPDK_ERRLOG("%s lock/unlock failure: %d\n", bdev_name, rc); 551 } 552 553 return rc; 554 } 555 556 int 557 vbdev_opal_enable_new_user(const char *bdev_name, const char *admin_password, uint16_t user_id, 558 const char *user_password) 559 { 560 struct nvme_ctrlr *nvme_ctrlr; 561 int locking_range_id; 562 int rc; 563 struct opal_vbdev *opal_bdev; 564 565 TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) { 566 if (strcmp(opal_bdev->name, bdev_name) == 0) { 567 break; 568 } 569 } 570 571 if (opal_bdev == NULL) { 572 SPDK_ERRLOG("%s not found\n", bdev_name); 573 return -ENODEV; 574 } 575 576 nvme_ctrlr = opal_bdev->nvme_ctrlr; 577 if (nvme_ctrlr == NULL) { 578 SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", opal_bdev->name); 579 return -ENODEV; 580 } 581 582 rc = spdk_opal_cmd_enable_user(nvme_ctrlr->opal_dev, user_id, admin_password); 583 if (rc) { 584 SPDK_ERRLOG("%s enable user error: %d\n", bdev_name, rc); 585 return rc; 586 } 587 588 rc = spdk_opal_cmd_set_new_passwd(nvme_ctrlr->opal_dev, user_id, user_password, admin_password, 589 true); 590 if (rc) { 591 SPDK_ERRLOG("%s set user password error: %d\n", bdev_name, rc); 592 return rc; 593 } 594 595 locking_range_id = opal_bdev->locking_range_id; 596 rc = spdk_opal_cmd_add_user_to_locking_range(nvme_ctrlr->opal_dev, user_id, locking_range_id, 597 OPAL_READONLY, admin_password); 598 if (rc) { 599 SPDK_ERRLOG("%s add user READONLY priority error: %d\n", bdev_name, rc); 600 return rc; 601 } 602 603 rc = spdk_opal_cmd_add_user_to_locking_range(nvme_ctrlr->opal_dev, user_id, locking_range_id, 604 OPAL_READWRITE, admin_password); 605 if (rc) { 606 SPDK_ERRLOG("%s add user READWRITE priority error: %d\n", bdev_name, rc); 607 return rc; 608 } 609 610 return 0; 611 } 612 613 SPDK_LOG_REGISTER_COMPONENT(vbdev_opal) 614