From 101a03992328153070c5b44e137aee39926a22f7 Mon Sep 17 00:00:00 2001 From: Kozlowski Mateusz Date: Fri, 29 Jul 2022 13:16:38 +0200 Subject: [PATCH] ftl: p2l map on shm Stores P2L map of open bands in shared memory, allowing for faster recovery times from application crash. Signed-off-by: Artur Paszkiewicz Signed-off-by: Kozlowski Mateusz Change-Id: I519441af05e4d0f57768835bf01c800556873c58 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13347 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/ftl/ftl_band.c | 4 ++++ lib/ftl/ftl_band.h | 5 +++++ lib/ftl/ftl_core.h | 3 +++ lib/ftl/mngt/ftl_mngt_band.c | 8 ++++++++ lib/ftl/mngt/ftl_mngt_misc.c | 25 ++++++++++++++++++++----- test/unit/lib/ftl/common/utils.c | 7 +++++++ 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/lib/ftl/ftl_band.c b/lib/ftl/ftl_band.c index 29ba61be1..53afb12bf 100644 --- a/lib/ftl/ftl_band.c +++ b/lib/ftl/ftl_band.c @@ -40,6 +40,7 @@ ftl_band_free_p2l_map(struct ftl_band *band) assert(p2l_map->ref_cnt == 0); assert(p2l_map->band_map != NULL); + band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID; ftl_mempool_put(dev->p2l_pool, p2l_map->band_map); p2l_map->band_map = NULL; } @@ -309,6 +310,7 @@ ftl_band_alloc_p2l_map(struct ftl_band *band) assert(p2l_map->ref_cnt == 0); assert(p2l_map->band_map == NULL); + assert(band->md->df_p2l_map == FTL_DF_OBJ_ID_INVALID); p2l_map->band_map = ftl_mempool_get(dev->p2l_pool); if (!p2l_map->band_map) { return -1; @@ -319,6 +321,8 @@ ftl_band_alloc_p2l_map(struct ftl_band *band) return -1; } + band->md->df_p2l_map = ftl_mempool_get_df_obj_id(dev->p2l_pool, p2l_map->band_map); + /* Set the P2L to FTL_LBA_INVALID */ memset(p2l_map->band_map, -1, FTL_BLOCK_SIZE * ftl_p2l_map_num_blocks(band->dev)); diff --git a/lib/ftl/ftl_band.h b/lib/ftl/ftl_band.h index 4bbfcc416..54db742a6 100644 --- a/lib/ftl/ftl_band.h +++ b/lib/ftl/ftl_band.h @@ -15,6 +15,8 @@ #include "ftl_internal.h" #include "ftl_core.h" +#include "utils/ftl_df.h" + #define FTL_MAX_OPEN_BANDS 4 #define FTL_BAND_VERSION_0 0 @@ -61,6 +63,9 @@ struct ftl_band_md { /* Number of times band was fully written (ie. number of free -> closed state cycles) */ uint64_t wr_cnt; + /* Durable format object id for P2L map, allocated on shared memory */ + ftl_df_obj_id df_p2l_map; + /* CRC32 checksum of the associated P2L map when band is in closed state */ uint32_t p2l_map_checksum; } __attribute__((aligned(FTL_BLOCK_SIZE))); diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index 0282d9824..ecaf0cca7 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -79,6 +79,9 @@ struct spdk_ftl_dev { /* P2L map memory pool */ struct ftl_mempool *p2l_pool; + /* Underlying SHM buf for LBA map mempool */ + struct ftl_md *p2l_pool_md; + /* Band md memory pool */ struct ftl_mempool *band_md_pool; diff --git a/lib/ftl/mngt/ftl_mngt_band.c b/lib/ftl/mngt/ftl_mngt_band.c index 4757032ce..16b50dd87 100644 --- a/lib/ftl/mngt/ftl_mngt_band.c +++ b/lib/ftl/mngt/ftl_mngt_band.c @@ -16,6 +16,7 @@ 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; return 0; } @@ -224,6 +225,10 @@ ftl_mngt_finalize_init_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process * uint64_t i, num_open = 0, num_shut = 0; uint64_t offset; + TAILQ_FOREACH_SAFE(band, &dev->free_bands, queue_entry, temp_band) { + band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID; + } + TAILQ_FOREACH_SAFE(band, &dev->shut_bands, queue_entry, temp_band) { if (band->md->state == FTL_BAND_STATE_OPEN || band->md->state == FTL_BAND_STATE_FULL) { @@ -241,6 +246,8 @@ ftl_mngt_finalize_init_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process * } else { num_shut++; } + + band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID; } /* Assign open bands to writers and alloc necessary resources */ @@ -269,6 +276,7 @@ ftl_mngt_finalize_init_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process * ftl_band_set_owner(band, ftl_writer_band_state_change, writer); 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); return; diff --git a/lib/ftl/mngt/ftl_mngt_misc.c b/lib/ftl/mngt/ftl_mngt_misc.c index 90b054640..7af1c0e9a 100644 --- a/lib/ftl/mngt/ftl_mngt_misc.c +++ b/lib/ftl/mngt/ftl_mngt_misc.c @@ -26,15 +26,25 @@ static int init_p2l_map_pool(struct spdk_ftl_dev *dev) { size_t p2l_pool_el_blks = spdk_divide_round_up(ftl_p2l_map_pool_elem_size(dev), FTL_BLOCK_SIZE); + size_t p2l_pool_buf_blks = P2L_MEMPOOL_SIZE * p2l_pool_el_blks; + void *p2l_pool_buf; - dev->p2l_pool = ftl_mempool_create(P2L_MEMPOOL_SIZE, - p2l_pool_el_blks * FTL_BLOCK_SIZE, - FTL_BLOCK_SIZE, - SPDK_ENV_SOCKET_ID_ANY); + dev->p2l_pool_md = ftl_md_create(dev, p2l_pool_buf_blks, 0, "p2l_pool", + FTL_MD_CREATE_SHM | FTL_MD_CREATE_SHM_NEW, NULL); + if (!dev->p2l_pool_md) { + return -ENOMEM; + } + + p2l_pool_buf = ftl_md_get_buffer(dev->p2l_pool_md); + dev->p2l_pool = ftl_mempool_create_ext(p2l_pool_buf, P2L_MEMPOOL_SIZE, + p2l_pool_el_blks * FTL_BLOCK_SIZE, + FTL_BLOCK_SIZE); if (!dev->p2l_pool) { return -ENOMEM; } + ftl_mempool_initialize_ext(dev->p2l_pool); + return 0; } @@ -70,10 +80,15 @@ void ftl_mngt_deinit_mem_pools(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) { if (dev->p2l_pool) { - ftl_mempool_destroy(dev->p2l_pool); + ftl_mempool_destroy_ext(dev->p2l_pool); dev->p2l_pool = NULL; } + if (dev->p2l_pool_md) { + ftl_md_destroy(dev->p2l_pool_md); + dev->p2l_pool_md = NULL; + } + if (dev->band_md_pool) { ftl_mempool_destroy(dev->band_md_pool); dev->band_md_pool = NULL; diff --git a/test/unit/lib/ftl/common/utils.c b/test/unit/lib/ftl/common/utils.c index a3f8748fb..ebfad3a76 100644 --- a/test/unit/lib/ftl/common/utils.c +++ b/test/unit/lib/ftl/common/utils.c @@ -50,6 +50,12 @@ ftl_mempool_put(struct ftl_mempool *mpool, void *element) spdk_mempool_put((struct spdk_mempool *)mpool, element); } +ftl_df_obj_id +ftl_mempool_get_df_obj_id(struct ftl_mempool *mpool, void *df_obj_ptr) +{ + return (ftl_df_obj_id)df_obj_ptr; +} + struct spdk_ftl_dev * test_init_ftl_dev(const struct base_bdev_geometry *geo) { @@ -107,6 +113,7 @@ test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id, size_t zone_size) band->id = id; band->md->state = FTL_BAND_STATE_CLOSED; + band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID; TAILQ_INSERT_HEAD(&dev->shut_bands, band, queue_entry); band->start_addr = zone_size * id;