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 <artur.paszkiewicz@intel.com>
Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: Iab2da102fd0ccaa56fbdb9b3c765be5eeefff145
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13349
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Artur Paszkiewicz 2022-06-28 15:58:29 +02:00 committed by Jim Harris
parent 0e33da4974
commit 1e904e2b75
8 changed files with 99 additions and 9 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)