From 1e904e2b75651d63bdac25b8fa8176279fcf2b77 Mon Sep 17 00:00:00 2001 From: Artur Paszkiewicz Date: Tue, 28 Jun 2022 15:58:29 +0200 Subject: [PATCH] ftl: fast startup Adding API for the bringup part of fast shutdown/startup. Adds shared memory utilization for necessary functions during initialization. Signed-off-by: Artur Paszkiewicz Signed-off-by: Kozlowski Mateusz Change-Id: Iab2da102fd0ccaa56fbdb9b3c765be5eeefff145 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13349 Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/ftl/ftl_band.c | 26 ++++++++++++++++++++++ lib/ftl/ftl_band.h | 1 + lib/ftl/ftl_core.h | 24 +++++++++++++++++++- lib/ftl/mngt/ftl_mngt_band.c | 22 ++++++++++++++++-- lib/ftl/mngt/ftl_mngt_md.c | 20 ++++++++++++++--- lib/ftl/mngt/ftl_mngt_misc.c | 4 +++- lib/ftl/utils/ftl_md.c | 9 ++++++-- test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c | 2 ++ 8 files changed, 99 insertions(+), 9 deletions(-) diff --git a/lib/ftl/ftl_band.c b/lib/ftl/ftl_band.c index 53afb12bf..350a5d918 100644 --- a/lib/ftl/ftl_band.c +++ b/lib/ftl/ftl_band.c @@ -330,6 +330,28 @@ ftl_band_alloc_p2l_map(struct ftl_band *band) return 0; } +int +ftl_band_open_p2l_map(struct ftl_band *band) +{ + struct spdk_ftl_dev *dev = band->dev; + struct ftl_p2l_map *p2l_map = &band->p2l_map; + + assert(p2l_map->ref_cnt == 0); + assert(p2l_map->band_map == NULL); + + assert(band->md->df_p2l_map != FTL_DF_OBJ_ID_INVALID); + + if (ftl_band_alloc_md_entry(band)) { + p2l_map->band_map = NULL; + return -1; + } + + p2l_map->band_map = ftl_mempool_claim_df(dev->p2l_pool, band->md->df_p2l_map); + + ftl_band_acquire_p2l_map(band); + return 0; +} + void ftl_band_release_p2l_map(struct ftl_band *band) { @@ -586,6 +608,10 @@ ftl_band_init_gc_iter(struct spdk_ftl_dev *dev) return; } + if (ftl_fast_startup(dev) || ftl_fast_recovery(dev)) { + return; + } + /* We lost GC state due to dirty shutdown, reset GC state to start over */ ftl_band_reset_gc_iter(dev); } diff --git a/lib/ftl/ftl_band.h b/lib/ftl/ftl_band.h index 54db742a6..2da210396 100644 --- a/lib/ftl/ftl_band.h +++ b/lib/ftl/ftl_band.h @@ -141,6 +141,7 @@ void ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type); void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state); void ftl_band_acquire_p2l_map(struct ftl_band *band); int ftl_band_alloc_p2l_map(struct ftl_band *band); +int ftl_band_open_p2l_map(struct ftl_band *band); void ftl_band_release_p2l_map(struct ftl_band *band); ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks); ftl_addr ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset); diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index ecaf0cca7..0a478e5b5 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -79,7 +79,7 @@ struct spdk_ftl_dev { /* P2L map memory pool */ struct ftl_mempool *p2l_pool; - /* Underlying SHM buf for LBA map mempool */ + /* Underlying SHM buf for P2L map mempool */ struct ftl_md *p2l_pool_md; /* Band md memory pool */ @@ -258,4 +258,26 @@ ftl_tail_md_num_blocks(const struct spdk_ftl_dev *dev) dev->xfer_size) * dev->xfer_size; } +/* + * shm_ready being set is a necessary part of the validity of the shm superblock + * If it's not set, then the recovery or startup must proceed from disk + * + * - If both sb and shm_sb are clean, then shm memory can be relied on for startup + * - If shm_sb wasn't set to clean, then disk startup/recovery needs to be done (which depends on the sb->clean flag) + * - sb->clean clear and sb_shm->clean is technically not possible (due to the order of these operations), but it should + * probably do a full recovery from disk to be on the safe side (which the ftl_fast_recovery will guarantee) + */ + +static inline bool +ftl_fast_startup(const struct spdk_ftl_dev *dev) +{ + return dev->sb->clean && dev->sb_shm->shm_clean && dev->sb_shm->shm_ready; +} + +static inline bool +ftl_fast_recovery(const struct spdk_ftl_dev *dev) +{ + return !dev->sb->clean && !dev->sb_shm->shm_clean && dev->sb_shm->shm_ready; +} + #endif /* FTL_CORE_H */ diff --git a/lib/ftl/mngt/ftl_mngt_band.c b/lib/ftl/mngt/ftl_mngt_band.c index 16b50dd87..1ddd4305a 100644 --- a/lib/ftl/mngt/ftl_mngt_band.c +++ b/lib/ftl/mngt/ftl_mngt_band.c @@ -16,7 +16,9 @@ ftl_band_init_md(struct ftl_band *band) struct ftl_band_md *band_md = ftl_md_get_buffer(band_info_md); band->md = &band_md[band->id]; - band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID; + if (!ftl_fast_startup(dev)) { + band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID; + } return 0; } @@ -224,6 +226,7 @@ ftl_mngt_finalize_init_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process * struct ftl_writer *writer; uint64_t i, num_open = 0, num_shut = 0; uint64_t offset; + bool fast_startup = ftl_fast_startup(dev); TAILQ_FOREACH_SAFE(band, &dev->free_bands, queue_entry, temp_band) { band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID; @@ -275,7 +278,17 @@ ftl_mngt_finalize_init_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process * writer->num_bands++; ftl_band_set_owner(band, ftl_writer_band_state_change, writer); - if (dev->sb->clean) { + if (fast_startup) { + FTL_NOTICELOG(dev, "SHM: band open P2L map df_id 0x%"PRIx64"\n", band->md->df_p2l_map); + if (ftl_band_open_p2l_map(band)) { + ftl_mngt_fail_step(mngt); + return; + } + + offset = band->md->iter.offset; + ftl_band_iter_init(band); + ftl_band_iter_set(band, offset); + } else if (dev->sb->clean) { band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID; if (ftl_band_alloc_p2l_map(band)) { ftl_mngt_fail_step(mngt); @@ -288,6 +301,11 @@ ftl_mngt_finalize_init_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process * } } + if (fast_startup) { + ftl_mempool_initialize_ext(dev->p2l_pool); + } + + /* Recalculate number of free bands */ dev->num_free = 0; TAILQ_FOREACH(band, &dev->free_bands, queue_entry) { diff --git a/lib/ftl/mngt/ftl_mngt_md.c b/lib/ftl/mngt/ftl_mngt_md.c index 9cf7e2c9d..e525fad65 100644 --- a/lib/ftl/mngt/ftl_mngt_md.c +++ b/lib/ftl/mngt/ftl_mngt_md.c @@ -252,7 +252,7 @@ ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt struct ftl_layout *layout = &dev->layout; struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_SB]; char uuid[SPDK_UUID_STRING_LEN]; - int md_create_flags = FTL_MD_CREATE_SHM | FTL_MD_CREATE_SHM_NEW; + int md_create_flags = ftl_md_create_region_flags(dev, FTL_LAYOUT_REGION_TYPE_SB); /* Must generate UUID before MD create on SHM for the SB */ if (dev->conf.mode & SPDK_FTL_MODE_CREATE) { @@ -261,14 +261,22 @@ ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt FTL_NOTICELOG(dev, "Create new FTL, UUID %s\n", uuid); } +shm_retry: /* Allocate md buf */ dev->sb_shm = NULL; dev->sb_shm_md = ftl_md_create(dev, spdk_divide_round_up(sizeof(*dev->sb_shm), FTL_BLOCK_SIZE), 0, "sb_shm", md_create_flags, NULL); if (dev->sb_shm_md == NULL) { - ftl_mngt_fail_step(mngt); - return; + /* The first attempt may fail when trying to open SHM - try to create new */ + if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { + md_create_flags |= FTL_MD_CREATE_SHM_NEW; + goto shm_retry; + } + if (dev->sb_shm_md == NULL) { + ftl_mngt_fail_step(mngt); + return; + } } dev->sb_shm = ftl_md_get_buffer(dev->sb_shm_md); @@ -284,6 +292,12 @@ ftl_mngt_superblock_init(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt region->vss_blksz, region->name, md_create_flags, region); if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_SB]) { + /* The first attempt may fail when trying to open SHM - try to create new */ + if ((md_create_flags & FTL_MD_CREATE_SHM_NEW) == 0) { + md_create_flags |= FTL_MD_CREATE_SHM_NEW; + ftl_md_destroy(dev->sb_shm_md, 0); + goto shm_retry; + } ftl_mngt_fail_step(mngt); return; } diff --git a/lib/ftl/mngt/ftl_mngt_misc.c b/lib/ftl/mngt/ftl_mngt_misc.c index b6c0870f3..d21ce961e 100644 --- a/lib/ftl/mngt/ftl_mngt_misc.c +++ b/lib/ftl/mngt/ftl_mngt_misc.c @@ -43,7 +43,9 @@ init_p2l_map_pool(struct spdk_ftl_dev *dev) return -ENOMEM; } - ftl_mempool_initialize_ext(dev->p2l_pool); + if (!ftl_fast_startup(dev)) { + ftl_mempool_initialize_ext(dev->p2l_pool); + } return 0; } diff --git a/lib/ftl/utils/ftl_md.c b/lib/ftl/utils/ftl_md.c index 5872c688f..856a42d6e 100644 --- a/lib/ftl/utils/ftl_md.c +++ b/lib/ftl/utils/ftl_md.c @@ -1121,7 +1121,9 @@ ftl_md_create_region_flags(struct spdk_ftl_dev *dev, int region_type) case FTL_LAYOUT_REGION_TYPE_BAND_MD: case FTL_LAYOUT_REGION_TYPE_NVC_MD: - flags |= FTL_MD_CREATE_SHM_NEW; + if (!ftl_fast_startup(dev)) { + flags |= FTL_MD_CREATE_SHM_NEW; + } break; default: return FTL_MD_CREATE_HEAP; @@ -1151,8 +1153,11 @@ ftl_md_destroy_region_flags(struct spdk_ftl_dev *dev, int region_type) int ftl_md_create_shm_flags(struct spdk_ftl_dev *dev) { - int flags = FTL_MD_CREATE_SHM | FTL_MD_CREATE_SHM_NEW; + int flags = FTL_MD_CREATE_SHM; + if (!ftl_fast_startup(dev) && !ftl_fast_recovery(dev)) { + flags |= FTL_MD_CREATE_SHM_NEW; + } return flags; } diff --git a/test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c b/test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c index 4f42045fb..9815a3f22 100644 --- a/test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c +++ b/test/unit/lib/ftl/ftl_band.c/ftl_band_ut.c @@ -117,6 +117,8 @@ DEFINE_STUB(spdk_bdev_queue_io_wait, int, (struct spdk_bdev *bdev, struct spdk_i DEFINE_STUB(ftl_l2p_get, ftl_addr, (struct spdk_ftl_dev *dev, uint64_t lba), 0); DEFINE_STUB_V(ftl_writer_run, (struct ftl_writer *writer)); DEFINE_STUB(ftl_writer_is_halted, bool, (struct ftl_writer *writer), true); +DEFINE_STUB(ftl_mempool_claim_df, void *, (struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id), + NULL); static void setup_band(void)