diff --git a/lib/ftl/mngt/ftl_mngt_misc.c b/lib/ftl/mngt/ftl_mngt_misc.c index 4b80c8db3..1aa423ef4 100644 --- a/lib/ftl/mngt/ftl_mngt_misc.c +++ b/lib/ftl/mngt/ftl_mngt_misc.c @@ -18,3 +18,45 @@ ftl_mngt_check_conf(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) ftl_mngt_fail_step(mngt); } } + +static void +user_clear_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) +{ + struct ftl_mngt_process *mngt = md->owner.cb_ctx; + + if (status) { + FTL_ERRLOG(ftl_mngt_get_dev(mngt), "FTL NV Cache: ERROR of clearing user cache data\n"); + ftl_mngt_fail_step(mngt); + } else { + ftl_mngt_next_step(mngt); + } +} + +void +ftl_mngt_scrub_nv_cache(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) +{ + struct ftl_layout_region *region = &dev->layout.region[FTL_LAYOUT_REGION_TYPE_DATA_NVC]; + struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_DATA_NVC]; + union ftl_md_vss vss; + + FTL_NOTICELOG(dev, "First startup needs to scrub nv cache data region, this may take some time.\n"); + FTL_NOTICELOG(dev, "Scrubbing %lluGiB\n", region->current.blocks * FTL_BLOCK_SIZE / GiB); + + /* Need to scrub user data, so in case of dirty shutdown the recovery won't + * pull in data during open chunks recovery from any previous instance + */ + md->cb = user_clear_cb; + md->owner.cb_ctx = mngt; + + vss.version.md_version = region->current.version; + vss.nv_cache.lba = FTL_ADDR_INVALID; + ftl_md_clear(md, 0, &vss); +} + +void +ftl_mngt_finalize_startup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) +{ + dev->initialized = 1; + + ftl_mngt_next_step(mngt); +} diff --git a/lib/ftl/mngt/ftl_mngt_shutdown.c b/lib/ftl/mngt/ftl_mngt_shutdown.c index 7f4f014a4..917ac0ed8 100644 --- a/lib/ftl/mngt/ftl_mngt_shutdown.c +++ b/lib/ftl/mngt/ftl_mngt_shutdown.c @@ -7,6 +7,10 @@ #include "ftl_mngt.h" #include "ftl_mngt_steps.h" +/* + * Steps executed during clean shutdown - includes persisting metadata and rolling + * back any setup steps executed during startup (closing bdevs, io channels, etc) + */ static const struct ftl_mngt_process_desc desc_shutdown = { .name = "FTL shutdown", .error_handler = ftl_mngt_rollback_device, diff --git a/lib/ftl/mngt/ftl_mngt_startup.c b/lib/ftl/mngt/ftl_mngt_startup.c index 1bf19e699..2f36f3385 100644 --- a/lib/ftl/mngt/ftl_mngt_startup.c +++ b/lib/ftl/mngt/ftl_mngt_startup.c @@ -8,7 +8,23 @@ #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 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_fail_step(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 = { @@ -35,6 +51,30 @@ static const struct ftl_mngt_process_desc desc_startup = { .action = ftl_mngt_init_md, .cleanup = ftl_mngt_deinit_md }, + { + .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 = "Scrub NV cache", + .action = ftl_mngt_scrub_nv_cache, + }, + { + .name = "Finalize initialization", + .action = ftl_mngt_finalize_startup, + }, {} } }; diff --git a/lib/ftl/mngt/ftl_mngt_steps.h b/lib/ftl/mngt/ftl_mngt_steps.h index b198eecc0..a3cc98d64 100644 --- a/lib/ftl/mngt/ftl_mngt_steps.h +++ b/lib/ftl/mngt/ftl_mngt_steps.h @@ -18,6 +18,10 @@ void ftl_mngt_open_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process void ftl_mngt_close_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); +void ftl_mngt_scrub_nv_cache(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); + +void ftl_mngt_finalize_startup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); + void ftl_mngt_init_layout(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); void ftl_mngt_init_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);