FTL: Open band recovery
Adds recovery of open bands from P2L metadata region. Recovers the commited P2Ls and write pointers for them. Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com> Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Change-Id: I943c53f55e653dd075035cef7ddba448c990be87 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13370 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
0e0f3d9af2
commit
8786f3b465
@ -34,6 +34,7 @@ struct ftl_mngt_recovery_ctx {
|
||||
uint64_t lba_last;
|
||||
uint32_t i;
|
||||
} iter;
|
||||
uint64_t p2l_ckpt_seq_id[FTL_LAYOUT_REGION_TYPE_P2L_COUNT];
|
||||
};
|
||||
|
||||
static const struct ftl_mngt_process_desc g_desc_recovery;
|
||||
@ -209,6 +210,57 @@ ftl_mngt_recovery_restore_band_state(struct spdk_ftl_dev *dev, struct ftl_mngt_p
|
||||
ftl_md_restore(md);
|
||||
}
|
||||
|
||||
static void
|
||||
p2l_ckpt_preprocess(struct spdk_ftl_dev *dev, struct ftl_mngt_recovery_ctx *pctx)
|
||||
{
|
||||
uint64_t seq_id;
|
||||
int md_region, ckpt_id;
|
||||
|
||||
for (md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
|
||||
md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; md_region++) {
|
||||
ckpt_id = md_region - FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
|
||||
seq_id = ftl_mngt_p2l_ckpt_get_seq_id(dev, md_region);
|
||||
pctx->p2l_ckpt_seq_id[ckpt_id] = seq_id;
|
||||
FTL_NOTICELOG(dev, "P2L ckpt_id=%d found seq_id=%"PRIu64"\n", ckpt_id, seq_id);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
p2l_ckpt_restore_p2l(struct ftl_mngt_recovery_ctx *pctx, struct ftl_band *band)
|
||||
{
|
||||
uint64_t seq_id;
|
||||
int md_region, ckpt_id;
|
||||
|
||||
memset(band->p2l_map.band_map, -1,
|
||||
FTL_BLOCK_SIZE * ftl_p2l_map_num_blocks(band->dev));
|
||||
|
||||
for (md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
|
||||
md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; md_region++) {
|
||||
ckpt_id = md_region - FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
|
||||
seq_id = pctx->p2l_ckpt_seq_id[ckpt_id];
|
||||
if (seq_id == band->md->seq) {
|
||||
FTL_NOTICELOG(band->dev, "Restore band P2L band_id=%u ckpt_id=%d seq_id=%"
|
||||
PRIu64"\n", band->id, ckpt_id, seq_id);
|
||||
return ftl_mngt_p2l_ckpt_restore(band, md_region, seq_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Band opened but no valid blocks within it, set write pointer to 0 */
|
||||
ftl_band_iter_init(band);
|
||||
FTL_NOTICELOG(band->dev, "Restore band P2L band_id=%u, band_seq_id=%"PRIu64" does not"
|
||||
" match any P2L checkpoint\n", band->id, band->md->seq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ftl_mngt_recovery_pre_process_p2l(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
|
||||
{
|
||||
struct ftl_mngt_recovery_ctx *pctx = ftl_mngt_get_process_ctx(mngt);
|
||||
|
||||
p2l_ckpt_preprocess(dev, pctx);
|
||||
ftl_mngt_next_step(mngt);
|
||||
}
|
||||
|
||||
static void
|
||||
ftl_mngt_recover_seq_id(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
|
||||
{
|
||||
@ -216,6 +268,71 @@ ftl_mngt_recover_seq_id(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
|
||||
ftl_mngt_next_step(mngt);
|
||||
}
|
||||
|
||||
static void
|
||||
ftl_mngt_recovery_open_bands_p2l(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
|
||||
{
|
||||
struct ftl_mngt_recovery_ctx *pctx = ftl_mngt_get_process_ctx(mngt);
|
||||
struct ftl_band *band;
|
||||
|
||||
if (TAILQ_EMPTY(&pctx->open_bands)) {
|
||||
FTL_NOTICELOG(dev, "No more open bands to recover from P2L\n");
|
||||
if (pctx->status) {
|
||||
ftl_mngt_fail_step(mngt);
|
||||
} else {
|
||||
ftl_mngt_next_step(mngt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ftl_mngt_get_step_ctx(mngt)) {
|
||||
ftl_mngt_alloc_step_ctx(mngt, sizeof(bool));
|
||||
|
||||
/* Step first time called, initialize */
|
||||
TAILQ_FOREACH(band, &pctx->open_bands, queue_entry) {
|
||||
band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID;
|
||||
if (ftl_band_alloc_p2l_map(band)) {
|
||||
FTL_ERRLOG(dev, "Open band recovery ERROR, Cannot allocate LBA map\n");
|
||||
ftl_mngt_fail_step(mngt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p2l_ckpt_restore_p2l(pctx, band)) {
|
||||
FTL_ERRLOG(dev, "Open band recovery ERROR, Cannot restore P2L\n");
|
||||
ftl_mngt_fail_step(mngt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!band->p2l_map.p2l_ckpt) {
|
||||
band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire_region_type(dev, band->md->p2l_md_region);
|
||||
if (!band->p2l_map.p2l_ckpt) {
|
||||
FTL_ERRLOG(dev, "Open band recovery ERROR, Cannot acquire P2L\n");
|
||||
ftl_mngt_fail_step(mngt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
band = TAILQ_FIRST(&pctx->open_bands);
|
||||
|
||||
if (ftl_band_filled(band, band->md->iter.offset)) {
|
||||
band->md->state = FTL_BAND_STATE_FULL;
|
||||
}
|
||||
|
||||
/* In a next step (finalize band initialization) this band will
|
||||
* be assigned to the writer. So temporary we move this band
|
||||
* to the closed list, and in the next step it will be moved to
|
||||
* the writer from such list.
|
||||
*/
|
||||
TAILQ_REMOVE(&pctx->open_bands, band, queue_entry);
|
||||
TAILQ_INSERT_TAIL(&dev->shut_bands, band, queue_entry);
|
||||
|
||||
FTL_NOTICELOG(dev, "Open band recovered, id = %u, seq id %"PRIu64", write offset %"PRIu64"\n",
|
||||
band->id, band->md->seq, band->md->iter.offset);
|
||||
|
||||
ftl_mngt_continue_step(mngt);
|
||||
}
|
||||
|
||||
static void
|
||||
ftl_mngt_restore_valid_counters(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
|
||||
{
|
||||
@ -250,6 +367,23 @@ static const struct ftl_mngt_process_desc g_desc_recovery = {
|
||||
.name = "Recover band state",
|
||||
.action = ftl_mngt_recovery_restore_band_state,
|
||||
},
|
||||
{
|
||||
.name = "Initialize P2L checkpointing",
|
||||
.action = ftl_mngt_p2l_init_ckpt,
|
||||
.cleanup = ftl_mngt_p2l_deinit_ckpt
|
||||
},
|
||||
{
|
||||
.name = "Restore P2L checkpoints",
|
||||
.action = ftl_mngt_p2l_restore_ckpt
|
||||
},
|
||||
{
|
||||
.name = "Preprocess P2L checkpoints",
|
||||
.action = ftl_mngt_recovery_pre_process_p2l
|
||||
},
|
||||
{
|
||||
.name = "Recover open bands P2L",
|
||||
.action = ftl_mngt_recovery_open_bands_p2l
|
||||
},
|
||||
{
|
||||
.name = "Recover max seq ID",
|
||||
.action = ftl_mngt_recover_seq_id
|
||||
@ -271,6 +405,10 @@ static const struct ftl_mngt_process_desc g_desc_recovery = {
|
||||
.name = "Finalize band initialization",
|
||||
.action = ftl_mngt_finalize_init_bands,
|
||||
},
|
||||
{
|
||||
.name = "Free P2L region bufs",
|
||||
.action = ftl_mngt_p2l_free_bufs,
|
||||
},
|
||||
{
|
||||
.name = "Start core poller",
|
||||
.action = ftl_mngt_start_core_poller,
|
||||
|
Loading…
Reference in New Issue
Block a user