diff --git a/lib/ftl/mngt/ftl_mngt_md.c b/lib/ftl/mngt/ftl_mngt_md.c index f8200882b..62d9269c6 100644 --- a/lib/ftl/mngt/ftl_mngt_md.c +++ b/lib/ftl/mngt/ftl_mngt_md.c @@ -138,6 +138,16 @@ ftl_mngt_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_pro persist(dev, mngt, FTL_LAYOUT_REGION_TYPE_NVC_MD); } +static void +ftl_mngt_fast_persist_nv_cache_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) +{ + if (ftl_nv_cache_save_state(&dev->nv_cache)) { + ftl_mngt_fail_step(mngt); + return; + } + ftl_mngt_next_step(mngt); +} + static void ftl_mngt_persist_vld_map_metadata(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) { @@ -223,6 +233,33 @@ ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) ftl_mngt_call_process(mngt, &desc_persist); } +/* + * Fast clean shutdown path - skips the persistance of most metadata regions and + * relies on their shared memory state instead. + */ +static const struct ftl_mngt_process_desc desc_fast_persist = { + .name = "Fast persist metadata", + .steps = { + { + .name = "Fast persist NV cache metadata", + .action = ftl_mngt_fast_persist_nv_cache_metadata, + }, +#ifdef SPDK_FTL_VSS_EMU + { + .name = "Persist VSS metadata", + .action = ftl_mngt_persist_vss, + }, +#endif + {} + } +}; + +void +ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) +{ + ftl_mngt_call_process(mngt, &desc_fast_persist); +} + void ftl_mngt_init_default_sb(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) { @@ -274,6 +311,17 @@ ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) dev->sb_shm->shm_ready = false; } +void +ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) +{ + struct ftl_superblock *sb = dev->sb; + + sb->clean = 1; + dev->sb_shm->shm_clean = true; + sb->header.crc = get_sb_crc(sb); + ftl_mngt_next_step(mngt); +} + /* * Initializes the superblock fields during first startup of FTL */ diff --git a/lib/ftl/mngt/ftl_mngt_shutdown.c b/lib/ftl/mngt/ftl_mngt_shutdown.c index dacbd5ac5..f41c18bd8 100644 --- a/lib/ftl/mngt/ftl_mngt_shutdown.c +++ b/lib/ftl/mngt/ftl_mngt_shutdown.c @@ -55,8 +55,59 @@ static const struct ftl_mngt_process_desc desc_shutdown = { } }; +/* + * Steps executed during fast clean shutdown (shutting down to shared memory). Utilizes + * minimum amount of metadata persistence and rolls back any setup steps executed during + * startup (closing bdevs, io channels, etc) + */ +static const struct ftl_mngt_process_desc desc_fast_shutdown = { + .name = "FTL fast shutdown", + .steps = { + { + .name = "Deinit core IO channel", + .action = ftl_mngt_deinit_io_channel + }, + { + .name = "Unregister IO device", + .action = ftl_mngt_unregister_io_device + }, + { + .name = "Stop core poller", + .action = ftl_mngt_stop_core_poller + }, + { + .name = "Fast persist metadata", + .action = ftl_mngt_fast_persist_md + }, + { + .name = "Set FTL SHM clean state", + .action = ftl_mngt_set_shm_clean + }, + { + .name = "Dump statistics", + .action = ftl_mngt_dump_stats + }, + { + .name = "Deinitialize L2P", + .action = ftl_mngt_deinit_l2p + }, + { + .name = "Rollback FTL device", + .action = ftl_mngt_rollback_device + }, + {} + } +}; + int ftl_mngt_call_dev_shutdown(struct spdk_ftl_dev *dev, ftl_mngt_completion cb, void *cb_cntx) { - return ftl_mngt_process_execute(dev, &desc_shutdown, cb, cb_cntx); + const struct ftl_mngt_process_desc *pdesc; + + if (dev->conf.fast_shutdown) { + pdesc = &desc_fast_shutdown; + } else { + pdesc = &desc_shutdown; + } + return ftl_mngt_process_execute(dev, pdesc, cb, cb_cntx); } diff --git a/lib/ftl/mngt/ftl_mngt_steps.h b/lib/ftl/mngt/ftl_mngt_steps.h index c0825c4b9..074ed5133 100644 --- a/lib/ftl/mngt/ftl_mngt_steps.h +++ b/lib/ftl/mngt/ftl_mngt_steps.h @@ -84,6 +84,8 @@ void ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) void ftl_mngt_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); +void ftl_mngt_fast_persist_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); + void ftl_mngt_rollback_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); void ftl_mngt_dump_stats(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); @@ -94,6 +96,8 @@ void ftl_mngt_set_dirty(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) void ftl_mngt_set_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); +void ftl_mngt_set_shm_clean(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); + void ftl_mngt_init_vld_map(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); void ftl_mngt_deinit_vld_map(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);