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:
parent
0e33da4974
commit
1e904e2b75
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user