FTL: Add band state change functions

Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Change-Id: I6a985f0b54a05fbebb8d65343cffaed7e47ed60d
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13332
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:
Kozlowski Mateusz 2022-06-10 10:17:24 +02:00 committed by Ben Walker
parent 7c9d3ea595
commit 5af491a2ee
2 changed files with 134 additions and 0 deletions

View File

@ -145,6 +145,9 @@ int ftl_band_filled(struct ftl_band *band, size_t offset);
int ftl_band_write_prep(struct ftl_band *band);
size_t ftl_p2l_map_pool_elem_size(struct spdk_ftl_dev *dev);
ftl_addr ftl_band_p2l_map_addr(struct ftl_band *band);
void ftl_band_open(struct ftl_band *band, enum ftl_band_type type);
void ftl_band_close(struct ftl_band *band);
void ftl_band_free(struct ftl_band *band);
void ftl_band_rq_write(struct ftl_band *band, struct ftl_rq *rq);
void ftl_band_rq_read(struct ftl_band *band, struct ftl_rq *rq);
void ftl_band_basic_rq_write(struct ftl_band *band, struct ftl_basic_rq *brq);

View File

@ -251,6 +251,137 @@ ftl_band_basic_rq_read(struct ftl_band *band, struct ftl_basic_rq *brq)
dev->io_activity_total += brq->num_blocks;
}
static void
band_open_cb(int status, void *cb_arg)
{
struct ftl_band *band = cb_arg;
if (spdk_unlikely(status)) {
ftl_md_persist_entry_retry(&band->md_persist_entry_ctx);
return;
}
ftl_band_set_state(band, FTL_BAND_STATE_OPEN);
}
void
ftl_band_open(struct ftl_band *band, enum ftl_band_type type)
{
struct spdk_ftl_dev *dev = band->dev;
struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_BAND_MD];
struct ftl_layout_region *region = &dev->layout.region[FTL_LAYOUT_REGION_TYPE_BAND_MD];
struct ftl_p2l_map *p2l_map = &band->p2l_map;
ftl_band_set_type(band, type);
ftl_band_set_state(band, FTL_BAND_STATE_OPENING);
memcpy(p2l_map->band_dma_md, band->md, region->entry_size * FTL_BLOCK_SIZE);
p2l_map->band_dma_md->state = FTL_BAND_STATE_OPEN;
p2l_map->band_dma_md->p2l_map_checksum = 0;
if (spdk_unlikely(0 != band->p2l_map.num_valid)) {
/*
* This is inconsistent state, a band with valid block,
* it could be moved on the free list
*/
assert(false && 0 == band->p2l_map.num_valid);
ftl_abort();
}
ftl_md_persist_entry(md, band->id, p2l_map->band_dma_md, NULL,
band_open_cb, band, &band->md_persist_entry_ctx);
}
static void
band_close_cb(int status, void *cb_arg)
{
struct ftl_band *band = cb_arg;
if (spdk_unlikely(status)) {
ftl_md_persist_entry_retry(&band->md_persist_entry_ctx);
return;
}
band->md->p2l_map_checksum = band->p2l_map.band_dma_md->p2l_map_checksum;
ftl_band_set_state(band, FTL_BAND_STATE_CLOSED);
}
static void
band_map_write_cb(struct ftl_basic_rq *brq)
{
struct ftl_band *band = brq->io.band;
struct ftl_p2l_map *p2l_map = &band->p2l_map;
struct spdk_ftl_dev *dev = band->dev;
struct ftl_layout_region *region = &dev->layout.region[FTL_LAYOUT_REGION_TYPE_BAND_MD];
struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_BAND_MD];
uint32_t band_map_crc;
if (spdk_likely(brq->success)) {
band_map_crc = spdk_crc32c_update(p2l_map->band_map,
ftl_tail_md_num_blocks(dev) * FTL_BLOCK_SIZE, 0);
memcpy(p2l_map->band_dma_md, band->md, region->entry_size * FTL_BLOCK_SIZE);
p2l_map->band_dma_md->state = FTL_BAND_STATE_CLOSED;
p2l_map->band_dma_md->p2l_map_checksum = band_map_crc;
ftl_md_persist_entry(md, band->id, p2l_map->band_dma_md, NULL,
band_close_cb, band, &band->md_persist_entry_ctx);
} else {
/* Try to retry in case of failure */
ftl_band_brq_bdev_write(brq);
band->queue_depth++;
}
}
void
ftl_band_close(struct ftl_band *band)
{
struct spdk_ftl_dev *dev = band->dev;
void *metadata = band->p2l_map.band_map;
uint64_t num_blocks = ftl_tail_md_num_blocks(dev);
/* Write LBA map first, after completion, set the state to close on nvcache, then internally */
ftl_band_set_state(band, FTL_BAND_STATE_CLOSING);
ftl_basic_rq_init(dev, &band->metadata_rq, metadata, num_blocks);
ftl_basic_rq_set_owner(&band->metadata_rq, band_map_write_cb, band);
ftl_band_basic_rq_write(band, &band->metadata_rq);
}
static void
band_free_cb(int status, void *ctx)
{
struct ftl_band *band = (struct ftl_band *)ctx;
if (spdk_unlikely(status)) {
ftl_md_persist_entry_retry(&band->md_persist_entry_ctx);
return;
}
ftl_band_release_p2l_map(band);
FTL_DEBUGLOG(band->dev, "Band is going to free state. Band id: %u\n", band->id);
ftl_band_set_state(band, FTL_BAND_STATE_FREE);
assert(0 == band->p2l_map.ref_cnt);
}
void
ftl_band_free(struct ftl_band *band)
{
struct spdk_ftl_dev *dev = band->dev;
struct ftl_p2l_map *p2l_map = &band->p2l_map;
struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_BAND_MD];
struct ftl_layout_region *region = &dev->layout.region[FTL_LAYOUT_REGION_TYPE_BAND_MD];
memcpy(p2l_map->band_dma_md, band->md, region->entry_size * FTL_BLOCK_SIZE);
p2l_map->band_dma_md->state = FTL_BAND_STATE_FREE;
p2l_map->band_dma_md->p2l_map_checksum = 0;
ftl_md_persist_entry(md, band->id, p2l_map->band_dma_md, NULL,
band_free_cb, band, &band->md_persist_entry_ctx);
/* TODO: The whole band erase code should probably be done here instead */
}
static void
read_tail_md_cb(struct ftl_basic_rq *brq)
{