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; }