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:
Wojciech Malikowski 2019-03-28 10:48:43 -04:00 committed by Darek Stojaczyk
parent 0dd5f32ebe
commit fcd2364c6a
8 changed files with 120 additions and 72 deletions

View File

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

View File

@ -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);

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

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

View File

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

View File

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