lib/ftl: ANM logic removal

ANM logic should be moved to ocssd bdev.
This patch temporarily disables ANM handling
by FTL library. New ANM handling mechanism will
be introduced in future patches.

Change-Id: I7d0261ee4e42496f60b82fbf6b39d9f84690024f
Signed-off-by: Wojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468784
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Mateusz Kozlowski <mateusz.kozlowski@intel.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
This commit is contained in:
Wojciech Malikowski 2019-09-19 03:48:44 -04:00 committed by Tomasz Zawadzki
parent 1735a0acd3
commit 988759501d
5 changed files with 11 additions and 703 deletions

View File

@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
C_SRCS = ftl_band.c ftl_core.c ftl_debug.c ftl_io.c ftl_rwb.c ftl_reloc.c \
ftl_anm.c ftl_restore.c ftl_init.c ftl_trace.c
ftl_restore.c ftl_init.c ftl_trace.c
LIBNAME = ftl

View File

@ -1,567 +0,0 @@
/*-
* BSD LICENSE
*
* Copyright (c) Intel Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "spdk/stdinc.h"
#include "spdk/nvme_spec.h"
#include "spdk/nvme_ocssd_spec.h"
#include "spdk/thread.h"
#include "spdk/ftl.h"
#include "ftl_anm.h"
#include "ftl_core.h"
#include "ftl_band.h"
#include "ftl_debug.h"
/* Number of log pages read in single get_log_page call */
#define FTL_ANM_LOG_ENTRIES 16
/* Structure aggregating ANM callback registered by ftl device */
struct ftl_anm_poller {
struct spdk_ftl_dev *dev;
ftl_anm_fn fn;
LIST_ENTRY(ftl_anm_poller) list_entry;
};
struct ftl_anm_ctrlr {
/* NVMe controller */
struct spdk_nvme_ctrlr *ctrlr;
/* NVMe namespace */
struct spdk_nvme_ns *ns;
/* Outstanding ANM event counter */
int anm_outstanding;
/* Indicates if get log page command has been submitted to controller */
int processing;
/* Notification counter */
uint64_t nc;
/* DMA allocated buffer for log pages */
struct spdk_ocssd_chunk_notification_entry *log;
/* Protects ctrlr against process_admin_completions from multiple threads */
pthread_mutex_t lock;
/* List link */
LIST_ENTRY(ftl_anm_ctrlr) list_entry;
/* List of registered pollers */
LIST_HEAD(, ftl_anm_poller) pollers;
};
struct ftl_anm {
struct spdk_thread *thread;
struct spdk_poller *poller;
pthread_mutex_t lock;
/* List of registered controllers */
LIST_HEAD(, ftl_anm_ctrlr) ctrlrs;
};
struct ftl_anm_init_ctx {
spdk_ftl_fn cb;
void *cb_arg;
};
static struct ftl_anm g_anm = { .lock = PTHREAD_MUTEX_INITIALIZER };
static int
ftl_anm_log_range(struct spdk_ocssd_chunk_notification_entry *log)
{
if (log->mask.lblk) {
return FTL_ANM_RANGE_LBK;
}
if (log->mask.chunk) {
return FTL_ANM_RANGE_CHK;
}
if (log->mask.pu) {
return FTL_ANM_RANGE_PU;
}
assert(0);
return FTL_ANM_RANGE_MAX;
}
static struct ftl_anm_event *
ftl_anm_event_alloc(struct spdk_ftl_dev *dev, struct ftl_addr addr,
enum ftl_anm_range range, size_t num_lbks)
{
struct ftl_anm_event *event;
event = calloc(1, sizeof(*event));
if (!event) {
return NULL;
}
event->dev = dev;
event->addr = addr;
switch (range) {
case FTL_ANM_RANGE_LBK:
event->num_lbks = num_lbks;
break;
case FTL_ANM_RANGE_CHK:
case FTL_ANM_RANGE_PU:
event->num_lbks = ftl_dev_lbks_in_zone(dev);
break;
default:
assert(false);
}
return event;
}
static int
ftl_anm_process_log(struct ftl_anm_poller *poller,
struct spdk_ocssd_chunk_notification_entry *log)
{
struct ftl_anm_event *event;
struct ftl_addr addr = ftl_addr_addr_unpack(poller->dev, log->lba);
struct spdk_ftl_dev *dev = poller->dev;
enum ftl_anm_range range = ftl_anm_log_range(log);
int i, num_bands = 1;
num_bands = range != FTL_ANM_RANGE_PU ? 1 : ftl_dev_num_bands(dev);
for (i = 0; i < num_bands; ++i) {
struct ftl_zone *zone = ftl_band_zone_from_addr(&dev->bands[i], addr);
if (zone->state == SPDK_BDEV_ZONE_STATE_OFFLINE) {
continue;
}
event = ftl_anm_event_alloc(dev, addr, range, log->nlb);
if (!event) {
return -ENOMEM;
}
poller->fn(event);
addr.zone_id++;
}
return 0;
}
static bool
ftl_anm_in_poller_range(struct ftl_anm_poller *poller,
struct spdk_ocssd_chunk_notification_entry *log)
{
struct spdk_ftl_dev *dev = poller->dev;
struct ftl_addr addr = ftl_addr_addr_unpack(dev, log->lba);
char buf[128];
if (addr.zone_id >= ftl_dev_num_bands(dev)) {
SPDK_ERRLOG("ANM log contains invalid @addr: %s\n",
ftl_addr2str(addr, buf, sizeof(buf)));
return false;
}
return true;
}
static int
ftl_anm_log_valid(struct ftl_anm_ctrlr *ctrlr,
struct spdk_ocssd_chunk_notification_entry *log)
{
/* Initialize ctrlr->nc during the first log page read */
if (!ctrlr->nc && log->nc) {
ctrlr->nc = log->nc - 1;
}
if (log->nc > ctrlr->nc) {
ctrlr->nc = log->nc;
return 1;
}
return 0;
}
static void
ftl_anm_log_page_cb(void *ctx, const struct spdk_nvme_cpl *cpl)
{
struct ftl_anm_ctrlr *ctrlr = ctx;
struct ftl_anm_poller *poller;
pthread_mutex_lock(&ctrlr->lock);
if (spdk_nvme_cpl_is_error(cpl)) {
SPDK_ERRLOG("Unexpected status code: [%d], status code type: [%d]\n",
cpl->status.sc, cpl->status.sct);
goto out;
}
for (size_t i = 0; i < FTL_ANM_LOG_ENTRIES; ++i) {
if (!ftl_anm_log_valid(ctrlr, &ctrlr->log[i])) {
goto out;
}
LIST_FOREACH(poller, &ctrlr->pollers, list_entry) {
struct spdk_ocssd_chunk_notification_entry *log = &ctrlr->log[i];
if (!ftl_anm_in_poller_range(poller, log)) {
continue;
}
if (ftl_anm_process_log(poller, log)) {
SPDK_ERRLOG("Failed to process ANM log by dev: %p\n", poller->dev);
}
break;
}
}
/* We increment anm_outstanding counter in case there are more logs in controller */
/* than we get in single log page call */
ctrlr->anm_outstanding++;
out:
ctrlr->processing = 0;
pthread_mutex_unlock(&ctrlr->lock);
}
static void
ftl_anm_aer_cb(void *ctx, const struct spdk_nvme_cpl *cpl)
{
union spdk_nvme_async_event_completion event = { .raw = cpl->cdw0 };
struct ftl_anm_ctrlr *ctrlr = ctx;
if (spdk_nvme_cpl_is_error(cpl)) {
SPDK_ERRLOG("Unexpected status code: [%d], status code type: [%d]\n",
cpl->status.sc, cpl->status.sct);
return;
}
pthread_mutex_lock(&ctrlr->lock);
if (event.bits.async_event_type == SPDK_NVME_ASYNC_EVENT_TYPE_VENDOR &&
event.bits.log_page_identifier == SPDK_OCSSD_LOG_CHUNK_NOTIFICATION) {
ctrlr->anm_outstanding++;
}
pthread_mutex_unlock(&ctrlr->lock);
}
static int
ftl_anm_get_log_page(struct ftl_anm_ctrlr *ctrlr)
{
uint32_t nsid = spdk_nvme_ns_get_id(ctrlr->ns);
ctrlr->anm_outstanding = 0;
if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr->ctrlr, SPDK_OCSSD_LOG_CHUNK_NOTIFICATION, nsid,
ctrlr->log, sizeof(*ctrlr->log) * FTL_ANM_LOG_ENTRIES, 0,
ftl_anm_log_page_cb, (void *)ctrlr)) {
return -1;
}
ctrlr->processing = 1;
return 0;
}
static int
ftl_anm_poller_cb(void *ctx)
{
struct ftl_anm *anm = ctx;
struct ftl_anm_ctrlr *ctrlr;
int rc = 0, num_processed = 0;
pthread_mutex_lock(&anm->lock);
LIST_FOREACH(ctrlr, &anm->ctrlrs, list_entry) {
rc = spdk_nvme_ctrlr_process_admin_completions(ctrlr->ctrlr);
if (rc < 0) {
SPDK_ERRLOG("Processing admin completions failed\n");
break;
}
num_processed += rc;
pthread_mutex_lock(&ctrlr->lock);
if (ctrlr->anm_outstanding && !ctrlr->processing) {
if (ftl_anm_get_log_page(ctrlr)) {
SPDK_ERRLOG("Failed to get log page from controller %p",
ctrlr->ctrlr);
}
}
pthread_mutex_unlock(&ctrlr->lock);
}
pthread_mutex_unlock(&anm->lock);
return num_processed;
}
static struct ftl_anm_poller *
ftl_anm_alloc_poller(struct spdk_ftl_dev *dev, ftl_anm_fn fn)
{
struct ftl_anm_poller *poller;
poller = calloc(1, sizeof(*poller));
if (!poller) {
return NULL;
}
poller->fn = fn;
poller->dev = dev;
return poller;
}
static void
ftl_anm_ctrlr_free(struct ftl_anm_ctrlr *ctrlr)
{
if (!ctrlr) {
return;
}
/* Unregister ctrlr from aer events */
spdk_nvme_ctrlr_register_aer_callback(ctrlr->ctrlr, NULL, NULL);
pthread_mutex_destroy(&ctrlr->lock);
spdk_dma_free(ctrlr->log);
free(ctrlr);
}
static struct ftl_anm_ctrlr *
ftl_anm_ctrlr_alloc(struct spdk_ftl_dev *dev)
{
struct ftl_anm_ctrlr *ctrlr;
ctrlr = calloc(1, sizeof(*ctrlr));
if (!ctrlr) {
return NULL;
}
ctrlr->log = spdk_dma_zmalloc(sizeof(*ctrlr->log) * FTL_ANM_LOG_ENTRIES,
4096, NULL);
if (!ctrlr->log) {
goto free_ctrlr;
}
if (pthread_mutex_init(&ctrlr->lock, NULL)) {
goto free_log;
}
/* Set the outstanding counter to force log page retrieval */
/* to consume events already present on the controller */
ctrlr->anm_outstanding = 1;
ctrlr->ctrlr = dev->ctrlr;
ctrlr->ns = dev->ns;
LIST_INIT(&ctrlr->pollers);
spdk_nvme_ctrlr_register_aer_callback(ctrlr->ctrlr, ftl_anm_aer_cb, ctrlr);
return ctrlr;
free_log:
free(ctrlr->log);
free_ctrlr:
free(ctrlr);
return NULL;
}
static struct ftl_anm_ctrlr *
ftl_anm_find_ctrlr(struct ftl_anm *anm, struct spdk_nvme_ctrlr *ctrlr)
{
struct ftl_anm_ctrlr *anm_ctrlr;
LIST_FOREACH(anm_ctrlr, &anm->ctrlrs, list_entry) {
if (ctrlr == anm_ctrlr->ctrlr) {
return anm_ctrlr;
}
}
return NULL;
}
void
ftl_anm_event_complete(struct ftl_anm_event *event)
{
free(event);
}
int
ftl_anm_register_device(struct spdk_ftl_dev *dev, ftl_anm_fn fn)
{
struct ftl_anm_poller *poller;
struct ftl_anm_ctrlr *ctrlr;
int rc = 0;
pthread_mutex_lock(&g_anm.lock);
ctrlr = ftl_anm_find_ctrlr(&g_anm, dev->ctrlr);
if (!ctrlr) {
ctrlr = ftl_anm_ctrlr_alloc(dev);
if (!ctrlr) {
rc = -1;
goto out;
}
LIST_INSERT_HEAD(&g_anm.ctrlrs, ctrlr, list_entry);
}
poller = ftl_anm_alloc_poller(dev, fn);
if (!poller) {
rc = -1;
goto out;
}
pthread_mutex_lock(&ctrlr->lock);
LIST_INSERT_HEAD(&ctrlr->pollers, poller, list_entry);
pthread_mutex_unlock(&ctrlr->lock);
out:
pthread_mutex_unlock(&g_anm.lock);
return rc;
}
static void
ftl_anm_unregister_device_cb(void *ctx)
{
struct ftl_anm_init_ctx *init_ctx = ctx;
struct spdk_ftl_dev *dev = init_ctx->cb_arg;
struct ftl_anm_ctrlr *ctrlr;
struct ftl_anm_poller *poller, *temp_poller;
pthread_mutex_lock(&g_anm.lock);
ctrlr = ftl_anm_find_ctrlr(&g_anm, dev->ctrlr);
assert(ctrlr != NULL);
pthread_mutex_lock(&ctrlr->lock);
LIST_FOREACH_SAFE(poller, &ctrlr->pollers, list_entry, temp_poller) {
if (poller->dev == dev) {
LIST_REMOVE(poller, list_entry);
free(poller);
}
}
pthread_mutex_unlock(&ctrlr->lock);
/* Release the controller if there are no more pollers */
if (LIST_EMPTY(&ctrlr->pollers)) {
if (!ctrlr->processing) {
LIST_REMOVE(ctrlr, list_entry);
ftl_anm_ctrlr_free(ctrlr);
} else {
pthread_mutex_unlock(&g_anm.lock);
spdk_thread_send_msg(g_anm.thread, ftl_anm_unregister_device_cb, ctx);
return;
}
}
pthread_mutex_unlock(&g_anm.lock);
init_ctx->cb(init_ctx->cb_arg, 0);
free(init_ctx);
}
int
ftl_anm_unregister_device(struct spdk_ftl_dev *dev, spdk_ftl_fn cb)
{
struct ftl_anm_init_ctx *ctx;
ctx = malloc(sizeof(*ctx));
if (!ctx) {
return -ENOMEM;
}
ctx->cb = cb;
ctx->cb_arg = dev;
spdk_thread_send_msg(g_anm.thread, ftl_anm_unregister_device_cb, ctx);
return 0;
}
static void
ftl_anm_register_poller_cb(void *ctx)
{
struct ftl_anm_init_ctx *init_ctx = ctx;
int rc = 0;
/* TODO: adjust polling timeout */
g_anm.poller = spdk_poller_register(ftl_anm_poller_cb, &g_anm, 1000);
if (!g_anm.poller) {
SPDK_ERRLOG("Unable to register ANM poller\n");
rc = -ENOMEM;
}
init_ctx->cb(init_ctx->cb_arg, rc);
free(init_ctx);
}
int
ftl_anm_init(struct spdk_thread *thread, spdk_ftl_fn cb, void *cb_arg)
{
struct ftl_anm_init_ctx *ctx;
ctx = malloc(sizeof(*ctx));
if (!ctx) {
return -ENOMEM;
}
g_anm.thread = thread;
ctx->cb = cb;
ctx->cb_arg = cb_arg;
spdk_thread_send_msg(thread, ftl_anm_register_poller_cb, ctx);
return 0;
}
static void
ftl_anm_unregister_poller_cb(void *ctx)
{
struct ftl_anm_init_ctx *init_ctx = ctx;
spdk_poller_unregister(&g_anm.poller);
init_ctx->cb(init_ctx->cb_arg, 0);
free(init_ctx);
}
int
ftl_anm_free(spdk_ftl_fn cb, void *cb_arg)
{
struct ftl_anm_init_ctx *ctx;
ctx = malloc(sizeof(*ctx));
if (!ctx) {
return -ENOMEM;
}
ctx->cb = cb;
ctx->cb_arg = cb_arg;
spdk_thread_send_msg(g_anm.thread, ftl_anm_unregister_poller_cb, ctx);
return 0;
}

View File

@ -1,70 +0,0 @@
/*-
* BSD LICENSE
*
* Copyright (c) Intel Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FTL_ANM_H
#define FTL_ANM_H
#include "spdk/thread.h"
#include "ftl_addr.h"
struct ftl_nvme_ctrlr;
struct ftl_anm_event;
struct spdk_ftl_dev;
typedef void (*ftl_anm_fn)(struct ftl_anm_event *event);
enum ftl_anm_range {
FTL_ANM_RANGE_LBK,
FTL_ANM_RANGE_CHK,
FTL_ANM_RANGE_PU,
FTL_ANM_RANGE_MAX,
};
struct ftl_anm_event {
/* Owner device */
struct spdk_ftl_dev *dev;
/* First block address */
struct ftl_addr addr;
/* Number of logical blocks */
size_t num_lbks;
};
int ftl_anm_init(struct spdk_thread *thread, spdk_ftl_fn cb, void *cb_arg);
int ftl_anm_free(spdk_ftl_fn cb, void *cb_arg);
int ftl_anm_register_device(struct spdk_ftl_dev *dev, ftl_anm_fn fn);
int ftl_anm_unregister_device(struct spdk_ftl_dev *dev, spdk_ftl_fn cb);
void ftl_anm_event_complete(struct ftl_anm_event *event);
#endif /* FTL_ANM_H */

View File

@ -44,7 +44,6 @@
#include "ftl_core.h"
#include "ftl_band.h"
#include "ftl_io.h"
#include "ftl_anm.h"
#include "ftl_rwb.h"
#include "ftl_debug.h"
#include "ftl_reloc.h"
@ -2116,37 +2115,6 @@ spdk_ftl_flush(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
return ftl_flush_rwb(dev, cb_fn, cb_arg);
}
static void
_ftl_process_anm_event(void *ctx)
{
ftl_process_anm_event((struct ftl_anm_event *)ctx);
}
void
ftl_process_anm_event(struct ftl_anm_event *event)
{
struct spdk_ftl_dev *dev = event->dev;
struct ftl_band *band;
size_t lbkoff;
/* Drop any ANM requests until the device is initialized */
if (!dev->initialized) {
ftl_anm_event_complete(event);
return;
}
if (!ftl_check_core_thread(dev)) {
spdk_thread_send_msg(ftl_get_core_thread(dev), _ftl_process_anm_event, event);
return;
}
band = ftl_band_from_addr(dev, event->addr);
lbkoff = ftl_band_lbkoff_from_addr(band, event->addr);
ftl_reloc_add(dev->reloc, band, lbkoff, event->num_lbks, 0, false);
ftl_anm_event_complete(event);
}
bool
ftl_addr_is_written(struct ftl_band *band, struct ftl_addr addr)
{

View File

@ -43,7 +43,6 @@
#include "spdk/bdev_zone.h"
#include "ftl_core.h"
#include "ftl_anm.h"
#include "ftl_io.h"
#include "ftl_reloc.h"
#include "ftl_rwb.h"
@ -662,10 +661,6 @@ _ftl_dev_init_thread(void *ctx)
assert(0);
}
if (spdk_get_thread() == ftl_get_core_thread(dev)) {
ftl_anm_register_device(dev, ftl_process_anm_event);
}
thread->ioch = spdk_get_io_channel(dev);
}
@ -1233,40 +1228,20 @@ ftl_nv_cache_header_fini_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb
spdk_thread_send_msg(dev->fini_ctx.thread, ftl_halt_complete_cb, dev);
}
static void
_ftl_anm_unregister_cb(void *ctx)
static int
ftl_halt_poller(void *ctx)
{
struct spdk_ftl_dev *dev = ctx;
if (!dev->core_thread.poller && !dev->read_thread.poller) {
spdk_poller_unregister(&dev->fini_ctx.poller);
if (ftl_dev_has_nv_cache(dev)) {
ftl_nv_cache_write_header(&dev->nv_cache, true, ftl_nv_cache_header_fini_cb, dev);
} else {
dev->halt_complete_status = 0;
spdk_thread_send_msg(dev->fini_ctx.thread, ftl_halt_complete_cb, dev);
}
}
static void
ftl_anm_unregister_cb(void *ctx, int status)
{
struct spdk_ftl_dev *dev = ctx;
spdk_thread_send_msg(ftl_get_core_thread(dev), _ftl_anm_unregister_cb, dev);
}
static int
ftl_halt_poller(void *ctx)
{
struct spdk_ftl_dev *dev = ctx;
int rc;
if (!dev->core_thread.poller && !dev->read_thread.poller) {
rc = ftl_anm_unregister_device(dev, ftl_anm_unregister_cb);
if (spdk_unlikely(rc != 0)) {
SPDK_ERRLOG("Failed to unregister ANM device, will retry later\n");
} else {
spdk_poller_unregister(&dev->fini_ctx.poller);
}
}
return 0;
@ -1311,13 +1286,15 @@ spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_init_fn cb_fn, void *cb_arg
int
spdk_ftl_module_init(const struct ftl_module_init_opts *opts, spdk_ftl_fn cb, void *cb_arg)
{
return ftl_anm_init(opts->anm_thread, cb, cb_arg);
cb(cb_arg, 0);
return 0;
}
int
spdk_ftl_module_fini(spdk_ftl_fn cb, void *cb_arg)
{
return ftl_anm_free(cb, cb_arg);
cb(cb_arg, 0);
return 0;
}
SPDK_LOG_REGISTER_COMPONENT("ftl_init", SPDK_LOG_FTL_INIT)