From fcd2364c6ab60d5722af18c37ee98e6fce3af61a Mon Sep 17 00:00:00 2001 From: Wojciech Malikowski Date: Thu, 28 Mar 2019 10:48:43 -0400 Subject: [PATCH] lib/ftl: Metadata read/write interfaces refactor Extended ftl_band_read_lba_map() interface to provide range of lba map to read. Added ftl_xfer_offset_from_ppa() function for calculating offset of read portion of lba map based on ppa address from IO. This offset is used for coping read lba map portion to internal ftl buffer. Change-Id: I1c72a18c79eda8c33cd0b20ea36a5d9521a09d06 Signed-off-by: Wojciech Malikowski Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/449435 Reviewed-by: Darek Stojaczyk Reviewed-by: Konrad Sztyber Tested-by: SPDK CI Jenkins --- lib/ftl/ftl_band.c | 126 +++++++++++++------ lib/ftl/ftl_band.h | 11 +- lib/ftl/ftl_core.c | 4 +- lib/ftl/ftl_init.c | 2 +- lib/ftl/ftl_reloc.c | 3 +- lib/ftl/ftl_restore.c | 4 +- test/unit/lib/ftl/ftl_md/ftl_md_ut.c | 38 +++--- test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c | 4 +- 8 files changed, 120 insertions(+), 72 deletions(-) diff --git a/lib/ftl/ftl_band.c b/lib/ftl/ftl_band.c index 52869ab5b..23b85bec1 100644 --- a/lib/ftl/ftl_band.c +++ b/lib/ftl/ftl_band.c @@ -381,13 +381,6 @@ ftl_unpack_tail_md(struct spdk_ftl_dev *dev, struct ftl_md *md, void *data) return FTL_MD_SUCCESS; } -static int -ftl_unpack_lba_map(struct spdk_ftl_dev *dev, struct ftl_md *md, void *data) -{ - memcpy(md->lba_map, data, ftl_num_band_lbks(dev) * sizeof(uint64_t)); - return FTL_MD_SUCCESS; -} - static int ftl_unpack_head_md(struct spdk_ftl_dev *dev, struct ftl_md *md, void *data) { @@ -634,6 +627,29 @@ ftl_band_next_xfer_ppa(struct ftl_band *band, struct ftl_ppa ppa, size_t num_lbk return ppa; } +static size_t +ftl_xfer_offset_from_ppa(struct ftl_band *band, struct ftl_ppa ppa) +{ + struct ftl_chunk *chunk, *current_chunk; + unsigned int punit_offset = 0; + size_t off, num_stripes, xfer_size = band->dev->xfer_size; + + assert(ppa.chk == band->id); + + num_stripes = (ppa.lbk / xfer_size) * band->num_chunks; + off = ppa.lbk % xfer_size; + + current_chunk = ftl_band_chunk_from_ppa(band, ppa); + CIRCLEQ_FOREACH(chunk, &band->chunks, circleq) { + if (current_chunk == chunk) { + break; + } + punit_offset++; + } + + return xfer_size * (num_stripes + punit_offset) + off; +} + struct ftl_ppa ftl_band_ppa_from_lbkoff(struct ftl_band *band, uint64_t lbkoff) { @@ -722,8 +738,8 @@ ftl_read_md_cb(void *arg, int status) static struct ftl_md_io * ftl_io_init_md_read(struct spdk_ftl_dev *dev, struct ftl_md *md, void *data, struct ftl_ppa ppa, - struct ftl_band *band, size_t lbk_cnt, ftl_md_pack_fn fn, - const struct ftl_cb *cb) + struct ftl_band *band, size_t lbk_cnt, spdk_ftl_fn fn, + ftl_md_pack_fn pack_fn, struct ftl_cb cb) { struct ftl_md_io *io; struct ftl_io_init_opts opts = { @@ -735,7 +751,7 @@ ftl_io_init_md_read(struct spdk_ftl_dev *dev, struct ftl_md *md, void *data, str .flags = FTL_IO_MD | FTL_IO_PPA_MODE, .type = FTL_IO_READ, .lbk_cnt = lbk_cnt, - .fn = ftl_read_md_cb, + .fn = fn, .data = data, }; @@ -747,8 +763,8 @@ ftl_io_init_md_read(struct spdk_ftl_dev *dev, struct ftl_md *md, void *data, str io->io.ppa = ppa; io->md = md; io->buf = data; - io->pack_fn = fn; - io->cb = *cb; + io->pack_fn = pack_fn; + io->cb = cb; return io; } @@ -775,18 +791,18 @@ ftl_io_init_md_write(struct spdk_ftl_dev *dev, struct ftl_band *band, } static int -ftl_band_write_md(struct ftl_band *band, void *data, size_t lbk_cnt, +ftl_band_write_md(struct ftl_band *band, size_t lbk_cnt, ftl_md_pack_fn md_fn, spdk_ftl_fn cb) { struct spdk_ftl_dev *dev = band->dev; struct ftl_io *io; - io = ftl_io_init_md_write(dev, band, data, lbk_cnt, cb); + io = ftl_io_init_md_write(dev, band, band->md.dma_buf, lbk_cnt, cb); if (!io) { return -ENOMEM; } - md_fn(dev, &band->md, data); + md_fn(dev, &band->md, band->md.dma_buf); ftl_io_write(io); return 0; @@ -802,30 +818,32 @@ ftl_band_md_clear(struct ftl_md *md) } int -ftl_band_write_head_md(struct ftl_band *band, void *data, spdk_ftl_fn cb) +ftl_band_write_head_md(struct ftl_band *band, spdk_ftl_fn cb) { - return ftl_band_write_md(band, data, ftl_head_md_num_lbks(band->dev), + return ftl_band_write_md(band, ftl_head_md_num_lbks(band->dev), ftl_pack_head_md, cb); } int -ftl_band_write_tail_md(struct ftl_band *band, void *data, spdk_ftl_fn cb) +ftl_band_write_tail_md(struct ftl_band *band, spdk_ftl_fn cb) { - return ftl_band_write_md(band, data, ftl_tail_md_num_lbks(band->dev), + return ftl_band_write_md(band, ftl_tail_md_num_lbks(band->dev), ftl_pack_tail_md, cb); } static struct ftl_ppa -ftl_band_lba_map_ppa(struct ftl_band *band) +ftl_band_lba_map_ppa(struct ftl_band *band, size_t offset) { return ftl_band_next_xfer_ppa(band, band->tail_md_ppa, ftl_tail_md_hdr_num_lbks() + - ftl_vld_map_num_lbks(band->dev)); + ftl_vld_map_num_lbks(band->dev) + + offset); } static int -ftl_band_read_md(struct ftl_band *band, struct ftl_md *md, void *data, size_t lbk_cnt, - struct ftl_ppa start_ppa, ftl_md_pack_fn unpack_fn, const struct ftl_cb *cb) +ftl_band_read_md(struct ftl_band *band, struct ftl_md *md, void *data, + size_t lbk_cnt, struct ftl_ppa start_ppa, spdk_ftl_fn fn, + ftl_md_pack_fn pack_fn, const struct ftl_cb cb) { struct spdk_ftl_dev *dev = band->dev; struct ftl_md_io *io; @@ -834,7 +852,7 @@ ftl_band_read_md(struct ftl_band *band, struct ftl_md *md, void *data, size_t lb return -ENOENT; } - io = ftl_io_init_md_read(dev, md, data, start_ppa, band, lbk_cnt, unpack_fn, cb); + io = ftl_io_init_md_read(dev, md, data, start_ppa, band, lbk_cnt, fn, pack_fn, cb); if (!io) { return -ENOMEM; } @@ -845,35 +863,71 @@ ftl_band_read_md(struct ftl_band *band, struct ftl_md *md, void *data, size_t lb int ftl_band_read_tail_md(struct ftl_band *band, struct ftl_md *md, - void *data, struct ftl_ppa ppa, const struct ftl_cb *cb) + void *data, struct ftl_ppa ppa, struct ftl_cb cb) { return ftl_band_read_md(band, md, data, ftl_tail_md_num_lbks(band->dev), ppa, + ftl_read_md_cb, ftl_unpack_tail_md, cb); } -int -ftl_band_read_lba_map(struct ftl_band *band, struct ftl_md *md, - void *data, const struct ftl_cb *cb) +static size_t +ftl_lba_map_offset_from_ppa(struct ftl_band *band, struct ftl_ppa ppa) { - /* TODO: change this interface to allow reading parts of the LBA map instead of */ - /* reading whole metadata */ - return ftl_band_read_md(band, md, data, - ftl_lba_map_num_lbks(band->dev), - ftl_band_lba_map_ppa(band), - ftl_unpack_lba_map, - cb); + size_t offset; + struct ftl_ppa start_ppa = ftl_band_lba_map_ppa(band, 0); + + offset = ftl_xfer_offset_from_ppa(band, ppa) - ftl_xfer_offset_from_ppa(band, start_ppa); + assert(offset < ftl_lba_map_num_lbks(band->dev)); + + return offset; +} + +static void +ftl_read_lba_map_cb(void *arg, int status) +{ + struct ftl_md_io *md_io = arg; + struct ftl_io *io = &md_io->io; + struct ftl_md *md = md_io->md; + uint64_t offset; + + offset = ftl_lba_map_offset_from_ppa(io->band, io->ppa); + assert(offset + io->lbk_cnt <= ftl_lba_map_num_lbks(io->dev)); + + if (!status) { + memcpy((char *)md->lba_map + offset * FTL_BLOCK_SIZE, md->dma_buf, + io->lbk_cnt * FTL_BLOCK_SIZE); + } + + md_io->cb.fn(md_io->cb.ctx, status); +} + +int +ftl_band_read_lba_map(struct ftl_band *band, struct ftl_md *md, size_t offset, size_t lba_cnt, + struct ftl_cb cb) +{ + size_t lbk_cnt, lbk_off; + + lbk_off = offset * sizeof(uint64_t) / FTL_BLOCK_SIZE; + lbk_cnt = spdk_divide_round_up(lba_cnt * sizeof(uint64_t), FTL_BLOCK_SIZE); + + assert(lbk_off + lbk_cnt <= ftl_lba_map_num_lbks(band->dev)); + + return ftl_band_read_md(band, md, md->dma_buf, + lbk_cnt, ftl_band_lba_map_ppa(band, lbk_off), + ftl_read_lba_map_cb, NULL, cb); } int ftl_band_read_head_md(struct ftl_band *band, struct ftl_md *md, - void *data, const struct ftl_cb *cb) + void *data, struct ftl_cb cb) { return ftl_band_read_md(band, md, data, ftl_head_md_num_lbks(band->dev), ftl_band_head_md_ppa(band), + ftl_read_md_cb, ftl_unpack_head_md, cb); } diff --git a/lib/ftl/ftl_band.h b/lib/ftl/ftl_band.h index 1f1be40ac..570ad3822 100644 --- a/lib/ftl/ftl_band.h +++ b/lib/ftl/ftl_band.h @@ -180,14 +180,13 @@ struct ftl_band *ftl_band_from_ppa(struct spdk_ftl_dev *dev, struct ftl_ppa ppa) struct ftl_chunk *ftl_band_chunk_from_ppa(struct ftl_band *band, struct ftl_ppa); void ftl_band_md_clear(struct ftl_md *md); int ftl_band_read_tail_md(struct ftl_band *band, struct ftl_md *md, - void *data, struct ftl_ppa, - const struct ftl_cb *cb); + void *data, struct ftl_ppa, struct ftl_cb cb); int ftl_band_read_head_md(struct ftl_band *band, struct ftl_md *md, - void *data, const struct ftl_cb *cb); + void *data, struct ftl_cb cb); int ftl_band_read_lba_map(struct ftl_band *band, struct ftl_md *md, - void *data, const struct ftl_cb *cb); -int ftl_band_write_tail_md(struct ftl_band *band, void *data, spdk_ftl_fn cb); -int ftl_band_write_head_md(struct ftl_band *band, void *data, spdk_ftl_fn cb); + size_t offset, size_t lba_cnt, struct ftl_cb cb); +int ftl_band_write_tail_md(struct ftl_band *band, spdk_ftl_fn cb); +int ftl_band_write_head_md(struct ftl_band *band, spdk_ftl_fn cb); struct ftl_ppa ftl_band_tail_md_ppa(struct ftl_band *band); struct ftl_ppa ftl_band_head_md_ppa(struct ftl_band *band); void ftl_band_write_failed(struct ftl_band *band); diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index aa31881e3..c88810de0 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -260,7 +260,7 @@ ftl_wptr_close_band(struct ftl_wptr *wptr) ftl_band_set_state(band, FTL_BAND_STATE_CLOSING); band->tail_md_ppa = wptr->ppa; - return ftl_band_write_tail_md(band, band->md.dma_buf, ftl_md_write_cb); + return ftl_band_write_tail_md(band, ftl_md_write_cb); } static int @@ -276,7 +276,7 @@ ftl_wptr_open_band(struct ftl_wptr *wptr) assert(band->state == FTL_BAND_STATE_PREP); ftl_band_set_state(band, FTL_BAND_STATE_OPENING); - return ftl_band_write_head_md(band, band->md.dma_buf, ftl_md_write_cb); + return ftl_band_write_head_md(band, ftl_md_write_cb); } static int diff --git a/lib/ftl/ftl_init.c b/lib/ftl/ftl_init.c index cd08d9906..c0eac6f3d 100644 --- a/lib/ftl/ftl_init.c +++ b/lib/ftl/ftl_init.c @@ -526,7 +526,7 @@ ftl_init_wptr_list(struct spdk_ftl_dev *dev) * unnecessary overhead and should be replaced by different data structure. */ dev->lba_pool = spdk_mempool_create(pool_name, 2 + 8, - ftl_num_band_lbks(dev) * sizeof(uint64_t), + ftl_lba_map_num_lbks(dev) * FTL_BLOCK_SIZE, SPDK_MEMPOOL_DEFAULT_CACHE_SIZE, SPDK_ENV_SOCKET_ID_ANY); if (!dev->lba_pool) { diff --git a/lib/ftl/ftl_reloc.c b/lib/ftl/ftl_reloc.c index 8395cce39..c5ddcfc0c 100644 --- a/lib/ftl/ftl_reloc.c +++ b/lib/ftl/ftl_reloc.c @@ -189,7 +189,8 @@ ftl_reloc_read_lba_map(struct ftl_band_reloc *breloc) assert(false); } - return ftl_band_read_lba_map(band, &band->md, band->md.dma_buf, &io->cb); + return ftl_band_read_lba_map(band, &band->md, 0, + ftl_num_band_lbks(dev), io->cb); } static void diff --git a/lib/ftl/ftl_restore.c b/lib/ftl/ftl_restore.c index 90ba842fd..e9dadbd81 100644 --- a/lib/ftl/ftl_restore.c +++ b/lib/ftl/ftl_restore.c @@ -268,7 +268,7 @@ ftl_restore_head_md(struct ftl_restore *restore) rband = &restore->bands[i]; cb.ctx = rband; - if (ftl_band_read_head_md(rband->band, &rband->band->md, head_buf, &cb)) { + if (ftl_band_read_head_md(rband->band, &rband->band->md, head_buf, cb)) { if (spdk_likely(rband->band->num_chunks)) { SPDK_ERRLOG("Failed to read metadata on band %zu\n", i); @@ -399,7 +399,7 @@ ftl_restore_tail_md(struct ftl_restore_band *rband) band->tail_md_ppa = ftl_band_tail_md_ppa(band); band->md.lba_map = restore->lba_map; - if (ftl_band_read_tail_md(band, &band->md, restore->md_buf, band->tail_md_ppa, &cb)) { + if (ftl_band_read_tail_md(band, &band->md, restore->md_buf, band->tail_md_ppa, cb)) { SPDK_ERRLOG("Failed to send tail metadata read\n"); ftl_restore_complete(restore, -EIO); return -EIO; diff --git a/test/unit/lib/ftl/ftl_md/ftl_md_ut.c b/test/unit/lib/ftl/ftl_md/ftl_md_ut.c index 53e634328..9de9887d8 100644 --- a/test/unit/lib/ftl/ftl_md/ftl_md_ut.c +++ b/test/unit/lib/ftl/ftl_md/ftl_md_ut.c @@ -81,22 +81,19 @@ test_md_unpack(void) { struct ftl_band *band; struct ftl_md *md; - void *data; setup_band(&band, &g_geo, &g_range); md = &band->md; - data = malloc(ftl_tail_md_num_lbks(band->dev) * FTL_BLOCK_SIZE); - SPDK_CU_ASSERT_FATAL(data); + SPDK_CU_ASSERT_FATAL(md->dma_buf); - ftl_pack_head_md(band->dev, md, data); - CU_ASSERT_EQUAL(ftl_unpack_head_md(band->dev, md, data), FTL_MD_SUCCESS); + ftl_pack_head_md(band->dev, md, md->dma_buf); + CU_ASSERT_EQUAL(ftl_unpack_head_md(band->dev, md, md->dma_buf), FTL_MD_SUCCESS); - ftl_pack_tail_md(band->dev, md, data); - CU_ASSERT_EQUAL(ftl_unpack_tail_md(band->dev, md, data), FTL_MD_SUCCESS); + ftl_pack_tail_md(band->dev, md, md->dma_buf); + CU_ASSERT_EQUAL(ftl_unpack_tail_md(band->dev, md, md->dma_buf), FTL_MD_SUCCESS); - free(data); cleanup_band(band); } @@ -106,38 +103,35 @@ test_md_unpack_fail(void) struct ftl_band *band; struct ftl_md *md; struct ftl_md_hdr *hdr; - void *data; setup_band(&band, &g_geo, &g_range); md = &band->md; - data = malloc(ftl_tail_md_num_lbks(band->dev) * FTL_BLOCK_SIZE); - SPDK_CU_ASSERT_FATAL(data); + SPDK_CU_ASSERT_FATAL(md->dma_buf); /* check crc */ - ftl_pack_tail_md(band->dev, md, data); + ftl_pack_tail_md(band->dev, md, md->dma_buf); /* flip last bit of lba_map */ - *((char *)data + ftl_tail_md_num_lbks(band->dev) * FTL_BLOCK_SIZE - 1) ^= 0x1; - CU_ASSERT_EQUAL(ftl_unpack_tail_md(band->dev, md, data), FTL_MD_INVALID_CRC); + *((char *)md->dma_buf + ftl_tail_md_num_lbks(band->dev) * FTL_BLOCK_SIZE - 1) ^= 0x1; + CU_ASSERT_EQUAL(ftl_unpack_tail_md(band->dev, md, md->dma_buf), FTL_MD_INVALID_CRC); /* check invalid version */ - hdr = data; - ftl_pack_tail_md(band->dev, md, data); + hdr = md->dma_buf; + ftl_pack_tail_md(band->dev, md, md->dma_buf); hdr->ver++; - CU_ASSERT_EQUAL(ftl_unpack_tail_md(band->dev, md, data), FTL_MD_INVALID_VER); + CU_ASSERT_EQUAL(ftl_unpack_tail_md(band->dev, md, md->dma_buf), FTL_MD_INVALID_VER); /* check wrong UUID */ - ftl_pack_head_md(band->dev, md, data); + ftl_pack_head_md(band->dev, md, md->dma_buf); hdr->uuid.u.raw[0] ^= 0x1; - CU_ASSERT_EQUAL(ftl_unpack_head_md(band->dev, md, data), FTL_MD_NO_MD); + CU_ASSERT_EQUAL(ftl_unpack_head_md(band->dev, md, md->dma_buf), FTL_MD_NO_MD); /* check invalid size */ - ftl_pack_tail_md(band->dev, md, data); + ftl_pack_tail_md(band->dev, md, md->dma_buf); band->dev->geo.clba--; - CU_ASSERT_EQUAL(ftl_unpack_tail_md(band->dev, md, data), FTL_MD_INVALID_SIZE); + CU_ASSERT_EQUAL(ftl_unpack_tail_md(band->dev, md, md->dma_buf), FTL_MD_INVALID_SIZE); - free(data); cleanup_band(band); } diff --git a/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c b/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c index 7e69d2748..1c40b0c46 100644 --- a/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c +++ b/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c @@ -96,9 +96,9 @@ ftl_lba_map_num_lbks(const struct spdk_ftl_dev *dev) int ftl_band_read_lba_map(struct ftl_band *band, struct ftl_md *md, - void *data, const struct ftl_cb *cb) + size_t offset, size_t lbk_cnt, struct ftl_cb cb) { - cb->fn(cb->ctx, 0); + cb.fn(cb.ctx, 0); return 0; }