ftl: device startup and shutdown

Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: Ia4a3439a2ac79e24bc6dc11a5c131d44ecb2ad80
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13291
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
This commit is contained in:
Artur Paszkiewicz 2022-06-21 15:45:21 +02:00 committed by Konrad Sztyber
parent 9f6a324301
commit e49ccfc820
16 changed files with 729 additions and 36 deletions

View File

@ -18,6 +18,12 @@ extern "C" {
struct spdk_ftl_dev;
struct spdk_ftl_conf {
/* Device's name */
char *name;
/* Device UUID (valid when restoring device from disk) */
struct spdk_uuid uuid;
/* Percentage of base device blocks not exposed to the user */
uint64_t overprovisioning;
@ -35,9 +41,6 @@ struct spdk_ftl_conf {
/* Name of cache block device (must support extended metadata) */
char *cache_bdev;
/* Base bdev reclaim unit size */
uint64_t base_bdev_reclaim_unit_size;
};
enum spdk_ftl_mode {
@ -45,6 +48,39 @@ enum spdk_ftl_mode {
SPDK_FTL_MODE_CREATE = (1 << 0),
};
typedef void (*spdk_ftl_fn)(void *cb_arg, int status);
typedef void (*spdk_ftl_init_fn)(struct spdk_ftl_dev *dev, void *cb_arg, int status);
/**
* Initialize the FTL on the given pair of bdevs - base and cache bdev.
* Upon receiving a successful completion callback user is free to use I/O calls.
*
* \param conf configuration for new device
* \param cb callback function to call when the device is created
* \param cb_arg callback's argument
*
* \return 0 if initialization was started successfully, negative errno otherwise.
*/
int spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb, void *cb_arg);
/**
* Deinitialize and free given device.
*
* \param dev device
* \param cb callback function to call when the device is freed
* \param cb_arg callback's argument
*
* \return 0 if deinitialization was started successfully, negative errno otherwise.
*/
int spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb, void *cb_arg);
/**
* Initialize FTL configuration structure with default values.
*
* \param conf FTL configuration to initialize
*/
void spdk_ftl_get_default_conf(struct spdk_ftl_conf *conf);
#ifdef __cplusplus
}
#endif

View File

@ -9,12 +9,16 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 5
SO_MINOR := 0
ifneq ($(strip $(SPDK_FTL_ZONE_EMU_BLOCKS)),)
CFLAGS += -DSPDK_FTL_ZONE_EMU_BLOCKS=$(SPDK_FTL_ZONE_EMU_BLOCKS)
endif
CFLAGS += -I.
FTL_SUBDIRS := mngt utils
C_SRCS = ftl_core.c
C_SRCS += mngt/ftl_mngt.c
C_SRCS = ftl_core.c ftl_init.c
C_SRCS += mngt/ftl_mngt.c mngt/ftl_mngt_bdev.c mngt/ftl_mngt_shutdown.c mngt/ftl_mngt_startup.c
C_SRCS += utils/ftl_conf.c
SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_ftl.map)

View File

@ -20,11 +20,8 @@
#include "utils/ftl_log.h"
struct spdk_ftl_dev {
/* Device instance */
struct spdk_uuid uuid;
/* Device name */
char *name;
/* Configuration */
struct spdk_ftl_conf conf;
/* Underlying device */
struct spdk_bdev_desc *base_bdev_desc;
@ -92,4 +89,33 @@ struct spdk_ftl_dev {
TAILQ_HEAD(, ftl_io) wr_sq;
};
static inline uint64_t
ftl_get_num_blocks_in_band(const struct spdk_ftl_dev *dev)
{
return dev->num_blocks_in_band;
}
static inline size_t
ftl_get_num_zones_in_band(const struct spdk_ftl_dev *dev)
{
return dev->num_zones_in_band;
}
static inline size_t
ftl_get_num_blocks_in_zone(const struct spdk_ftl_dev *dev)
{
return dev->num_blocks_in_zone;
}
static inline uint32_t
ftl_get_write_unit_size(struct spdk_bdev *bdev)
{
if (spdk_bdev_is_zoned(bdev)) {
return spdk_bdev_get_write_unit_size(bdev);
}
/* TODO: this should be passed via input parameter */
return 32;
}
#endif /* FTL_CORE_H */

207
lib/ftl/ftl_init.c Normal file
View File

@ -0,0 +1,207 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#include "spdk/stdinc.h"
#include "spdk/nvme.h"
#include "spdk/thread.h"
#include "spdk/string.h"
#include "spdk/likely.h"
#include "spdk/ftl.h"
#include "spdk/likely.h"
#include "spdk/string.h"
#include "spdk/bdev_zone.h"
#include "spdk/bdev_module.h"
#include "spdk/config.h"
#include "ftl_core.h"
#include "ftl_utils.h"
#include "mngt/ftl_mngt.h"
struct ftl_dev_init_ctx {
spdk_ftl_init_fn cb_fn;
/* Callback's argument */
void *cb_arg;
};
struct ftl_dev_free_ctx {
spdk_ftl_fn cb_fn;
/* Callback's argument */
void *cb_arg;
};
static int
init_core_thread(struct spdk_ftl_dev *dev)
{
struct spdk_cpuset cpumask = {};
/*
* If core mask is provided create core thread on first cpu that match with the mask,
* otherwise use current user thread
*/
if (dev->conf.core_mask) {
if (spdk_cpuset_parse(&cpumask, dev->conf.core_mask)) {
return -EINVAL;
}
dev->core_thread = spdk_thread_create("ftl_core_thread", &cpumask);
} else {
dev->core_thread = spdk_get_thread();
}
if (dev->core_thread == NULL) {
FTL_ERRLOG(dev, "Cannot create thread for mask %s\n", dev->conf.core_mask);
return -ENOMEM;
}
return 0;
}
static void
exit_thread(void *ctx)
{
struct spdk_thread *thread = ctx;
spdk_thread_exit(thread);
}
static void
deinit_core_thread(struct spdk_ftl_dev *dev)
{
if (dev->core_thread && dev->conf.core_mask) {
spdk_thread_send_msg(dev->core_thread, exit_thread,
dev->core_thread);
dev->core_thread = NULL;
}
}
static void
free_dev(struct spdk_ftl_dev *dev)
{
if (!dev) {
return;
}
deinit_core_thread(dev);
ftl_conf_deinit(&dev->conf);
free(dev);
}
static struct spdk_ftl_dev *
allocate_dev(const struct spdk_ftl_conf *conf, int *error)
{
int rc;
struct spdk_ftl_dev *dev = calloc(1, sizeof(*dev));
if (!dev) {
FTL_ERRLOG(dev, "Cannot allocate FTL device\n");
*error = -ENOMEM;
return NULL;
}
rc = ftl_conf_init_dev(dev, conf);
if (rc) {
*error = rc;
goto error;
}
rc = init_core_thread(dev);
if (rc) {
*error = rc;
goto error;
}
TAILQ_INIT(&dev->rd_sq);
TAILQ_INIT(&dev->wr_sq);
return dev;
error:
free_dev(dev);
return NULL;
}
static void
dev_init_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
{
struct ftl_dev_init_ctx *ctx = _ctx;
if (status) {
free_dev(dev);
dev = NULL;
}
ctx->cb_fn(dev, ctx->cb_arg, status);
free(ctx);
}
int
spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb_fn, void *cb_arg)
{
int rc = -1;
struct ftl_dev_init_ctx *ctx;
struct spdk_ftl_dev *dev = NULL;
ctx = calloc(1, sizeof(*ctx));
if (!ctx) {
rc = -ENOMEM;
goto error;
}
ctx->cb_fn = cb_fn;
ctx->cb_arg = cb_arg;
dev = allocate_dev(conf, &rc);
if (!dev) {
goto error;
}
rc = ftl_mngt_call_dev_startup(dev, dev_init_cb, ctx);
if (rc) {
goto error;
}
return 0;
error:
free(ctx);
free_dev(dev);
return rc;
}
static void
dev_free_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
{
struct ftl_dev_free_ctx *ctx = _ctx;
if (!status) {
free_dev(dev);
}
ctx->cb_fn(ctx->cb_arg, status);
free(ctx);
}
int
spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
{
int rc = -1;
struct ftl_dev_free_ctx *ctx;
ctx = calloc(1, sizeof(*ctx));
if (!ctx) {
rc = -ENOMEM;
goto error;
}
ctx->cb_fn = cb_fn;
ctx->cb_arg = cb_arg;
rc = ftl_mngt_call_dev_shutdown(dev, dev_free_cb, ctx);
if (rc) {
goto error;
}
return 0;
error:
free(ctx);
return rc;
}
SPDK_LOG_REGISTER_COMPONENT(ftl_init)

View File

@ -13,6 +13,8 @@
/* Marks address as invalid */
#define FTL_ADDR_INVALID ((ftl_addr)-1)
/* Smallest data unit size */
#define FTL_BLOCK_SIZE 4096ULL
/*
* This type represents address in the ftl address space. Values from 0 to based bdev size are

View File

@ -410,31 +410,34 @@ trace_step(struct spdk_ftl_dev *dev, struct ftl_mngt_step *step, bool rollback)
FTL_NOTICELOG(dev, "\t status: %d\n", step->action.status);
}
static void
process_summary(struct ftl_mngt_process *mngt)
{
uint64_t duration;
if (mngt->silent) {
return;
}
duration = mngt->tsc_stop - mngt->tsc_start;
FTL_NOTICELOG(mngt->dev, "Management process finished, "
"name '%s', duration = %.3f ms, result %d\n",
mngt->desc->name,
tsc_to_ms(duration),
mngt->status);
}
static void
finish_msg(void *ctx)
{
struct ftl_mngt_process *mngt = ctx;
char *devname = NULL;
if (!mngt->silent && mngt->dev->conf.name) {
/* the callback below can free the device so make a temp copy of the name */
devname = strdup(mngt->dev->conf.name);
}
mngt->caller.cb(mngt->dev, mngt->caller.cb_ctx, mngt->status);
process_summary(mngt);
if (!mngt->silent) {
/* TODO: refactor the logging macros to pass just the name instead of device */
struct spdk_ftl_dev tmpdev = {
.conf = {
.name = devname
}
};
FTL_NOTICELOG(&tmpdev, "Management process finished, name '%s', duration = %.3f ms, result %d\n",
mngt->desc->name,
tsc_to_ms(mngt->tsc_stop - mngt->tsc_start),
mngt->status);
}
free_mngt(mngt);
free(devname);
}
void

View File

@ -287,4 +287,33 @@ void ftl_mngt_call_process(struct ftl_mngt_process *mngt,
void ftl_mngt_call_process_rollback(struct ftl_mngt_process *mngt,
const struct ftl_mngt_process_desc *process);
/*
* The specific management functions
*/
/**
* @brief Starts up a FTL instance
*
* @param dev FTL device
* @param cb Caller callback
* @param cb_cntx Caller context
*
* @return Operation result
* @retval 0 The operation successful has started
* @retval Non-zero Startup failure
*/
int ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx);
/**
* @brief Shuts down a FTL instance
*
* @param dev FTL device
* @param cb Caller callback
* @param cb_cntx Caller context
*
* @return Operation result
* @retval 0 The operation successful has started
* @retval Non-zero Shutdown failure
*/
int ftl_mngt_call_dev_shutdown(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx);
#endif /* LIB_FTL_FTL_MNGT_H */

View File

@ -0,0 +1,250 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#include "spdk/bdev_module.h"
#include "spdk/ftl.h"
#include "ftl_internal.h"
#include "ftl_mngt_steps.h"
#include "ftl_internal.h"
#include "ftl_core.h"
#include "utils/ftl_defs.h"
#define MINIMUM_CACHE_SIZE_GIB 5
#define MINIMUM_BASE_SIZE_GIB 20
/* Dummy bdev module used to to claim bdevs. */
static struct spdk_bdev_module g_ftl_bdev_module = {
.name = "ftl_lib",
};
static inline size_t
ftl_calculate_num_zones_in_band(struct spdk_bdev_desc *desc)
{
if (spdk_bdev_is_zoned(spdk_bdev_desc_get_bdev(desc))) {
return spdk_bdev_get_optimal_open_zones(spdk_bdev_desc_get_bdev(desc));
}
return 1;
}
static inline size_t
ftl_calculate_num_blocks_in_zone(struct spdk_bdev_desc *desc)
{
if (spdk_bdev_is_zoned(spdk_bdev_desc_get_bdev(desc))) {
return spdk_bdev_get_zone_size(spdk_bdev_desc_get_bdev(desc));
}
/* TODO: this should be passed via input parameter */
#ifdef SPDK_FTL_ZONE_EMU_BLOCKS
return SPDK_FTL_ZONE_EMU_BLOCKS;
#else
return (1ULL << 30) / FTL_BLOCK_SIZE;
#endif
}
static inline uint64_t
ftl_calculate_num_blocks_in_band(struct spdk_bdev_desc *desc)
{
return ftl_calculate_num_zones_in_band(desc) * ftl_calculate_num_blocks_in_zone(desc);
}
static void
base_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx)
{
switch (type) {
case SPDK_BDEV_EVENT_REMOVE:
assert(0);
break;
default:
break;
}
}
void
ftl_mngt_open_base_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
uint32_t block_size;
uint64_t num_blocks;
const char *bdev_name = dev->conf.base_bdev;
struct spdk_bdev *bdev;
if (spdk_bdev_open_ext(bdev_name, true, base_bdev_event_cb,
dev, &dev->base_bdev_desc)) {
FTL_ERRLOG(dev, "Unable to open bdev: %s\n", bdev_name);
goto error;
}
bdev = spdk_bdev_desc_get_bdev(dev->base_bdev_desc);
if (spdk_bdev_module_claim_bdev(bdev, dev->base_bdev_desc, &g_ftl_bdev_module)) {
/* clear the desc so that we don't try to release the claim on cleanup */
spdk_bdev_close(dev->base_bdev_desc);
dev->base_bdev_desc = NULL;
FTL_ERRLOG(dev, "Unable to claim bdev %s\n", bdev_name);
goto error;
}
block_size = spdk_bdev_get_block_size(bdev);
if (block_size != FTL_BLOCK_SIZE) {
FTL_ERRLOG(dev, "Unsupported block size (%"PRIu32")\n", block_size);
goto error;
}
num_blocks = spdk_bdev_get_num_blocks(bdev);
if (num_blocks * block_size < MINIMUM_BASE_SIZE_GIB * GiB) {
FTL_ERRLOG(dev, "Bdev %s is too small, requires, at least %uGiB capacity\n",
spdk_bdev_get_name(bdev), MINIMUM_BASE_SIZE_GIB);
goto error;
}
dev->base_ioch = spdk_bdev_get_io_channel(dev->base_bdev_desc);
if (!dev->base_ioch) {
FTL_ERRLOG(dev, "Failed to create base bdev IO channel\n");
goto error;
}
dev->xfer_size = ftl_get_write_unit_size(bdev);
/* TODO: validate size when base device VSS usage gets added */
dev->md_size = spdk_bdev_get_md_size(bdev);
/* Cache frequently used values */
dev->num_blocks_in_band = ftl_calculate_num_blocks_in_band(dev->base_bdev_desc);
dev->num_zones_in_band = ftl_calculate_num_zones_in_band(dev->base_bdev_desc);
dev->num_blocks_in_zone = ftl_calculate_num_blocks_in_zone(dev->base_bdev_desc);
dev->is_zoned = spdk_bdev_is_zoned(spdk_bdev_desc_get_bdev(dev->base_bdev_desc));
if (dev->is_zoned) {
/* TODO - current FTL code isn't fully compatible with ZNS drives */
FTL_ERRLOG(dev, "Creating FTL on Zoned devices is not supported\n");
goto error;
}
dev->num_bands = num_blocks / ftl_get_num_blocks_in_band(dev);
/* Save a band worth of space for metadata */
dev->num_bands--;
ftl_mngt_next_step(mngt);
return;
error:
ftl_mngt_fail_step(mngt);
}
void
ftl_mngt_close_base_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
if (dev->base_ioch) {
spdk_put_io_channel(dev->base_ioch);
dev->base_ioch = NULL;
}
if (dev->base_bdev_desc) {
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(dev->base_bdev_desc);
spdk_bdev_module_release_bdev(bdev);
spdk_bdev_close(dev->base_bdev_desc);
dev->base_bdev_desc = NULL;
}
ftl_mngt_next_step(mngt);
}
static void
nv_cache_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx)
{
switch (type) {
case SPDK_BDEV_EVENT_REMOVE:
assert(0);
break;
default:
break;
}
}
void
ftl_mngt_open_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
struct spdk_bdev *bdev;
const char *bdev_name = dev->conf.cache_bdev;
if (spdk_bdev_open_ext(bdev_name, true, nv_cache_bdev_event_cb, dev,
&dev->cache_bdev_desc)) {
FTL_ERRLOG(dev, "Unable to open bdev: %s\n", bdev_name);
goto error;
}
bdev = spdk_bdev_desc_get_bdev(dev->cache_bdev_desc);
if (spdk_bdev_module_claim_bdev(bdev, dev->cache_bdev_desc, &g_ftl_bdev_module)) {
/* clear the desc so that we don't try to release the claim on cleanup */
spdk_bdev_close(dev->cache_bdev_desc);
dev->cache_bdev_desc = NULL;
FTL_ERRLOG(dev, "Unable to claim bdev %s\n", bdev_name);
goto error;
}
FTL_NOTICELOG(dev, "Using %s as write buffer cache\n", spdk_bdev_get_name(bdev));
if (spdk_bdev_get_block_size(bdev) != FTL_BLOCK_SIZE) {
FTL_ERRLOG(dev, "Unsupported block size (%d)\n",
spdk_bdev_get_block_size(bdev));
goto error;
}
dev->cache_ioch = spdk_bdev_get_io_channel(dev->cache_bdev_desc);
if (!dev->cache_ioch) {
FTL_ERRLOG(dev, "Failed to create cache IO channel for NV Cache\n");
goto error;
}
if (!spdk_bdev_is_md_separate(bdev)) {
FTL_ERRLOG(dev, "Bdev %s doesn't support separate metadata buffer IO\n",
spdk_bdev_get_name(bdev));
goto error;
}
dev->cache_md_size = spdk_bdev_get_md_size(bdev);
if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) {
FTL_ERRLOG(dev, "Unsupported DIF type used by bdev %s\n",
spdk_bdev_get_name(bdev));
goto error;
}
if (bdev->blockcnt * bdev->blocklen < MINIMUM_CACHE_SIZE_GIB * GiB) {
FTL_ERRLOG(dev, "Bdev %s is too small, requires, at least %uGiB capacity\n",
spdk_bdev_get_name(bdev), MINIMUM_CACHE_SIZE_GIB);
goto error;
}
ftl_mngt_next_step(mngt);
return;
error:
ftl_mngt_fail_step(mngt);
}
void
ftl_mngt_close_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
if (dev->cache_ioch) {
spdk_put_io_channel(dev->cache_ioch);
dev->cache_ioch = NULL;
}
if (dev->cache_bdev_desc) {
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(dev->cache_bdev_desc);
spdk_bdev_module_release_bdev(bdev);
spdk_bdev_close(dev->cache_bdev_desc);
dev->cache_bdev_desc = NULL;
}
ftl_mngt_next_step(mngt);
}

View File

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#include "ftl_core.h"
#include "ftl_mngt.h"
#include "ftl_mngt_steps.h"
static const struct ftl_mngt_process_desc desc_shutdown = {
.name = "FTL shutdown",
.error_handler = ftl_mngt_rollback_device,
.steps = {
{
.name = "Rollback FTL device",
.action = ftl_mngt_rollback_device
},
{}
}
};
int
ftl_mngt_call_dev_shutdown(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx)
{
return ftl_mngt_process_execute(dev, &desc_shutdown, cb, cb_cntx);
}

View File

@ -0,0 +1,39 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#include "ftl_core.h"
#include "ftl_mngt.h"
#include "ftl_mngt_steps.h"
static const struct ftl_mngt_process_desc desc_startup;
static const struct ftl_mngt_process_desc desc_startup = {
.name = "FTL startup",
.steps = {
{
.name = "Open base bdev",
.action = ftl_mngt_open_base_bdev,
.cleanup = ftl_mngt_close_base_bdev
},
{
.name = "Open cache bdev",
.action = ftl_mngt_open_cache_bdev,
.cleanup = ftl_mngt_close_cache_bdev
},
{}
}
};
int
ftl_mngt_call_dev_startup(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx)
{
return ftl_mngt_process_execute(dev, &desc_startup, cb, cb_cntx);
}
void
ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
ftl_mngt_call_process_rollback(mngt, &desc_startup);
}

View File

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#ifndef FTL_MNGT_STEPS_H
#define FTL_MNGT_STEPS_H
#include "ftl_mngt.h"
void ftl_mngt_open_base_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_close_base_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_open_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_close_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
#endif /* FTL_MNGT_STEPS_H */

View File

@ -1,5 +1,10 @@
{
global:
# public functions
spdk_ftl_dev_init;
spdk_ftl_dev_free;
spdk_ftl_get_default_conf;
local: *;
};

View File

@ -7,14 +7,33 @@
#include "ftl_conf.h"
#include "ftl_core.h"
static const struct spdk_ftl_conf g_default_conf = {
/* 20% spare blocks */
.overprovisioning = 20,
/* IO pool size per user thread (this should be adjusted to thread IO qdepth) */
.user_io_pool_size = 2048,
};
void
spdk_ftl_get_default_conf(struct spdk_ftl_conf *conf)
{
*conf = g_default_conf;
}
int
ftl_conf_cpy(struct spdk_ftl_conf *dst, const struct spdk_ftl_conf *src)
{
char *name = NULL;
char *core_mask = NULL;
char *l2p_path = NULL;
char *base_bdev = NULL;
char *cache_bdev = NULL;
if (src->name) {
name = strdup(src->name);
if (!name) {
goto error;
}
}
if (src->core_mask) {
core_mask = strdup(src->core_mask);
if (!core_mask) {
@ -34,18 +53,15 @@ ftl_conf_cpy(struct spdk_ftl_conf *dst, const struct spdk_ftl_conf *src)
}
}
free(dst->core_mask);
free(dst->base_bdev);
free(dst->cache_bdev);
*dst = *src;
dst->name = name;
dst->core_mask = core_mask;
dst->base_bdev = base_bdev;
dst->cache_bdev = cache_bdev;
return 0;
error:
free(name);
free(core_mask);
free(l2p_path);
free(base_bdev);
free(cache_bdev);
return -ENOMEM;
@ -54,7 +70,34 @@ error:
void
ftl_conf_deinit(struct spdk_ftl_conf *conf)
{
free(conf->name);
free(conf->core_mask);
free(conf->base_bdev);
free(conf->cache_bdev);
}
int
ftl_conf_init_dev(struct spdk_ftl_dev *dev, const struct spdk_ftl_conf *conf)
{
int rc;
if (!conf->name) {
FTL_ERRLOG(dev, "No FTL name in configuration\n");
return -EINVAL;
}
if (!conf->base_bdev) {
FTL_ERRLOG(dev, "No base device in configuration\n");
return -EINVAL;
}
if (!conf->cache_bdev) {
FTL_ERRLOG(dev, "No NV cache device in configuration\n");
return -EINVAL;
}
rc = ftl_conf_cpy(&dev->conf, conf);
if (rc) {
return rc;
}
return 0;
}

View File

@ -12,4 +12,6 @@ int ftl_conf_cpy(struct spdk_ftl_conf *dst, const struct spdk_ftl_conf *src);
void ftl_conf_deinit(struct spdk_ftl_conf *conf);
int ftl_conf_init_dev(struct spdk_ftl_dev *dev, const struct spdk_ftl_conf *conf);
#endif /* FTL_DEFS_H */

View File

@ -14,7 +14,7 @@
{ \
spdk_log(SPDK_LOG_##type, __FILE__, __LINE__, __func__, "[FTL] "format, ## __VA_ARGS__); \
} else { \
spdk_log(SPDK_LOG_##type, __FILE__, __LINE__, __func__, "[FTL][%s] "format, (dev)->name, ## __VA_ARGS__); \
spdk_log(SPDK_LOG_##type, __FILE__, __LINE__, __func__, "[FTL][%s] "format, (dev)->conf.name, ## __VA_ARGS__); \
} \
#define FTL_ERRLOG(dev, format, ...) \

View File

@ -60,7 +60,7 @@ DEPDIRS-blobfs := log thread blob trace util
DEPDIRS-event := log util thread $(JSON_LIBS) trace init
DEPDIRS-init := jsonrpc json log rpc thread util
DEPDIRS-ftl := log thread
DEPDIRS-ftl := log util thread bdev
DEPDIRS-nbd := log util thread $(JSON_LIBS) bdev
DEPDIRS-nvmf := accel log sock util nvme thread $(JSON_LIBS) trace bdev
ifeq ($(CONFIG_RDMA),y)