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