Spdk/lib/ftl/mngt/ftl_mngt_startup.c
paul luse a6dbe3721e update Intel copyright notices
per Intel policy to include file commit date using git cmd
below.  The policy does not apply to non-Intel (C) notices.

git log --follow -C90% --format=%ad --date default <file> | tail -1

and then pull just the 4 digit year from the result.

Intel copyrights were not added to files where Intel either had
no contribution ot the contribution lacked substance (ie license
header updates, formatting changes, etc).  Contribution date used
"--follow -C95%" to get the most accurate date.

Note that several files in this patch didn't end the license/(c)
block with a blank comment line so these were added as the vast
majority of files do have this last blank line.  Simply there for
consistency.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: Id5b7ce4f658fe87132f14139ead58d6e285c04d4
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15192
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Mellanox Build Bot
2022-11-10 08:28:53 +00:00

392 lines
8.4 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2022 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_first_start;
static const struct ftl_mngt_process_desc desc_restore;
static const struct ftl_mngt_process_desc desc_clean_start;
static void
ftl_mngt_select_startup_mode(struct spdk_ftl_dev *dev,
struct ftl_mngt_process *mngt)
{
if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
ftl_mngt_call_process(mngt, &desc_first_start);
} else {
ftl_mngt_call_process(mngt, &desc_restore);
}
}
static void
ftl_mngt_select_restore_mode(struct spdk_ftl_dev *dev,
struct ftl_mngt_process *mngt)
{
if (dev->sb->clean) {
ftl_mngt_call_process(mngt, &desc_clean_start);
} else {
ftl_mngt_recover(dev, mngt);
}
}
/*
* Common startup steps required by FTL in all cases (creation, load, dirty shutdown recovery).
* Includes actions like opening the devices, calculating the expected size and version of metadata, etc.
*/
static const struct ftl_mngt_process_desc desc_startup = {
.name = "FTL startup",
.steps = {
{
.name = "Check configuration",
.action = ftl_mngt_check_conf,
},
{
.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
},
#ifdef SPDK_FTL_VSS_EMU
{
.name = "Initialize VSS emu",
.action = ftl_mngt_md_init_vss_emu,
.cleanup = ftl_mngt_md_deinit_vss_emu
},
#endif
{
.name = "Initialize superblock",
.action = ftl_mngt_superblock_init,
.cleanup = ftl_mngt_superblock_deinit
},
{
.name = "Initialize memory pools",
.action = ftl_mngt_init_mem_pools,
.cleanup = ftl_mngt_deinit_mem_pools
},
{
.name = "Initialize bands",
.action = ftl_mngt_init_bands,
.cleanup = ftl_mngt_deinit_bands
},
{
.name = "Register IO device",
.action = ftl_mngt_register_io_device,
.cleanup = ftl_mngt_unregister_io_device
},
{
.name = "Initialize core IO channel",
.action = ftl_mngt_init_io_channel,
.cleanup = ftl_mngt_deinit_io_channel
},
{
.name = "Decorate bands",
.action = ftl_mngt_decorate_bands
},
{
.name = "Initialize layout",
.action = ftl_mngt_init_layout
},
{
.name = "Verify layout",
.action = ftl_mngt_layout_verify,
},
{
.name = "Initialize metadata",
.action = ftl_mngt_init_md,
.cleanup = ftl_mngt_deinit_md
},
{
.name = "Initialize band addresses",
.action = ftl_mngt_initialize_band_address
},
{
.name = "Initialize NV cache",
.action = ftl_mngt_init_nv_cache,
.cleanup = ftl_mngt_deinit_nv_cache
},
{
.name = "Upgrade layout",
.action = ftl_mngt_layout_upgrade,
},
{
.name = "Initialize valid map",
.action = ftl_mngt_init_vld_map,
.cleanup = ftl_mngt_deinit_vld_map
},
{
.name = "Initialize trim map",
.action = ftl_mngt_init_unmap_map,
.cleanup = ftl_mngt_deinit_unmap_map
},
{
.name = "Initialize bands metadata",
.action = ftl_mngt_init_bands_md,
.cleanup = ftl_mngt_deinit_bands_md
},
{
.name = "Initialize reloc",
.action = ftl_mngt_init_reloc,
.cleanup = ftl_mngt_deinit_reloc
},
{
.name = "Select startup mode",
.action = ftl_mngt_select_startup_mode
},
{}
}
};
/*
* Steps executed when creating FTL for the first time - most important being scrubbing
* old data/metadata (so it's not leaked during dirty shutdown recovery) and laying out
* regions for the new metadata (initializing band states, etc).
*/
static const struct ftl_mngt_process_desc desc_first_start = {
.name = "FTL first start",
.steps = {
{
.name = "Initialize L2P",
.action = ftl_mngt_init_l2p,
.cleanup = ftl_mngt_deinit_l2p
},
{
.name = "Clear L2P",
.action = ftl_mngt_clear_l2p,
.cleanup = ftl_mngt_clear_l2p
},
{
.name = "Scrub NV cache",
.action = ftl_mngt_scrub_nv_cache,
},
{
.name = "Finalize band initialization",
.action = ftl_mngt_finalize_init_bands,
},
{
.name = "Save initial band info metadata",
.action = ftl_mngt_persist_band_info_metadata,
},
{
.name = "Save initial chunk info metadata",
.action = ftl_mngt_persist_nv_cache_metadata,
},
{
.name = "Initialize P2L checkpointing",
.action = ftl_mngt_p2l_init_ckpt,
.cleanup = ftl_mngt_p2l_deinit_ckpt
},
{
.name = "Wipe P2L region",
.action = ftl_mngt_p2l_wipe,
},
{
.name = "Clear trim map",
.action = ftl_mngt_unmap_clear,
},
{
.name = "Free P2L region bufs",
.action = ftl_mngt_p2l_free_bufs,
},
{
.name = "Set FTL dirty state",
.action = ftl_mngt_set_dirty,
},
{
.name = "Start core poller",
.action = ftl_mngt_start_core_poller,
.cleanup = ftl_mngt_stop_core_poller
},
{
.name = "Finalize initialization",
.action = ftl_mngt_finalize_startup,
},
{}
}
};
/*
* Step utilized on loading of an FTL instance - decides on dirty/clean shutdown path.
*/
static const struct ftl_mngt_process_desc desc_restore = {
.name = "FTL restore",
.steps = {
{
.name = "Select recovery mode",
.action = ftl_mngt_select_restore_mode,
},
{}
}
};
/*
* Loading of FTL after clean shutdown.
*/
static const struct ftl_mngt_process_desc desc_clean_start = {
.name = "Clean startup",
.steps = {
{
.name = "Restore metadata",
.action = ftl_mngt_restore_md
},
{
.name = "Initialize P2L checkpointing",
.action = ftl_mngt_p2l_init_ckpt,
.cleanup = ftl_mngt_p2l_deinit_ckpt
},
{
.name = "Restore P2L checkpoints",
.action = ftl_mngt_p2l_restore_ckpt
},
{
.name = "Initialize L2P",
.action = ftl_mngt_init_l2p,
.cleanup = ftl_mngt_deinit_l2p
},
{
.name = "Restore L2P",
.action = ftl_mngt_restore_l2p,
},
{
.name = "Finalize band initialization",
.action = ftl_mngt_finalize_init_bands,
},
{
.name = "Free P2L region bufs",
.action = ftl_mngt_p2l_free_bufs,
},
{
.name = "Start core poller",
.action = ftl_mngt_start_core_poller,
.cleanup = ftl_mngt_stop_core_poller
},
{
.name = "Self test on startup",
.action = ftl_mngt_self_test,
},
{
.name = "Set FTL dirty state",
.action = ftl_mngt_set_dirty,
},
{
.name = "Finalize initialization",
.action = ftl_mngt_finalize_startup,
},
{}
}
};
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);
}
struct ftl_unmap_ctx {
uint64_t lba;
uint64_t num_blocks;
spdk_ftl_fn cb_fn;
void *cb_arg;
struct spdk_thread *thread;
int status;
};
static void
ftl_mngt_process_unmap_cb(void *ctx, int status)
{
struct ftl_mngt_process *mngt = ctx;
if (status) {
ftl_mngt_fail_step(ctx);
} else {
ftl_mngt_next_step(mngt);
}
}
static void
ftl_mngt_process_unmap(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
struct ftl_io *io = ftl_mngt_get_process_ctx(mngt);
struct ftl_unmap_ctx *ctx = ftl_mngt_get_caller_ctx(mngt);
int rc;
if (!dev->ioch) {
ftl_mngt_fail_step(mngt);
return;
}
rc = spdk_ftl_unmap(dev, io, dev->ioch, ctx->lba, ctx->num_blocks, ftl_mngt_process_unmap_cb, mngt);
if (rc == -EAGAIN) {
ftl_mngt_continue_step(mngt);
}
}
/*
* RPC unmap path.
*/
static const struct ftl_mngt_process_desc g_desc_unmap = {
.name = "FTL unmap",
.ctx_size = sizeof(struct ftl_io),
.steps = {
{
.name = "Process unmap",
.action = ftl_mngt_process_unmap,
},
{}
}
};
static void
unmap_user_cb(void *_ctx)
{
struct ftl_unmap_ctx *ctx = _ctx;
ctx->cb_fn(ctx->cb_arg, ctx->status);
free(ctx);
}
static void
ftl_mngt_unmap_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
{
struct ftl_unmap_ctx *ctx = _ctx;
ctx->status = status;
if (spdk_thread_send_msg(ctx->thread, unmap_user_cb, ctx)) {
ftl_abort();
}
}
int
ftl_mngt_unmap(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks, spdk_ftl_fn cb,
void *cb_cntx)
{
struct ftl_unmap_ctx *ctx;
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
return -EAGAIN;
}
ctx->lba = lba;
ctx->num_blocks = num_blocks;
ctx->cb_fn = cb;
ctx->cb_arg = cb_cntx;
ctx->thread = spdk_get_thread();
return ftl_mngt_process_execute(dev, &g_desc_unmap, ftl_mngt_unmap_cb, ctx);
}
void
ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
ftl_mngt_call_process_rollback(mngt, &desc_startup);
}