LCOV - code coverage report
Current view: top level - module/bdev/ftl - bdev_ftl.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 338 0.0 %
Date: 2024-12-06 22:24:29 Functions: 0 37 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2020 Intel Corporation.
       3             :  *   All rights reserved.
       4             :  *   Copyright 2023 Solidigm All Rights Reserved
       5             :  */
       6             : 
       7             : #include "spdk/stdinc.h"
       8             : #include "spdk/bdev.h"
       9             : #include "spdk/env.h"
      10             : #include "spdk/thread.h"
      11             : #include "spdk/json.h"
      12             : #include "spdk/string.h"
      13             : #include "spdk/likely.h"
      14             : #include "spdk/util.h"
      15             : #include "spdk/ftl.h"
      16             : #include "spdk/log.h"
      17             : 
      18             : #include "bdev_ftl.h"
      19             : 
      20             : struct ftl_bdev {
      21             :         struct spdk_bdev        bdev;
      22             :         struct spdk_ftl_dev     *dev;
      23             :         ftl_bdev_init_fn        init_cb;
      24             :         void                    *init_arg;
      25             :         int                     rc;
      26             :         struct spdk_bdev_desc   *base_bdev_desc;
      27             :         struct spdk_bdev_desc   *cache_bdev_desc;
      28             : };
      29             : 
      30             : struct bdev_ftl_action {
      31             :         struct spdk_bdev_desc   *ftl_bdev_desc;
      32             :         struct ftl_bdev         *ftl_bdev_dev;
      33             :         spdk_ftl_fn             cb_fn;
      34             :         void                    *cb_arg;
      35             :         int                     rc;
      36             :         size_t                  ctx_size;
      37             :         char                    ctx[0];
      38             : };
      39             : 
      40             : struct ftl_deferred_init {
      41             :         struct spdk_ftl_conf            conf;
      42             : 
      43             :         LIST_ENTRY(ftl_deferred_init)   entry;
      44             : };
      45             : 
      46             : static LIST_HEAD(, ftl_deferred_init)   g_deferred_init = LIST_HEAD_INITIALIZER(g_deferred_init);
      47             : 
      48             : static int bdev_ftl_initialize(void);
      49             : static void bdev_ftl_finish(void);
      50             : static void bdev_ftl_examine(struct spdk_bdev *bdev);
      51             : 
      52             : static void bdev_ftl_action_finish_cb(void *cb_arg, int status);
      53             : static struct bdev_ftl_action *bdev_ftl_action_start(const char *bdev_name,
      54             :                 size_t ctx_size, spdk_ftl_fn cb_fn, void *cb_arg);
      55             : static void bdev_ftl_action_finish(struct bdev_ftl_action *action);
      56             : static void *bdev_ftl_action_ctx(struct bdev_ftl_action *action, size_t size);
      57             : 
      58             : static int
      59           0 : bdev_ftl_get_ctx_size(void)
      60             : {
      61           0 :         return spdk_ftl_io_size();
      62             : }
      63             : 
      64             : static struct spdk_bdev_module g_ftl_if = {
      65             :         .name           = "ftl",
      66             :         .module_init    = bdev_ftl_initialize,
      67             :         .module_fini    = bdev_ftl_finish,
      68             :         .examine_disk   = bdev_ftl_examine,
      69             :         .get_ctx_size   = bdev_ftl_get_ctx_size,
      70             : };
      71             : 
      72           0 : SPDK_BDEV_MODULE_REGISTER(ftl, &g_ftl_if)
      73             : 
      74             : static void
      75           0 : bdev_ftl_free(struct ftl_bdev *ftl_bdev)
      76             : {
      77           0 :         spdk_bdev_close(ftl_bdev->base_bdev_desc);
      78           0 :         spdk_bdev_close(ftl_bdev->cache_bdev_desc);
      79           0 :         free(ftl_bdev->bdev.name);
      80           0 :         free(ftl_bdev);
      81           0 : }
      82             : 
      83             : static void
      84           0 : bdev_ftl_dev_free_cb(void *ctx, int status)
      85             : {
      86           0 :         struct ftl_bdev *ftl_bdev = ctx;
      87             : 
      88           0 :         spdk_bdev_destruct_done(&ftl_bdev->bdev, status);
      89           0 :         bdev_ftl_free(ftl_bdev);
      90           0 : }
      91             : 
      92             : static int
      93           0 : bdev_ftl_destruct(void *ctx)
      94             : {
      95           0 :         struct ftl_bdev *ftl_bdev = ctx;
      96             : 
      97           0 :         spdk_ftl_dev_free(ftl_bdev->dev, bdev_ftl_dev_free_cb, ftl_bdev);
      98             : 
      99             :         /* return 1 to indicate that the destruction is asynchronous */
     100           0 :         return 1;
     101             : }
     102             : 
     103             : static void
     104           0 : bdev_ftl_cb(void *arg, int rc)
     105             : {
     106           0 :         struct spdk_bdev_io *bdev_io = arg;
     107             :         enum spdk_bdev_io_status status;
     108             : 
     109           0 :         switch (rc) {
     110           0 :         case 0:
     111           0 :                 status = SPDK_BDEV_IO_STATUS_SUCCESS;
     112           0 :                 break;
     113           0 :         case -EAGAIN:
     114             :         case -ENOMEM:
     115           0 :                 status = SPDK_BDEV_IO_STATUS_NOMEM;
     116           0 :                 break;
     117           0 :         default:
     118           0 :                 status = SPDK_BDEV_IO_STATUS_FAILED;
     119           0 :                 break;
     120             :         }
     121             : 
     122           0 :         spdk_bdev_io_complete(bdev_io, status);
     123           0 : }
     124             : 
     125             : static void
     126           0 : bdev_ftl_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
     127             :                     bool success)
     128             : {
     129             :         struct ftl_bdev *ftl_bdev;
     130             :         int rc;
     131             : 
     132           0 :         ftl_bdev = bdev_io->bdev->ctxt;
     133             : 
     134           0 :         if (!success) {
     135           0 :                 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
     136           0 :                 return;
     137             :         }
     138             : 
     139           0 :         rc = spdk_ftl_readv(ftl_bdev->dev, (struct ftl_io *)bdev_io->driver_ctx,
     140             :                             ch,
     141             :                             bdev_io->u.bdev.offset_blocks,
     142             :                             bdev_io->u.bdev.num_blocks,
     143           0 :                             bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, bdev_ftl_cb, bdev_io);
     144             : 
     145           0 :         if (spdk_unlikely(rc != 0)) {
     146           0 :                 bdev_ftl_cb(bdev_io, rc);
     147             :         }
     148             : }
     149             : 
     150             : static int
     151           0 : _bdev_ftl_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
     152             : {
     153           0 :         struct ftl_bdev *ftl_bdev = (struct ftl_bdev *)bdev_io->bdev->ctxt;
     154             : 
     155           0 :         switch (bdev_io->type) {
     156           0 :         case SPDK_BDEV_IO_TYPE_READ:
     157           0 :                 spdk_bdev_io_get_buf(bdev_io, bdev_ftl_get_buf_cb,
     158           0 :                                      bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
     159           0 :                 return 0;
     160             : 
     161           0 :         case SPDK_BDEV_IO_TYPE_WRITE:
     162           0 :                 return spdk_ftl_writev(ftl_bdev->dev, (struct ftl_io *)bdev_io->driver_ctx,
     163             :                                        ch, bdev_io->u.bdev.offset_blocks,
     164             :                                        bdev_io->u.bdev.num_blocks, bdev_io->u.bdev.iovs,
     165           0 :                                        bdev_io->u.bdev.iovcnt, bdev_ftl_cb, bdev_io);
     166             : 
     167           0 :         case SPDK_BDEV_IO_TYPE_UNMAP:
     168           0 :                 return spdk_ftl_unmap(ftl_bdev->dev, (struct ftl_io *)bdev_io->driver_ctx,
     169             :                                       ch, bdev_io->u.bdev.offset_blocks,
     170             :                                       bdev_io->u.bdev.num_blocks, bdev_ftl_cb, bdev_io);
     171           0 :         case SPDK_BDEV_IO_TYPE_FLUSH:
     172           0 :                 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
     173           0 :                 return 0;
     174           0 :         default:
     175           0 :                 return -ENOTSUP;
     176             :         }
     177             : }
     178             : 
     179             : static void
     180           0 : bdev_ftl_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
     181             : {
     182           0 :         int rc = _bdev_ftl_submit_request(ch, bdev_io);
     183             : 
     184           0 :         if (spdk_unlikely(rc != 0)) {
     185           0 :                 bdev_ftl_cb(bdev_io, rc);
     186             :         }
     187           0 : }
     188             : 
     189             : static bool
     190           0 : bdev_ftl_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
     191             : {
     192           0 :         switch (io_type) {
     193           0 :         case SPDK_BDEV_IO_TYPE_READ:
     194             :         case SPDK_BDEV_IO_TYPE_WRITE:
     195             :         case SPDK_BDEV_IO_TYPE_FLUSH:
     196             :         case SPDK_BDEV_IO_TYPE_UNMAP:
     197           0 :                 return true;
     198           0 :         default:
     199           0 :                 return false;
     200             :         }
     201             : }
     202             : 
     203             : static struct spdk_io_channel *
     204           0 : bdev_ftl_get_io_channel(void *ctx)
     205             : {
     206           0 :         struct ftl_bdev *ftl_bdev = ctx;
     207             : 
     208           0 :         return spdk_ftl_get_io_channel(ftl_bdev->dev);
     209             : }
     210             : 
     211             : static void
     212           0 : bdev_ftl_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
     213             : {
     214           0 :         struct ftl_bdev *ftl_bdev = bdev->ctxt;
     215           0 :         struct spdk_ftl_conf conf;
     216             : 
     217           0 :         spdk_ftl_dev_get_conf(ftl_bdev->dev, &conf, sizeof(conf));
     218             : 
     219           0 :         spdk_json_write_object_begin(w);
     220             : 
     221           0 :         spdk_json_write_named_string(w, "method", "bdev_ftl_create");
     222             : 
     223           0 :         spdk_json_write_named_object_begin(w, "params");
     224           0 :         spdk_json_write_named_string(w, "name", ftl_bdev->bdev.name);
     225             : 
     226           0 :         spdk_json_write_named_uint64(w, "overprovisioning", conf.overprovisioning);
     227           0 :         spdk_json_write_named_uint64(w, "l2p_dram_limit", conf.l2p_dram_limit);
     228             : 
     229           0 :         if (conf.core_mask) {
     230           0 :                 spdk_json_write_named_string(w, "core_mask", conf.core_mask);
     231             :         }
     232             : 
     233           0 :         spdk_json_write_named_uuid(w, "uuid", &conf.uuid);
     234             : 
     235           0 :         spdk_json_write_named_bool(w, "fast_shutdown", conf.fast_shutdown);
     236             : 
     237           0 :         spdk_json_write_named_string(w, "base_bdev", conf.base_bdev);
     238             : 
     239           0 :         if (conf.cache_bdev) {
     240           0 :                 spdk_json_write_named_string(w, "cache", conf.cache_bdev);
     241             :         }
     242             : 
     243           0 :         spdk_json_write_object_end(w);
     244           0 :         spdk_json_write_object_end(w);
     245           0 : }
     246             : 
     247             : static int
     248           0 : bdev_ftl_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
     249             : {
     250           0 :         struct ftl_bdev *ftl_bdev = ctx;
     251           0 :         struct spdk_ftl_attrs attrs;
     252           0 :         struct spdk_ftl_conf conf;
     253             : 
     254           0 :         spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs, sizeof(attrs));
     255           0 :         spdk_ftl_dev_get_conf(ftl_bdev->dev, &conf, sizeof(conf));
     256             : 
     257           0 :         spdk_json_write_named_object_begin(w, "ftl");
     258             : 
     259           0 :         spdk_json_write_named_string(w, "base_bdev", conf.base_bdev);
     260             : 
     261           0 :         if (conf.cache_bdev) {
     262           0 :                 spdk_json_write_named_string(w, "cache", conf.cache_bdev);
     263             :         }
     264             : 
     265             :         /* ftl */
     266           0 :         spdk_json_write_object_end(w);
     267             : 
     268           0 :         return 0;
     269             : }
     270             : 
     271             : static const struct spdk_bdev_fn_table ftl_fn_table = {
     272             :         .destruct               = bdev_ftl_destruct,
     273             :         .submit_request         = bdev_ftl_submit_request,
     274             :         .io_type_supported      = bdev_ftl_io_type_supported,
     275             :         .get_io_channel         = bdev_ftl_get_io_channel,
     276             :         .write_config_json      = bdev_ftl_write_config_json,
     277             :         .dump_info_json         = bdev_ftl_dump_info_json,
     278             : };
     279             : 
     280             : static void
     281           0 : bdev_ftl_create_err_complete(struct ftl_bdev *ftl_bdev)
     282             : {
     283           0 :         ftl_bdev_init_fn init_cb = ftl_bdev->init_cb;
     284           0 :         void *init_arg = ftl_bdev->init_arg;
     285           0 :         int rc = ftl_bdev->rc;
     286             : 
     287           0 :         bdev_ftl_free(ftl_bdev);
     288             : 
     289           0 :         assert(rc);
     290           0 :         init_cb(NULL, init_arg, rc);
     291           0 : }
     292             : 
     293             : static void
     294           0 : bdev_ftl_create_err_cleanup_cb(void *ctx, int status)
     295             : {
     296           0 :         struct ftl_bdev *ftl_bdev = ctx;
     297             : 
     298           0 :         if (status) {
     299           0 :                 SPDK_ERRLOG("Fatal ERROR of FTL cleanup, name %s\n", ftl_bdev->bdev.name);
     300             :         }
     301             : 
     302           0 :         bdev_ftl_create_err_complete(ftl_bdev);
     303           0 : }
     304             : 
     305             : static void
     306           0 : bdev_ftl_create_cb(struct spdk_ftl_dev *dev, void *ctx, int status)
     307             : {
     308           0 :         struct ftl_bdev         *ftl_bdev = ctx;
     309           0 :         struct ftl_bdev_info    info = {};
     310           0 :         struct spdk_ftl_attrs   attrs;
     311           0 :         struct spdk_ftl_conf    conf;
     312           0 :         ftl_bdev_init_fn        init_cb = ftl_bdev->init_cb;
     313           0 :         void                    *init_arg = ftl_bdev->init_arg;
     314             : 
     315           0 :         if (status) {
     316           0 :                 SPDK_ERRLOG("Failed to create FTL device (%d)\n", status);
     317           0 :                 ftl_bdev->rc = status;
     318           0 :                 goto error;
     319             :         }
     320             : 
     321           0 :         spdk_ftl_dev_get_attrs(dev, &attrs, sizeof(attrs));
     322           0 :         spdk_ftl_dev_get_conf(dev, &conf, sizeof(conf));
     323             : 
     324           0 :         ftl_bdev->dev = dev;
     325           0 :         ftl_bdev->bdev.product_name = "FTL disk";
     326           0 :         ftl_bdev->bdev.write_cache = 0;
     327           0 :         ftl_bdev->bdev.blocklen = attrs.block_size;
     328           0 :         ftl_bdev->bdev.blockcnt = attrs.num_blocks;
     329           0 :         ftl_bdev->bdev.uuid = conf.uuid;
     330           0 :         ftl_bdev->bdev.optimal_io_boundary = attrs.optimum_io_size;
     331           0 :         ftl_bdev->bdev.split_on_optimal_io_boundary = true;
     332             : 
     333           0 :         SPDK_DEBUGLOG(bdev_ftl, "Creating bdev %s:\n", ftl_bdev->bdev.name);
     334           0 :         SPDK_DEBUGLOG(bdev_ftl, "\tblock_len:\t%zu\n", attrs.block_size);
     335           0 :         SPDK_DEBUGLOG(bdev_ftl, "\tnum_blocks:\t%"PRIu64"\n", attrs.num_blocks);
     336             : 
     337           0 :         ftl_bdev->bdev.ctxt = ftl_bdev;
     338           0 :         ftl_bdev->bdev.fn_table = &ftl_fn_table;
     339           0 :         ftl_bdev->bdev.module = &g_ftl_if;
     340             : 
     341           0 :         status = spdk_bdev_register(&ftl_bdev->bdev);
     342           0 :         if (status) {
     343           0 :                 ftl_bdev->rc = status;
     344           0 :                 goto error;
     345             :         }
     346             : 
     347           0 :         info.name = ftl_bdev->bdev.name;
     348           0 :         info.uuid = ftl_bdev->bdev.uuid;
     349             : 
     350           0 :         init_cb(&info, init_arg, 0);
     351           0 :         return;
     352             : 
     353           0 : error:
     354           0 :         if (ftl_bdev->dev) {
     355             :                 /* Cleanup all FTL */
     356           0 :                 spdk_ftl_dev_set_fast_shutdown(ftl_bdev->dev, false);
     357             : 
     358             :                 /* FTL was created, but we have got an error, so we need to delete it */
     359           0 :                 spdk_ftl_dev_free(dev, bdev_ftl_create_err_cleanup_cb, ftl_bdev);
     360             :         } else {
     361           0 :                 bdev_ftl_create_err_complete(ftl_bdev);
     362             :         }
     363             : }
     364             : 
     365             : static void
     366           0 : bdev_ftl_defer_free(struct ftl_deferred_init *init)
     367             : {
     368           0 :         spdk_ftl_conf_deinit(&init->conf);
     369           0 :         free(init);
     370           0 : }
     371             : 
     372             : int
     373           0 : bdev_ftl_defer_init(const struct spdk_ftl_conf *conf)
     374             : {
     375             :         struct ftl_deferred_init *init;
     376             :         int rc;
     377             : 
     378           0 :         init = calloc(1, sizeof(*init));
     379           0 :         if (!init) {
     380           0 :                 return -ENOMEM;
     381             :         }
     382             : 
     383           0 :         rc = spdk_ftl_conf_copy(&init->conf, conf);
     384           0 :         if (rc) {
     385           0 :                 free(init);
     386           0 :                 return -ENOMEM;
     387             :         }
     388             : 
     389           0 :         LIST_INSERT_HEAD(&g_deferred_init, init, entry);
     390             : 
     391           0 :         return 0;
     392             : }
     393             : 
     394             : static void
     395           0 : bdev_ftl_create_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx)
     396             : {
     397           0 : }
     398             : 
     399             : int
     400           0 : bdev_ftl_create_bdev(const struct spdk_ftl_conf *conf, ftl_bdev_init_fn cb, void *cb_arg)
     401             : {
     402             :         struct ftl_bdev *ftl_bdev;
     403           0 :         struct spdk_bdev_desc *base_bdev_desc, *cache_bdev_desc;
     404             :         int rc;
     405             : 
     406           0 :         rc = spdk_bdev_open_ext(conf->base_bdev, false, bdev_ftl_create_bdev_event_cb, NULL,
     407             :                                 &base_bdev_desc);
     408           0 :         if (rc) {
     409           0 :                 return rc;
     410             :         }
     411           0 :         rc = spdk_bdev_open_ext(conf->cache_bdev, false, bdev_ftl_create_bdev_event_cb, NULL,
     412             :                                 &cache_bdev_desc);
     413           0 :         if (rc) {
     414           0 :                 spdk_bdev_close(base_bdev_desc);
     415           0 :                 return rc;
     416             :         }
     417             : 
     418           0 :         ftl_bdev = calloc(1, sizeof(*ftl_bdev));
     419           0 :         if (!ftl_bdev) {
     420           0 :                 SPDK_ERRLOG("Could not allocate ftl_bdev\n");
     421           0 :                 spdk_bdev_close(base_bdev_desc);
     422           0 :                 spdk_bdev_close(cache_bdev_desc);
     423           0 :                 return -ENOMEM;
     424             :         }
     425             : 
     426           0 :         ftl_bdev->base_bdev_desc = base_bdev_desc;
     427           0 :         ftl_bdev->cache_bdev_desc = cache_bdev_desc;
     428             : 
     429           0 :         ftl_bdev->bdev.name = strdup(conf->name);
     430           0 :         if (!ftl_bdev->bdev.name) {
     431           0 :                 rc = -ENOMEM;
     432           0 :                 goto error;
     433             :         }
     434             : 
     435           0 :         ftl_bdev->init_cb = cb;
     436           0 :         ftl_bdev->init_arg = cb_arg;
     437             : 
     438           0 :         rc = spdk_ftl_dev_init(conf, bdev_ftl_create_cb, ftl_bdev);
     439           0 :         if (rc) {
     440           0 :                 SPDK_ERRLOG("Could not create FTL device\n");
     441           0 :                 goto error;
     442             :         }
     443             : 
     444           0 :         return 0;
     445             : 
     446           0 : error:
     447           0 :         bdev_ftl_free(ftl_bdev);
     448           0 :         return rc;
     449             : }
     450             : 
     451             : static int
     452           0 : bdev_ftl_initialize(void)
     453             : {
     454           0 :         return spdk_ftl_init();
     455             : }
     456             : 
     457             : static void
     458           0 : bdev_ftl_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx)
     459             : {
     460           0 : }
     461             : 
     462             : void
     463           0 : bdev_ftl_delete_bdev(const char *name, bool fast_shutdown, spdk_bdev_unregister_cb cb_fn,
     464             :                      void *cb_arg)
     465             : {
     466           0 :         struct spdk_bdev_desc   *ftl_bdev_desc;
     467             :         struct spdk_bdev *bdev;
     468             :         struct ftl_bdev *ftl;
     469             :         int rc;
     470             : 
     471           0 :         rc = spdk_bdev_open_ext(name, false, bdev_ftl_event_cb, NULL, &ftl_bdev_desc);
     472             : 
     473           0 :         if (rc) {
     474           0 :                 goto not_found;
     475             :         }
     476             : 
     477           0 :         bdev = spdk_bdev_desc_get_bdev(ftl_bdev_desc);
     478             : 
     479           0 :         if (bdev->module != &g_ftl_if) {
     480           0 :                 goto bdev_opened;
     481             :         }
     482             : 
     483           0 :         ftl = bdev->ctxt;
     484           0 :         assert(ftl);
     485           0 :         spdk_ftl_dev_set_fast_shutdown(ftl->dev, fast_shutdown);
     486           0 :         spdk_bdev_close(ftl_bdev_desc);
     487             : 
     488           0 :         rc = spdk_bdev_unregister_by_name(name, &g_ftl_if, cb_fn, cb_arg);
     489           0 :         if (rc) {
     490           0 :                 cb_fn(cb_arg, rc);
     491             :         }
     492             : 
     493           0 :         return;
     494           0 : bdev_opened:
     495           0 :         spdk_bdev_close(ftl_bdev_desc);
     496           0 : not_found:
     497           0 :         cb_fn(cb_arg, -ENODEV);
     498             : }
     499             : 
     500             : void
     501           0 : bdev_ftl_unmap(const char *name, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb_fn,
     502             :                void *cb_arg)
     503             : {
     504             :         struct bdev_ftl_action *action;
     505             : 
     506           0 :         action = bdev_ftl_action_start(name, 0, cb_fn, cb_arg);
     507           0 :         if (!action) {
     508           0 :                 return;
     509             :         }
     510             : 
     511             :         /* It's ok to pass NULL as IO channel - FTL will detect this and use it's internal IO channel for management operations */
     512           0 :         action->rc = spdk_ftl_unmap(action->ftl_bdev_dev->dev, NULL, NULL, lba, num_blocks,
     513             :                                     bdev_ftl_action_finish_cb, action);
     514           0 :         if (action->rc) {
     515           0 :                 bdev_ftl_action_finish(action);
     516             :         }
     517             : }
     518             : 
     519             : static void
     520           0 : bdev_ftl_get_stats_cb(struct ftl_stats *stats, void *cb_arg)
     521             : {
     522           0 :         struct bdev_ftl_action *action = cb_arg;
     523             : 
     524           0 :         bdev_ftl_action_finish(action);
     525           0 : }
     526             : 
     527             : void
     528           0 : bdev_ftl_get_stats(const char *name, spdk_ftl_fn cb, struct rpc_ftl_stats_ctx *ftl_stats_ctx)
     529             : {
     530             :         struct bdev_ftl_action *action;
     531             : 
     532           0 :         action = bdev_ftl_action_start(name, 0, cb, ftl_stats_ctx);
     533           0 :         if (!action) {
     534           0 :                 return;
     535             :         }
     536           0 :         ftl_stats_ctx->ftl_bdev_desc = action->ftl_bdev_desc;
     537           0 :         action->rc = spdk_ftl_get_stats(action->ftl_bdev_dev->dev, &ftl_stats_ctx->ftl_stats,
     538             :                                         bdev_ftl_get_stats_cb, action);
     539           0 :         if (action->rc) {
     540           0 :                 bdev_ftl_action_finish(action);
     541             :         }
     542             : }
     543             : 
     544             : void
     545           0 : bdev_ftl_get_properties(const char *name, spdk_ftl_fn cb_fn, struct spdk_jsonrpc_request *request)
     546             : {
     547             :         struct bdev_ftl_action *action;
     548             : 
     549           0 :         action = bdev_ftl_action_start(name, 0, cb_fn, request);
     550           0 :         if (!action) {
     551           0 :                 return;
     552             :         }
     553             : 
     554           0 :         action->rc = spdk_ftl_get_properties(action->ftl_bdev_dev->dev, request,
     555             :                                              bdev_ftl_action_finish_cb, action);
     556           0 :         if (action->rc) {
     557           0 :                 bdev_ftl_action_finish(action);
     558             :         }
     559             : }
     560             : 
     561             : struct bdev_ftl_set_property_args {
     562             :         char *property;
     563             :         char *value;
     564             : };
     565             : 
     566             : static void
     567           0 : bdev_ftl_set_property_cb(void *cb_arg, int status)
     568             : {
     569           0 :         struct bdev_ftl_action *action = cb_arg;
     570           0 :         struct bdev_ftl_set_property_args *args = bdev_ftl_action_ctx(action, sizeof(*args));
     571             : 
     572           0 :         free(args->property);
     573           0 :         free(args->value);
     574           0 :         args->property = NULL;
     575           0 :         args->value = NULL;
     576           0 :         bdev_ftl_action_finish_cb(cb_arg, status);
     577           0 : }
     578             : 
     579             : void
     580           0 : bdev_ftl_set_property(const char *name, const char *property, const char *value,
     581             :                       spdk_ftl_fn cb_fn, void *cb_arg)
     582             : {
     583             :         struct bdev_ftl_action *action;
     584             :         struct bdev_ftl_set_property_args *args;
     585             : 
     586           0 :         action = bdev_ftl_action_start(name, sizeof(*args), cb_fn, cb_arg);
     587           0 :         if (!action) {
     588           0 :                 return;
     589             :         }
     590             : 
     591           0 :         args = bdev_ftl_action_ctx(action, sizeof(*args));
     592           0 :         args->property = strdup(property);
     593           0 :         args->value = strdup(value);
     594             : 
     595           0 :         if (!args->property || !args->value) {
     596           0 :                 free(args->property);
     597           0 :                 free(args->value);
     598           0 :                 action->rc = -ENOMEM;
     599           0 :                 bdev_ftl_action_finish(action);
     600           0 :                 return;
     601             :         }
     602             : 
     603           0 :         action->rc = spdk_ftl_set_property(action->ftl_bdev_dev->dev,
     604           0 :                                            args->property, args->value, strlen(args->value) + 1,
     605             :                                            bdev_ftl_set_property_cb, action);
     606           0 :         if (action->rc) {
     607           0 :                 bdev_ftl_action_finish(action);
     608             :         }
     609             : }
     610             : 
     611             : static void
     612           0 : bdev_ftl_finish(void)
     613             : {
     614           0 :         spdk_ftl_fini();
     615           0 : }
     616             : 
     617             : static void
     618           0 : bdev_ftl_create_deferred_cb(const struct ftl_bdev_info *info, void *ctx, int status)
     619             : {
     620           0 :         struct ftl_deferred_init *opts = ctx;
     621             : 
     622           0 :         if (status) {
     623           0 :                 SPDK_ERRLOG("Failed to initialize FTL bdev '%s'\n", opts->conf.name);
     624             :         }
     625             : 
     626           0 :         bdev_ftl_defer_free(opts);
     627             : 
     628           0 :         spdk_bdev_module_examine_done(&g_ftl_if);
     629           0 : }
     630             : 
     631             : static void
     632           0 : bdev_ftl_examine(struct spdk_bdev *bdev)
     633             : {
     634             :         struct ftl_deferred_init *opts;
     635             :         int rc;
     636             : 
     637           0 :         LIST_FOREACH(opts, &g_deferred_init, entry) {
     638             :                 /* spdk_bdev_module_examine_done will be called by bdev_ftl_create_deferred_cb */
     639           0 :                 rc = bdev_ftl_create_bdev(&opts->conf, bdev_ftl_create_deferred_cb, opts);
     640           0 :                 if (rc == -ENODEV) {
     641           0 :                         continue;
     642             :                 }
     643             : 
     644           0 :                 LIST_REMOVE(opts, entry);
     645             : 
     646           0 :                 if (rc) {
     647           0 :                         bdev_ftl_create_deferred_cb(NULL, opts, rc);
     648             :                 }
     649           0 :                 return;
     650             :         }
     651             : 
     652           0 :         spdk_bdev_module_examine_done(&g_ftl_if);
     653             : }
     654             : 
     655           0 : SPDK_LOG_REGISTER_COMPONENT(bdev_ftl)
     656             : 
     657             : /*
     658             :  * Generic function to execute an action on the FTL bdev
     659             :  */
     660             : static void
     661           0 : bdev_ftl_action_finish(struct bdev_ftl_action *action)
     662             : {
     663           0 :         action->cb_fn(action->cb_arg, action->rc);
     664           0 :         if (action->ftl_bdev_desc) {
     665           0 :                 spdk_bdev_close(action->ftl_bdev_desc);
     666             :         }
     667           0 :         free(action);
     668           0 : }
     669             : 
     670             : static struct bdev_ftl_action *
     671           0 : bdev_ftl_action_start(const char *bdev_name, size_t ctx_size, spdk_ftl_fn cb_fn, void *cb_arg)
     672             : {
     673             :         struct spdk_bdev *bdev;
     674           0 :         struct bdev_ftl_action *action = calloc(1, sizeof(*action) + ctx_size);
     675             : 
     676           0 :         if (NULL == action) {
     677           0 :                 cb_fn(cb_arg, -ENOMEM);
     678           0 :                 return NULL;
     679             :         }
     680           0 :         action->cb_arg = cb_arg;
     681           0 :         action->cb_fn = cb_fn;
     682           0 :         action->ctx_size = ctx_size;
     683             : 
     684           0 :         action->rc = spdk_bdev_open_ext(bdev_name, false, bdev_ftl_event_cb, NULL, &action->ftl_bdev_desc);
     685           0 :         if (action->rc) {
     686           0 :                 goto error;
     687             :         }
     688             : 
     689           0 :         bdev = spdk_bdev_desc_get_bdev(action->ftl_bdev_desc);
     690           0 :         if (bdev->module != &g_ftl_if) {
     691           0 :                 action->rc = -ENODEV;
     692           0 :                 goto error;
     693             :         }
     694             : 
     695           0 :         action->ftl_bdev_dev = bdev->ctxt;
     696           0 :         assert(action->ftl_bdev_dev);
     697             : 
     698           0 :         return action;
     699           0 : error:
     700           0 :         bdev_ftl_action_finish(action);
     701           0 :         return NULL;
     702             : }
     703             : 
     704             : static void
     705           0 : bdev_ftl_action_finish_cb(void *cb_arg, int status)
     706             : {
     707           0 :         struct bdev_ftl_action *action = cb_arg;
     708             : 
     709           0 :         action->rc = status;
     710           0 :         bdev_ftl_action_finish(action);
     711           0 : }
     712             : 
     713             : static void *
     714           0 : bdev_ftl_action_ctx(struct bdev_ftl_action *action, size_t size)
     715             : {
     716           0 :         assert(action->ctx_size);
     717           0 :         assert(size == action->ctx_size);
     718           0 :         return action->ctx;
     719             : }

Generated by: LCOV version 1.15