diff --git a/lib/ftl/ftl_nv_cache.c b/lib/ftl/ftl_nv_cache.c index 0e88c6ce6..bf6f2b0ad 100644 --- a/lib/ftl/ftl_nv_cache.c +++ b/lib/ftl/ftl_nv_cache.c @@ -1660,6 +1660,68 @@ ftl_chunk_close(struct ftl_nv_cache_chunk *chunk) ftl_chunk_basic_rq_write(chunk, brq); } +static void +restore_chunk_state_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) +{ + struct ftl_mngt_process *mngt = md->owner.cb_ctx; + struct ftl_nv_cache *nvc = &dev->nv_cache; + struct ftl_nv_cache_chunk *chunk; + uint64_t i; + + if (status) { + /* Restore error, end step */ + ftl_mngt_fail_step(mngt); + return; + } + + for (i = 0; i < nvc->chunk_count; i++) { + chunk = &nvc->chunks[i]; + + switch (chunk->md->state) { + case FTL_CHUNK_STATE_FREE: + break; + case FTL_CHUNK_STATE_OPEN: + TAILQ_REMOVE(&nvc->chunk_free_list, chunk, entry); + nvc->chunk_free_count--; + + TAILQ_INSERT_TAIL(&nvc->chunk_open_list, chunk, entry); + nvc->chunk_open_count++; + + /* Chunk is not empty, mark it to be recovered */ + chunk->recovery = true; + break; + case FTL_CHUNK_STATE_CLOSED: + TAILQ_REMOVE(&nvc->chunk_free_list, chunk, entry); + nvc->chunk_free_count--; + + TAILQ_INSERT_TAIL(&nvc->chunk_full_list, chunk, entry); + nvc->chunk_full_count++; + + /* Chunk is not empty, mark it to be recovered */ + chunk->recovery = true; + break; + default: + status = -EINVAL; + } + } + + if (status) { + ftl_mngt_fail_step(mngt); + } else { + ftl_mngt_next_step(mngt); + } +} + +void +ftl_mngt_nv_cache_restore_chunk_state(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) +{ + struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_NVC_MD]; + + md->owner.cb_ctx = mngt; + md->cb = restore_chunk_state_cb; + ftl_md_restore(md); +} + int ftl_nv_cache_chunks_busy(struct ftl_nv_cache *nv_cache) { diff --git a/lib/ftl/ftl_nv_cache.h b/lib/ftl/ftl_nv_cache.h index cd99cecc0..06567e652 100644 --- a/lib/ftl/ftl_nv_cache.h +++ b/lib/ftl/ftl_nv_cache.h @@ -215,6 +215,8 @@ uint64_t chunk_tail_md_offset(struct ftl_nv_cache *nv_cache); void ftl_nv_cache_get_max_seq_id(struct ftl_nv_cache *nv_cache, uint64_t *open_seq_id, uint64_t *close_seq_id); +void ftl_mngt_nv_cache_restore_chunk_state(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt); + typedef int (*ftl_chunk_md_cb)(struct ftl_nv_cache_chunk *chunk, void *cntx); struct ftl_nv_cache_chunk *ftl_nv_cache_get_chunk_from_addr(struct spdk_ftl_dev *dev, diff --git a/lib/ftl/mngt/ftl_mngt_recovery.c b/lib/ftl/mngt/ftl_mngt_recovery.c index 2435d69c4..49e3ef0fc 100644 --- a/lib/ftl/mngt/ftl_mngt_recovery.c +++ b/lib/ftl/mngt/ftl_mngt_recovery.c @@ -712,6 +712,10 @@ static const struct ftl_mngt_process_desc g_desc_recovery = { .name = "Recover open bands P2L", .action = ftl_mngt_recovery_open_bands_p2l }, + { + .name = "Recover chunk state", + .action = ftl_mngt_nv_cache_restore_chunk_state + }, { .name = "Recover max seq ID", .action = ftl_mngt_recover_seq_id