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 struct ftl_bdev { 50 struct spdk_bdev bdev; 51 52 struct spdk_ftl_dev *dev; 53 54 ftl_bdev_init_fn init_cb; 55 56 void *init_arg; 57 }; 58 59 struct ftl_deferred_init { 60 struct ftl_bdev_init_opts opts; 61 62 LIST_ENTRY(ftl_deferred_init) entry; 63 }; 64 65 static LIST_HEAD(, ftl_deferred_init) g_deferred_init = LIST_HEAD_INITIALIZER(g_deferred_init); 66 67 static int bdev_ftl_initialize(void); 68 static void bdev_ftl_finish(void); 69 static void bdev_ftl_examine(struct spdk_bdev *bdev); 70 71 static struct spdk_bdev_module g_ftl_if = { 72 .name = "ftl", 73 .module_init = bdev_ftl_initialize, 74 .module_fini = bdev_ftl_finish, 75 .examine_disk = bdev_ftl_examine, 76 }; 77 78 SPDK_BDEV_MODULE_REGISTER(ftl, &g_ftl_if) 79 80 static void 81 bdev_ftl_free_cb(struct spdk_ftl_dev *dev, void *ctx, int status) 82 { 83 struct ftl_bdev *ftl_bdev = ctx; 84 85 spdk_bdev_destruct_done(&ftl_bdev->bdev, status); 86 free(ftl_bdev->bdev.name); 87 free(ftl_bdev); 88 } 89 90 static int 91 bdev_ftl_destruct(void *ctx) 92 { 93 struct ftl_bdev *ftl_bdev = ctx; 94 spdk_ftl_dev_free(ftl_bdev->dev, bdev_ftl_free_cb, ftl_bdev); 95 96 /* return 1 to indicate that the destruction is asynchronous */ 97 return 1; 98 } 99 100 static void 101 bdev_ftl_cb(void *arg, int rc) 102 { 103 struct spdk_bdev_io *bdev_io = arg; 104 enum spdk_bdev_io_status status; 105 106 switch (rc) { 107 case 0: 108 status = SPDK_BDEV_IO_STATUS_SUCCESS; 109 break; 110 case -ENOMEM: 111 status = SPDK_BDEV_IO_STATUS_NOMEM; 112 break; 113 default: 114 status = SPDK_BDEV_IO_STATUS_FAILED; 115 break; 116 } 117 118 spdk_bdev_io_complete(bdev_io, status); 119 } 120 121 static void 122 bdev_ftl_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, 123 bool success) 124 { 125 struct ftl_bdev *ftl_bdev; 126 int rc; 127 128 ftl_bdev = bdev_io->bdev->ctxt; 129 130 if (!success) { 131 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 132 return; 133 } 134 135 rc = spdk_ftl_read(ftl_bdev->dev, 136 ch, 137 bdev_io->u.bdev.offset_blocks, 138 bdev_io->u.bdev.num_blocks, 139 bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, bdev_ftl_cb, bdev_io); 140 141 if (spdk_unlikely(rc != 0)) { 142 spdk_bdev_io_complete(bdev_io, rc); 143 } 144 } 145 146 static int 147 _bdev_ftl_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 148 { 149 struct ftl_bdev *ftl_bdev = (struct ftl_bdev *)bdev_io->bdev->ctxt; 150 151 switch (bdev_io->type) { 152 case SPDK_BDEV_IO_TYPE_READ: 153 spdk_bdev_io_get_buf(bdev_io, bdev_ftl_get_buf_cb, 154 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen); 155 return 0; 156 157 case SPDK_BDEV_IO_TYPE_WRITE: 158 return spdk_ftl_write(ftl_bdev->dev, ch, bdev_io->u.bdev.offset_blocks, 159 bdev_io->u.bdev.num_blocks, bdev_io->u.bdev.iovs, 160 bdev_io->u.bdev.iovcnt, bdev_ftl_cb, bdev_io); 161 162 case SPDK_BDEV_IO_TYPE_FLUSH: 163 return spdk_ftl_flush(ftl_bdev->dev, bdev_ftl_cb, bdev_io); 164 165 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: 166 case SPDK_BDEV_IO_TYPE_RESET: 167 case SPDK_BDEV_IO_TYPE_UNMAP: 168 default: 169 return -ENOTSUP; 170 break; 171 } 172 } 173 174 static void 175 bdev_ftl_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 176 { 177 int rc = _bdev_ftl_submit_request(ch, bdev_io); 178 179 if (spdk_unlikely(rc != 0)) { 180 spdk_bdev_io_complete(bdev_io, rc); 181 } 182 } 183 184 static bool 185 bdev_ftl_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) 186 { 187 switch (io_type) { 188 case SPDK_BDEV_IO_TYPE_READ: 189 case SPDK_BDEV_IO_TYPE_WRITE: 190 case SPDK_BDEV_IO_TYPE_FLUSH: 191 return true; 192 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES: 193 case SPDK_BDEV_IO_TYPE_RESET: 194 case SPDK_BDEV_IO_TYPE_UNMAP: 195 default: 196 return false; 197 } 198 } 199 200 static struct spdk_io_channel * 201 bdev_ftl_get_io_channel(void *ctx) 202 { 203 struct ftl_bdev *ftl_bdev = ctx; 204 205 return spdk_get_io_channel(ftl_bdev->dev); 206 } 207 208 static void 209 _bdev_ftl_write_config_info(struct ftl_bdev *ftl_bdev, struct spdk_json_write_ctx *w) 210 { 211 struct spdk_ftl_attrs attrs = {}; 212 213 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs); 214 215 spdk_json_write_named_string(w, "base_bdev", attrs.base_bdev); 216 217 if (attrs.cache_bdev) { 218 spdk_json_write_named_string(w, "cache", attrs.cache_bdev); 219 } 220 } 221 222 static void 223 bdev_ftl_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) 224 { 225 struct ftl_bdev *ftl_bdev = bdev->ctxt; 226 struct spdk_ftl_attrs attrs; 227 struct spdk_ftl_conf *conf = &attrs.conf; 228 char uuid[SPDK_UUID_STRING_LEN]; 229 230 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs); 231 232 spdk_json_write_object_begin(w); 233 234 spdk_json_write_named_string(w, "method", "bdev_ftl_create"); 235 236 spdk_json_write_named_object_begin(w, "params"); 237 spdk_json_write_named_string(w, "name", ftl_bdev->bdev.name); 238 239 spdk_json_write_named_bool(w, "allow_open_bands", conf->allow_open_bands); 240 spdk_json_write_named_uint64(w, "overprovisioning", conf->lba_rsvd); 241 spdk_json_write_named_uint64(w, "limit_crit", conf->limits[SPDK_FTL_LIMIT_CRIT].limit); 242 spdk_json_write_named_uint64(w, "limit_crit_threshold", conf->limits[SPDK_FTL_LIMIT_CRIT].thld); 243 spdk_json_write_named_uint64(w, "limit_high", conf->limits[SPDK_FTL_LIMIT_HIGH].limit); 244 spdk_json_write_named_uint64(w, "limit_high_threshold", conf->limits[SPDK_FTL_LIMIT_HIGH].thld); 245 spdk_json_write_named_uint64(w, "limit_low", conf->limits[SPDK_FTL_LIMIT_LOW].limit); 246 spdk_json_write_named_uint64(w, "limit_low_threshold", conf->limits[SPDK_FTL_LIMIT_LOW].thld); 247 spdk_json_write_named_uint64(w, "limit_start", conf->limits[SPDK_FTL_LIMIT_START].limit); 248 spdk_json_write_named_uint64(w, "limit_start_threshold", conf->limits[SPDK_FTL_LIMIT_START].thld); 249 250 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &attrs.uuid); 251 spdk_json_write_named_string(w, "uuid", uuid); 252 253 _bdev_ftl_write_config_info(ftl_bdev, w); 254 255 spdk_json_write_object_end(w); 256 spdk_json_write_object_end(w); 257 } 258 259 static int 260 bdev_ftl_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) 261 { 262 struct ftl_bdev *ftl_bdev = ctx; 263 struct spdk_ftl_attrs attrs; 264 265 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs); 266 267 spdk_json_write_named_object_begin(w, "ftl"); 268 269 _bdev_ftl_write_config_info(ftl_bdev, w); 270 spdk_json_write_named_string_fmt(w, "num_zones", "%zu", attrs.num_zones); 271 spdk_json_write_named_string_fmt(w, "zone_size", "%zu", attrs.zone_size); 272 273 /* ftl */ 274 spdk_json_write_object_end(w); 275 276 return 0; 277 } 278 279 static const struct spdk_bdev_fn_table ftl_fn_table = { 280 .destruct = bdev_ftl_destruct, 281 .submit_request = bdev_ftl_submit_request, 282 .io_type_supported = bdev_ftl_io_type_supported, 283 .get_io_channel = bdev_ftl_get_io_channel, 284 .write_config_json = bdev_ftl_write_config_json, 285 .dump_info_json = bdev_ftl_dump_info_json, 286 }; 287 288 static void 289 bdev_ftl_create_cb(struct spdk_ftl_dev *dev, void *ctx, int status) 290 { 291 struct ftl_bdev *ftl_bdev = ctx; 292 struct ftl_bdev_info info = {}; 293 struct spdk_ftl_attrs attrs; 294 ftl_bdev_init_fn init_cb = ftl_bdev->init_cb; 295 void *init_arg = ftl_bdev->init_arg; 296 int rc = -ENODEV; 297 298 if (status) { 299 SPDK_ERRLOG("Failed to create FTL device (%d)\n", status); 300 rc = status; 301 goto error; 302 } 303 304 spdk_ftl_dev_get_attrs(dev, &attrs); 305 306 ftl_bdev->dev = dev; 307 ftl_bdev->bdev.product_name = "FTL disk"; 308 ftl_bdev->bdev.write_cache = 0; 309 ftl_bdev->bdev.blocklen = attrs.block_size; 310 ftl_bdev->bdev.blockcnt = attrs.num_blocks; 311 ftl_bdev->bdev.uuid = attrs.uuid; 312 313 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "Creating bdev %s:\n", ftl_bdev->bdev.name); 314 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "\tblock_len:\t%zu\n", attrs.block_size); 315 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "\tnum_blocks:\t%"PRIu64"\n", attrs.num_blocks); 316 317 ftl_bdev->bdev.ctxt = ftl_bdev; 318 ftl_bdev->bdev.fn_table = &ftl_fn_table; 319 ftl_bdev->bdev.module = &g_ftl_if; 320 321 if (spdk_bdev_register(&ftl_bdev->bdev)) { 322 goto error; 323 } 324 325 info.name = ftl_bdev->bdev.name; 326 info.uuid = ftl_bdev->bdev.uuid; 327 328 init_cb(&info, init_arg, 0); 329 return; 330 331 error: 332 free(ftl_bdev->bdev.name); 333 free(ftl_bdev); 334 335 init_cb(NULL, init_arg, rc); 336 } 337 338 static void 339 bdev_ftl_defer_free(struct ftl_deferred_init *init) 340 { 341 free((char *)init->opts.name); 342 free((char *)init->opts.base_bdev); 343 free((char *)init->opts.cache_bdev); 344 free(init); 345 } 346 347 static int 348 bdev_ftl_defer_init(const struct ftl_bdev_init_opts *opts) 349 { 350 struct ftl_deferred_init *init; 351 352 init = calloc(1, sizeof(*init)); 353 if (!init) { 354 return -ENOMEM; 355 } 356 357 init->opts.mode = opts->mode; 358 init->opts.uuid = opts->uuid; 359 init->opts.ftl_conf = opts->ftl_conf; 360 361 init->opts.name = strdup(opts->name); 362 if (!init->opts.name) { 363 SPDK_ERRLOG("Could not allocate bdev name\n"); 364 goto error; 365 } 366 367 init->opts.base_bdev = strdup(opts->base_bdev); 368 if (!init->opts.base_bdev) { 369 SPDK_ERRLOG("Could not allocate base bdev name\n"); 370 goto error; 371 } 372 373 if (opts->cache_bdev) { 374 init->opts.cache_bdev = strdup(opts->cache_bdev); 375 if (!init->opts.cache_bdev) { 376 SPDK_ERRLOG("Could not allocate cache bdev name\n"); 377 goto error; 378 } 379 } 380 381 LIST_INSERT_HEAD(&g_deferred_init, init, entry); 382 383 return 0; 384 385 error: 386 bdev_ftl_defer_free(init); 387 return -ENOMEM; 388 } 389 390 int 391 bdev_ftl_create_bdev(const struct ftl_bdev_init_opts *bdev_opts, 392 ftl_bdev_init_fn cb, void *cb_arg) 393 { 394 struct ftl_bdev *ftl_bdev = NULL; 395 struct spdk_ftl_dev_init_opts opts = {}; 396 int rc; 397 398 ftl_bdev = calloc(1, sizeof(*ftl_bdev)); 399 if (!ftl_bdev) { 400 SPDK_ERRLOG("Could not allocate ftl_bdev\n"); 401 return -ENOMEM; 402 } 403 404 ftl_bdev->bdev.name = strdup(bdev_opts->name); 405 if (!ftl_bdev->bdev.name) { 406 rc = -ENOMEM; 407 goto error_bdev; 408 } 409 410 if (spdk_bdev_get_by_name(bdev_opts->base_bdev) == NULL || 411 (bdev_opts->cache_bdev && spdk_bdev_get_by_name(bdev_opts->cache_bdev) == NULL)) { 412 rc = bdev_ftl_defer_init(bdev_opts); 413 if (rc == 0) { 414 rc = -ENODEV; 415 } 416 goto error_name; 417 } 418 419 ftl_bdev->init_cb = cb; 420 ftl_bdev->init_arg = cb_arg; 421 422 opts.mode = bdev_opts->mode; 423 opts.uuid = bdev_opts->uuid; 424 opts.name = ftl_bdev->bdev.name; 425 opts.base_bdev = bdev_opts->base_bdev; 426 opts.cache_bdev = bdev_opts->cache_bdev; 427 opts.conf = &bdev_opts->ftl_conf; 428 429 /* TODO: set threads based on config */ 430 opts.core_thread = spdk_get_thread(); 431 432 rc = spdk_ftl_dev_init(&opts, bdev_ftl_create_cb, ftl_bdev); 433 if (rc) { 434 SPDK_ERRLOG("Could not create FTL device\n"); 435 goto error_name; 436 } 437 438 return 0; 439 440 error_name: 441 free(ftl_bdev->bdev.name); 442 error_bdev: 443 free(ftl_bdev); 444 return rc; 445 } 446 447 static int 448 bdev_ftl_initialize(void) 449 { 450 return 0; 451 } 452 453 void 454 bdev_ftl_delete_bdev(const char *name, spdk_bdev_unregister_cb cb_fn, void *cb_arg) 455 { 456 struct spdk_bdev *bdev; 457 458 bdev = spdk_bdev_get_by_name(name); 459 if (bdev) { 460 spdk_bdev_unregister(bdev, cb_fn, cb_arg); 461 return; 462 } 463 464 cb_fn(cb_arg, -ENODEV); 465 } 466 467 static void 468 bdev_ftl_finish(void) 469 { 470 } 471 472 static void 473 bdev_ftl_create_defered_cb(const struct ftl_bdev_info *info, void *ctx, int status) 474 { 475 struct ftl_deferred_init *opts = ctx; 476 477 if (status) { 478 SPDK_ERRLOG("Failed to initialize FTL bdev '%s'\n", opts->opts.name); 479 } 480 481 bdev_ftl_defer_free(opts); 482 483 spdk_bdev_module_examine_done(&g_ftl_if); 484 } 485 486 static void 487 bdev_ftl_examine(struct spdk_bdev *bdev) 488 { 489 struct ftl_deferred_init *opts; 490 491 LIST_FOREACH(opts, &g_deferred_init, entry) { 492 if (spdk_bdev_get_by_name(opts->opts.base_bdev) == NULL) { 493 continue; 494 } 495 496 if (opts->opts.cache_bdev && spdk_bdev_get_by_name(opts->opts.base_bdev) == NULL) { 497 continue; 498 } 499 500 LIST_REMOVE(opts, entry); 501 502 /* spdk_bdev_module_examine_done will be called by bdev_ftl_create_defered_cb */ 503 if (bdev_ftl_create_bdev(&opts->opts, bdev_ftl_create_defered_cb, opts)) { 504 SPDK_ERRLOG("Failed to initialize FTL bdev '%s'\n", opts->opts.name); 505 bdev_ftl_defer_free(opts); 506 break; 507 } 508 return; 509 } 510 511 spdk_bdev_module_examine_done(&g_ftl_if); 512 } 513 514 SPDK_LOG_REGISTER_COMPONENT("bdev_ftl", SPDK_LOG_BDEV_FTL) 515