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

Generated by: LCOV version 1.15