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 <wojciech.malikowski@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/449435 Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
0dd5f32ebe
commit
fcd2364c6a
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user