Spdk/lib/ftl/ftl_init.c

212 lines
3.6 KiB
C
Raw Normal View History

/* 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_module.h"
#include "spdk/config.h"
#include "ftl_core.h"
#include "ftl_io.h"
#include "ftl_band.h"
#include "ftl_debug.h"
#include "ftl_nv_cache.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);
spdk_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);
TAILQ_INIT(&dev->ioch_queue);
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)