Commit 1e904e2b authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Jim Harris
Browse files

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: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: default avatarKozlowski 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: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 0e33da49
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -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);
}
+1 −0
Original line number Diff line number Diff line
@@ -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);
+23 −1
Original line number Diff line number Diff line
@@ -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 */
+20 −2
Original line number Diff line number Diff line
@@ -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];
	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) {
+17 −3
Original line number Diff line number Diff line
@@ -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,15 +261,23 @@ 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) {
		/* 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;
	}
Loading