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