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/stdinc.h" 35 #include "spdk/bdev.h" 36 #include "spdk/conf.h" 37 #include "spdk/env.h" 38 #include "spdk/io_channel.h" 39 #include "spdk/json.h" 40 #include "spdk/string.h" 41 #include "spdk/likely.h" 42 #include "spdk/util.h" 43 #include "spdk/string.h" 44 #include "spdk/ftl.h" 45 #include "spdk_internal/log.h" 46 47 #include "bdev_ftl.h" 48 49 #define FTL_COMPLETION_RING_SIZE 4096 50 51 struct ftl_bdev { 52 struct spdk_bdev bdev; 53 54 struct spdk_ftl_dev *dev; 55 56 ftl_bdev_init_fn init_cb; 57 58 void *init_arg; 59 }; 60 61 struct ftl_io_channel { 62 struct spdk_ftl_dev *dev; 63 64 struct spdk_poller *poller; 65 66 #define FTL_MAX_COMPLETIONS 64 67 struct ftl_bdev_io *io[FTL_MAX_COMPLETIONS]; 68 69 /* Completion ring */ 70 struct spdk_ring *ring; 71 72 struct spdk_io_channel *ioch; 73 }; 74 75 struct ftl_bdev_io { 76 struct ftl_bdev *bdev; 77 78 struct spdk_ring *ring; 79 80 int status; 81 }; 82 83 struct ftl_deferred_init { 84 struct ftl_bdev_init_opts opts; 85 86 LIST_ENTRY(ftl_deferred_init) entry; 87 }; 88 89 static LIST_HEAD(, ftl_deferred_init) g_deferred_init = LIST_HEAD_INITIALIZER(g_deferred_init); 90 91 static int bdev_ftl_initialize(void); 92 static void bdev_ftl_finish(void); 93 static void bdev_ftl_examine(struct spdk_bdev *bdev); 94 95 static int 96 bdev_ftl_get_ctx_size(void) 97 { 98 return sizeof(struct ftl_bdev_io); 99 } 100 101 static struct spdk_bdev_module g_ftl_if = { 102 .name = "ftl", 103 .module_init = bdev_ftl_initialize, 104 .module_fini = bdev_ftl_finish, 105 .examine_disk = bdev_ftl_examine, 106 .get_ctx_size = bdev_ftl_get_ctx_size, 107 }; 108 109 SPDK_BDEV_MODULE_REGISTER(ftl, &g_ftl_if) 110 111 static void 112 bdev_ftl_free_cb(struct spdk_ftl_dev *dev, void *ctx, int status) 113 { 114 struct ftl_bdev *ftl_bdev = ctx; 115 116 spdk_io_device_unregister(ftl_bdev, NULL); 117 118 spdk_bdev_destruct_done(&ftl_bdev->bdev, status); 119 free(ftl_bdev->bdev.name); 120 free(ftl_bdev); 121 } 122 123 static int 124 bdev_ftl_destruct(void *ctx) 125 { 126 struct ftl_bdev *ftl_bdev = ctx; 127 spdk_ftl_dev_free(ftl_bdev->dev, bdev_ftl_free_cb, ftl_bdev); 128 129 /* return 1 to indicate that the destruction is asynchronous */ 130 return 1; 131 } 132 133 static void 134 bdev_ftl_complete_io(struct ftl_bdev_io *io, int rc) 135 { 136 enum spdk_bdev_io_status status; 137 138 switch (rc) { 139 case 0: 140 status = SPDK_BDEV_IO_STATUS_SUCCESS; 141 break; 142 case -ENOMEM: 143 status = SPDK_BDEV_IO_STATUS_NOMEM; 144 break; 145 default: 146 status = SPDK_BDEV_IO_STATUS_FAILED; 147 break; 148 } 149 150 spdk_bdev_io_complete(spdk_bdev_io_from_ctx(io), status); 151 } 152 153 static void 154 bdev_ftl_cb(void *arg, int status) 155 { 156 struct ftl_bdev_io *io = arg; 157 size_t cnt __attribute__((unused)); 158 159 io->status = status; 160 161 cnt = spdk_ring_enqueue(io->ring, (void **)&io, 1, NULL); 162 assert(cnt == 1); 163 } 164 165 static int 166 bdev_ftl_fill_bio(struct ftl_bdev *ftl_bdev, struct spdk_io_channel *ch, 167 struct ftl_bdev_io *io) 168 { 169 struct ftl_io_channel *ioch = spdk_io_channel_get_ctx(ch); 170 171 memset(io, 0, sizeof(*io)); 172 173 io->status = SPDK_BDEV_IO_STATUS_SUCCESS; 174 io->ring = ioch->ring; 175 io->bdev = ftl_bdev; 176 return 0; 177 } 178 179 static int 180 bdev_ftl_readv(struct ftl_bdev *ftl_bdev, struct spdk_io_channel *ch, 181 struct ftl_bdev_io *io) 182 { 183 struct spdk_bdev_io *bio; 184 struct ftl_io_channel *ioch = spdk_io_channel_get_ctx(ch); 185 int rc; 186 187 bio = spdk_bdev_io_from_ctx(io); 188 189 rc = bdev_ftl_fill_bio(ftl_bdev, ch, io); 190 if (rc) { 191 return rc; 192 } 193 194 return spdk_ftl_read(ftl_bdev->dev, 195 ioch->ioch, 196 bio->u.bdev.offset_blocks, 197 bio->u.bdev.num_blocks, 198 bio->u.bdev.iovs, bio->u.bdev.iovcnt, bdev_ftl_cb, io); 199 } 200 201 static int 202 bdev_ftl_writev(struct ftl_bdev *ftl_bdev, struct spdk_io_channel *ch, 203 struct ftl_bdev_io *io) 204 { 205 struct spdk_bdev_io *bio; 206 struct ftl_io_channel *ioch; 207 int rc; 208 209 bio = spdk_bdev_io_from_ctx(io); 210 ioch = spdk_io_channel_get_ctx(ch); 211 212 rc = bdev_ftl_fill_bio(ftl_bdev, ch, io); 213 if (rc) { 214 return rc; 215 } 216 217 return spdk_ftl_write(ftl_bdev->dev, 218 ioch->ioch, 219 bio->u.bdev.offset_blocks, 220 bio->u.bdev.num_blocks, 221 bio->u.bdev.iovs, 222 bio->u.bdev.iovcnt, bdev_ftl_cb, io); 223 } 224 225 static void 226 bdev_ftl_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, 227 bool success) 228 { 229 if (!success) { 230 bdev_ftl_complete_io((struct ftl_bdev_io *)bdev_io->driver_ctx, 231 SPDK_BDEV_IO_STATUS_FAILED); 232 return; 233 } 234 235 int rc = bdev_ftl_readv((struct ftl_bdev *)bdev_io->bdev->ctxt, 236 ch, (struct ftl_bdev_io *)bdev_io->driver_ctx); 237 238 if (spdk_unlikely(rc != 0)) { 239 bdev_ftl_complete_io((struct ftl_bdev_io *)bdev_io->driver_ctx, rc); 240 } 241 } 242 243 static int 244 bdev_ftl_flush(struct ftl_bdev *ftl_bdev, struct spdk_io_channel *ch, struct ftl_bdev_io *io) 245 { 246 int rc; 247 248 rc = bdev_ftl_fill_bio(ftl_bdev, ch, io); 249 if (rc) { 250 return rc; 251 } 252 253 return spdk_ftl_flush(ftl_bdev->dev, bdev_ftl_cb, io); 254 } 255 256 static int 257 _bdev_ftl_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 258 { 259 struct ftl_bdev *ftl_bdev = (struct ftl_bdev *)bdev_io->bdev->ctxt; 260 261 switch (bdev_io->type) { 262 case SPDK_BDEV_IO_TYPE_READ: 263 spdk_bdev_io_get_buf(bdev_io, bdev_ftl_get_buf_cb, 264 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen); 265 return 0; 266 267 case SPDK_BDEV_IO_TYPE_WRITE: 268 return bdev_ftl_writev(ftl_bdev, ch, (struct ftl_bdev_io *)bdev_io->driver_ctx); 269 270 case SPDK_BDEV_IO_TYPE_FLUSH: 271 return bdev_ftl_flush(ftl_bdev, ch, (struct ftl_bdev_io *)bdev_io->driver_ctx); 272 273 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: 274 case SPDK_BDEV_IO_TYPE_RESET: 275 case SPDK_BDEV_IO_TYPE_UNMAP: 276 default: 277 return -ENOTSUP; 278 break; 279 } 280 } 281 282 static void 283 bdev_ftl_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 284 { 285 int rc = _bdev_ftl_submit_request(ch, bdev_io); 286 287 if (spdk_unlikely(rc != 0)) { 288 bdev_ftl_complete_io((struct ftl_bdev_io *)bdev_io->driver_ctx, rc); 289 } 290 } 291 292 static bool 293 bdev_ftl_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) 294 { 295 switch (io_type) { 296 case SPDK_BDEV_IO_TYPE_READ: 297 case SPDK_BDEV_IO_TYPE_WRITE: 298 case SPDK_BDEV_IO_TYPE_FLUSH: 299 return true; 300 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: 301 case SPDK_BDEV_IO_TYPE_RESET: 302 case SPDK_BDEV_IO_TYPE_UNMAP: 303 default: 304 return false; 305 } 306 } 307 308 static struct spdk_io_channel * 309 bdev_ftl_get_io_channel(void *ctx) 310 { 311 struct ftl_bdev *ftl_bdev = ctx; 312 313 return spdk_get_io_channel(ftl_bdev); 314 } 315 316 static void 317 _bdev_ftl_write_config_info(struct ftl_bdev *ftl_bdev, struct spdk_json_write_ctx *w) 318 { 319 struct spdk_ftl_attrs attrs = {}; 320 321 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs); 322 323 spdk_json_write_named_string(w, "base_bdev", attrs.base_bdev); 324 325 if (attrs.cache_bdev) { 326 spdk_json_write_named_string(w, "cache", attrs.cache_bdev); 327 } 328 } 329 330 static void 331 bdev_ftl_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) 332 { 333 struct ftl_bdev *ftl_bdev = bdev->ctxt; 334 struct spdk_ftl_attrs attrs; 335 struct spdk_ftl_conf *conf = &attrs.conf; 336 char uuid[SPDK_UUID_STRING_LEN]; 337 338 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs); 339 340 spdk_json_write_object_begin(w); 341 342 spdk_json_write_named_string(w, "method", "bdev_ftl_create"); 343 344 spdk_json_write_named_object_begin(w, "params"); 345 spdk_json_write_named_string(w, "name", ftl_bdev->bdev.name); 346 347 spdk_json_write_named_bool(w, "allow_open_bands", conf->allow_open_bands); 348 spdk_json_write_named_uint64(w, "overprovisioning", conf->lba_rsvd); 349 spdk_json_write_named_uint64(w, "limit_crit", conf->limits[SPDK_FTL_LIMIT_CRIT].limit); 350 spdk_json_write_named_uint64(w, "limit_crit_threshold", conf->limits[SPDK_FTL_LIMIT_CRIT].thld); 351 spdk_json_write_named_uint64(w, "limit_high", conf->limits[SPDK_FTL_LIMIT_HIGH].limit); 352 spdk_json_write_named_uint64(w, "limit_high_threshold", conf->limits[SPDK_FTL_LIMIT_HIGH].thld); 353 spdk_json_write_named_uint64(w, "limit_low", conf->limits[SPDK_FTL_LIMIT_LOW].limit); 354 spdk_json_write_named_uint64(w, "limit_low_threshold", conf->limits[SPDK_FTL_LIMIT_LOW].thld); 355 spdk_json_write_named_uint64(w, "limit_start", conf->limits[SPDK_FTL_LIMIT_START].limit); 356 spdk_json_write_named_uint64(w, "limit_start_threshold", conf->limits[SPDK_FTL_LIMIT_START].thld); 357 358 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &attrs.uuid); 359 spdk_json_write_named_string(w, "uuid", uuid); 360 361 _bdev_ftl_write_config_info(ftl_bdev, w); 362 363 spdk_json_write_object_end(w); 364 spdk_json_write_object_end(w); 365 } 366 367 static int 368 bdev_ftl_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) 369 { 370 struct ftl_bdev *ftl_bdev = ctx; 371 struct spdk_ftl_attrs attrs; 372 373 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs); 374 375 spdk_json_write_named_object_begin(w, "ftl"); 376 377 _bdev_ftl_write_config_info(ftl_bdev, w); 378 spdk_json_write_named_string_fmt(w, "num_zones", "%zu", attrs.num_zones); 379 spdk_json_write_named_string_fmt(w, "zone_size", "%zu", attrs.zone_size); 380 381 /* ftl */ 382 spdk_json_write_object_end(w); 383 384 return 0; 385 } 386 387 static const struct spdk_bdev_fn_table ftl_fn_table = { 388 .destruct = bdev_ftl_destruct, 389 .submit_request = bdev_ftl_submit_request, 390 .io_type_supported = bdev_ftl_io_type_supported, 391 .get_io_channel = bdev_ftl_get_io_channel, 392 .write_config_json = bdev_ftl_write_config_json, 393 .dump_info_json = bdev_ftl_dump_info_json, 394 }; 395 396 static int 397 bdev_ftl_poll(void *arg) 398 { 399 struct ftl_io_channel *ch = arg; 400 size_t cnt, i; 401 402 cnt = spdk_ring_dequeue(ch->ring, (void **)&ch->io, FTL_MAX_COMPLETIONS); 403 404 for (i = 0; i < cnt; ++i) { 405 bdev_ftl_complete_io(ch->io[i], ch->io[i]->status); 406 } 407 408 return cnt; 409 } 410 411 static int 412 bdev_ftl_io_channel_create_cb(void *io_device, void *ctx) 413 { 414 struct ftl_io_channel *ch = ctx; 415 struct ftl_bdev *ftl_bdev = (struct ftl_bdev *)io_device; 416 417 ch->dev = ftl_bdev->dev; 418 ch->ring = spdk_ring_create(SPDK_RING_TYPE_MP_SC, FTL_COMPLETION_RING_SIZE, 419 SPDK_ENV_SOCKET_ID_ANY); 420 421 if (!ch->ring) { 422 return -ENOMEM; 423 } 424 425 ch->poller = spdk_poller_register(bdev_ftl_poll, ch, 0); 426 if (!ch->poller) { 427 spdk_ring_free(ch->ring); 428 return -ENOMEM; 429 } 430 431 ch->ioch = spdk_get_io_channel(ftl_bdev->dev); 432 433 return 0; 434 } 435 436 static void 437 bdev_ftl_io_channel_destroy_cb(void *io_device, void *ctx_buf) 438 { 439 struct ftl_io_channel *ch = ctx_buf; 440 441 spdk_ring_free(ch->ring); 442 spdk_poller_unregister(&ch->poller); 443 spdk_put_io_channel(ch->ioch); 444 } 445 446 static void 447 bdev_ftl_create_cb(struct spdk_ftl_dev *dev, void *ctx, int status) 448 { 449 struct ftl_bdev *ftl_bdev = ctx; 450 struct ftl_bdev_info info = {}; 451 struct spdk_ftl_attrs attrs; 452 ftl_bdev_init_fn init_cb = ftl_bdev->init_cb; 453 void *init_arg = ftl_bdev->init_arg; 454 int rc = -ENODEV; 455 456 if (status) { 457 SPDK_ERRLOG("Failed to create FTL device (%d)\n", status); 458 rc = status; 459 goto error_dev; 460 } 461 462 spdk_ftl_dev_get_attrs(dev, &attrs); 463 464 ftl_bdev->dev = dev; 465 ftl_bdev->bdev.product_name = "FTL disk"; 466 ftl_bdev->bdev.write_cache = 0; 467 ftl_bdev->bdev.blocklen = attrs.block_size; 468 ftl_bdev->bdev.blockcnt = attrs.num_blocks; 469 ftl_bdev->bdev.uuid = attrs.uuid; 470 471 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "Creating bdev %s:\n", ftl_bdev->bdev.name); 472 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "\tblock_len:\t%zu\n", attrs.block_size); 473 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "\tnum_blocks:\t%"PRIu64"\n", attrs.num_blocks); 474 475 ftl_bdev->bdev.ctxt = ftl_bdev; 476 ftl_bdev->bdev.fn_table = &ftl_fn_table; 477 ftl_bdev->bdev.module = &g_ftl_if; 478 479 spdk_io_device_register(ftl_bdev, bdev_ftl_io_channel_create_cb, 480 bdev_ftl_io_channel_destroy_cb, 481 sizeof(struct ftl_io_channel), 482 ftl_bdev->bdev.name); 483 484 if (spdk_bdev_register(&ftl_bdev->bdev)) { 485 goto error_unregister; 486 } 487 488 info.name = ftl_bdev->bdev.name; 489 info.uuid = ftl_bdev->bdev.uuid; 490 491 init_cb(&info, init_arg, 0); 492 return; 493 494 error_unregister: 495 spdk_io_device_unregister(ftl_bdev, NULL); 496 error_dev: 497 free(ftl_bdev->bdev.name); 498 free(ftl_bdev); 499 500 init_cb(NULL, init_arg, rc); 501 } 502 503 static void 504 bdev_ftl_defer_free(struct ftl_deferred_init *init) 505 { 506 free((char *)init->opts.name); 507 free((char *)init->opts.base_bdev); 508 free((char *)init->opts.cache_bdev); 509 free(init); 510 } 511 512 static int 513 bdev_ftl_defer_init(const struct ftl_bdev_init_opts *opts) 514 { 515 struct ftl_deferred_init *init; 516 517 init = calloc(1, sizeof(*init)); 518 if (!init) { 519 return -ENOMEM; 520 } 521 522 init->opts.mode = opts->mode; 523 init->opts.uuid = opts->uuid; 524 init->opts.ftl_conf = opts->ftl_conf; 525 526 init->opts.name = strdup(opts->name); 527 if (!init->opts.name) { 528 SPDK_ERRLOG("Could not allocate bdev name\n"); 529 goto error; 530 } 531 532 init->opts.base_bdev = strdup(opts->base_bdev); 533 if (!init->opts.base_bdev) { 534 SPDK_ERRLOG("Could not allocate base bdev name\n"); 535 goto error; 536 } 537 538 if (opts->cache_bdev) { 539 init->opts.cache_bdev = strdup(opts->cache_bdev); 540 if (!init->opts.cache_bdev) { 541 SPDK_ERRLOG("Could not allocate cache bdev name\n"); 542 goto error; 543 } 544 } 545 546 LIST_INSERT_HEAD(&g_deferred_init, init, entry); 547 548 return 0; 549 550 error: 551 bdev_ftl_defer_free(init); 552 return -ENOMEM; 553 } 554 555 int 556 bdev_ftl_create_bdev(const struct ftl_bdev_init_opts *bdev_opts, 557 ftl_bdev_init_fn cb, void *cb_arg) 558 { 559 struct ftl_bdev *ftl_bdev = NULL; 560 struct spdk_ftl_dev_init_opts opts = {}; 561 int rc; 562 563 ftl_bdev = calloc(1, sizeof(*ftl_bdev)); 564 if (!ftl_bdev) { 565 SPDK_ERRLOG("Could not allocate ftl_bdev\n"); 566 return -ENOMEM; 567 } 568 569 ftl_bdev->bdev.name = strdup(bdev_opts->name); 570 if (!ftl_bdev->bdev.name) { 571 rc = -ENOMEM; 572 goto error_bdev; 573 } 574 575 if (spdk_bdev_get_by_name(bdev_opts->base_bdev) == NULL || 576 (bdev_opts->cache_bdev && spdk_bdev_get_by_name(bdev_opts->cache_bdev) == NULL)) { 577 rc = bdev_ftl_defer_init(bdev_opts); 578 if (rc == 0) { 579 rc = -ENODEV; 580 } 581 goto error_name; 582 } 583 584 ftl_bdev->init_cb = cb; 585 ftl_bdev->init_arg = cb_arg; 586 587 opts.mode = bdev_opts->mode; 588 opts.uuid = bdev_opts->uuid; 589 opts.name = ftl_bdev->bdev.name; 590 opts.base_bdev = bdev_opts->base_bdev; 591 opts.cache_bdev = bdev_opts->cache_bdev; 592 opts.conf = &bdev_opts->ftl_conf; 593 594 /* TODO: set threads based on config */ 595 opts.core_thread = spdk_get_thread(); 596 597 rc = spdk_ftl_dev_init(&opts, bdev_ftl_create_cb, ftl_bdev); 598 if (rc) { 599 SPDK_ERRLOG("Could not create FTL device\n"); 600 goto error_name; 601 } 602 603 return 0; 604 605 error_name: 606 free(ftl_bdev->bdev.name); 607 error_bdev: 608 free(ftl_bdev); 609 return rc; 610 } 611 612 static int 613 bdev_ftl_initialize(void) 614 { 615 return 0; 616 } 617 618 void 619 bdev_ftl_delete_bdev(const char *name, spdk_bdev_unregister_cb cb_fn, void *cb_arg) 620 { 621 struct spdk_bdev *bdev; 622 623 bdev = spdk_bdev_get_by_name(name); 624 if (bdev) { 625 spdk_bdev_unregister(bdev, cb_fn, cb_arg); 626 return; 627 } 628 629 cb_fn(cb_arg, -ENODEV); 630 } 631 632 static void 633 bdev_ftl_finish(void) 634 { 635 } 636 637 static void 638 bdev_ftl_create_defered_cb(const struct ftl_bdev_info *info, void *ctx, int status) 639 { 640 struct ftl_deferred_init *opts = ctx; 641 642 if (status) { 643 SPDK_ERRLOG("Failed to initialize FTL bdev '%s'\n", opts->opts.name); 644 } 645 646 bdev_ftl_defer_free(opts); 647 648 spdk_bdev_module_examine_done(&g_ftl_if); 649 } 650 651 static void 652 bdev_ftl_examine(struct spdk_bdev *bdev) 653 { 654 struct ftl_deferred_init *opts; 655 656 LIST_FOREACH(opts, &g_deferred_init, entry) { 657 if (spdk_bdev_get_by_name(opts->opts.base_bdev) == NULL) { 658 continue; 659 } 660 661 if (opts->opts.cache_bdev && spdk_bdev_get_by_name(opts->opts.base_bdev) == NULL) { 662 continue; 663 } 664 665 LIST_REMOVE(opts, entry); 666 667 /* spdk_bdev_module_examine_done will be called by bdev_ftl_create_defered_cb */ 668 if (bdev_ftl_create_bdev(&opts->opts, bdev_ftl_create_defered_cb, opts)) { 669 SPDK_ERRLOG("Failed to initialize FTL bdev '%s'\n", opts->opts.name); 670 bdev_ftl_defer_free(opts); 671 break; 672 } 673 return; 674 } 675 676 spdk_bdev_module_examine_done(&g_ftl_if); 677 } 678 679 SPDK_LOG_REGISTER_COMPONENT("bdev_ftl", SPDK_LOG_BDEV_FTL) 680