2022-06-21 13:45:21 +00:00
|
|
|
/* 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"
|
2022-06-21 11:04:00 +00:00
|
|
|
#include "ftl_io.h"
|
2022-06-21 13:05:28 +00:00
|
|
|
#include "ftl_band.h"
|
2022-06-20 09:44:35 +00:00
|
|
|
#include "ftl_debug.h"
|
2022-06-13 09:54:12 +00:00
|
|
|
#include "ftl_nv_cache.h"
|
2022-06-21 13:45:21 +00:00
|
|
|
#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);
|
2022-06-21 09:20:47 +00:00
|
|
|
spdk_ftl_conf_deinit(&dev->conf);
|
2022-06-21 13:45:21 +00:00
|
|
|
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);
|
2022-06-21 11:03:31 +00:00
|
|
|
TAILQ_INIT(&dev->ioch_queue);
|
2022-06-21 13:45:21 +00:00
|
|
|
|
|
|
|
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)
|