ftl: vss emulation

Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: If22933834d640606526dec9185e849df367ac789
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13311
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Artur Paszkiewicz 2022-06-15 10:02:25 +02:00 committed by Jim Harris
parent 884980d0aa
commit f725ca81cf
8 changed files with 244 additions and 0 deletions

View File

@ -9,6 +9,10 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 5
SO_MINOR := 0
ifdef SPDK_FTL_VSS_EMU
CFLAGS += -DSPDK_FTL_VSS_EMU
endif
ifneq ($(strip $(SPDK_FTL_ZONE_EMU_BLOCKS)),)
CFLAGS += -DSPDK_FTL_ZONE_EMU_BLOCKS=$(SPDK_FTL_ZONE_EMU_BLOCKS)
endif

View File

@ -27,6 +27,21 @@ blocks2mib(uint64_t blocks)
#define FTL_LAYOUT_REGION_ALIGNMENT_BLOCKS 32ULL
#define FTL_LAYOUT_REGION_ALIGNMENT_BYTES (FTL_LAYOUT_REGION_ALIGNMENT_BLOCKS * FTL_BLOCK_SIZE)
#ifdef SPDK_FTL_VSS_EMU
static inline uint64_t
blocks_region(uint64_t bytes)
{
const uint64_t alignment = FTL_LAYOUT_REGION_ALIGNMENT_BYTES;
uint64_t result;
result = spdk_divide_round_up(bytes, alignment);
result *= alignment;
result /= FTL_BLOCK_SIZE;
return result;
}
#endif
static void
dump_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
{
@ -111,6 +126,16 @@ setup_layout_nvc(struct spdk_ftl_dev *dev)
struct ftl_layout *layout = &dev->layout;
struct ftl_layout_region *region;
#ifdef SPDK_FTL_VSS_EMU
/* Skip the already init`d VSS region */
region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS];
offset += region->current.blocks;
if (offset >= layout->nvc.total_blocks) {
goto error;
}
#endif
region = &layout->region[FTL_LAYOUT_REGION_TYPE_DATA_NVC];
region->type = FTL_LAYOUT_REGION_TYPE_DATA_NVC;
region->name = "data_nvc";
@ -208,6 +233,36 @@ ftl_layout_setup(struct spdk_ftl_dev *dev)
return 0;
}
#ifdef SPDK_FTL_VSS_EMU
void
ftl_layout_setup_vss_emu(struct spdk_ftl_dev *dev)
{
const struct spdk_bdev *bdev;
struct ftl_layout *layout = &dev->layout;
struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS];
assert(layout->md[FTL_LAYOUT_REGION_TYPE_VSS] == NULL);
region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS];
region->type = FTL_LAYOUT_REGION_TYPE_VSS;
region->name = "vss";
region->current.version = region->prev.version = 0;
region->current.offset = 0;
bdev = spdk_bdev_desc_get_bdev(dev->cache_bdev_desc);
layout->nvc.total_blocks = spdk_bdev_get_num_blocks(bdev);
region->current.blocks = blocks_region(dev->cache_md_size * layout->nvc.total_blocks);
region->vss_blksz = 0;
region->bdev_desc = dev->cache_bdev_desc;
region->ioch = dev->cache_ioch;
assert(region->bdev_desc != NULL);
assert(region->ioch != NULL);
}
#endif
void
ftl_layout_dump(struct spdk_ftl_dev *dev)
{

View File

@ -12,6 +12,10 @@ struct spdk_ftl_dev;
struct ftl_md;
enum ftl_layout_region_type {
#ifdef SPDK_FTL_VSS_EMU
/** VSS region for NV cache VSS emulation */
FTL_LAYOUT_REGION_TYPE_VSS,
#endif
/* User data region on the nv cache device */
FTL_LAYOUT_REGION_TYPE_DATA_NVC,
@ -111,6 +115,13 @@ struct ftl_layout {
*/
int ftl_layout_setup(struct spdk_ftl_dev *dev);
#ifdef SPDK_FTL_VSS_EMU
/**
* @brief Setup FTL layout of VSS emu
*/
void ftl_layout_setup_vss_emu(struct spdk_ftl_dev *dev);
#endif
void ftl_layout_dump(struct spdk_ftl_dev *dev);
int ftl_validate_regions(struct spdk_ftl_dev *dev, struct ftl_layout *layout);

View File

@ -9,6 +9,8 @@
#include "spdk/bdev.h"
#include "ftl_core.h"
#ifndef SPDK_FTL_VSS_EMU
static inline int
ftl_nv_cache_bdev_readv_blocks_with_md(struct spdk_ftl_dev *dev,
struct spdk_bdev_desc *desc,
@ -61,4 +63,116 @@ ftl_nv_cache_bdev_write_blocks_with_md(struct spdk_ftl_dev *dev,
cb, cb_arg);
}
#else
/* TODO: Maybe we can add a non-power-fail-safe support for VSS in AIO bdev and get rid of this */
static inline void
ftl_nv_cache_bdev_get_md(struct spdk_ftl_dev *dev,
uint64_t offset_blocks, uint64_t num_blocks,
void *md_buf)
{
struct ftl_md *vss = dev->layout.md[FTL_LAYOUT_REGION_TYPE_VSS];
union ftl_md_vss *src;
union ftl_md_vss *dst = md_buf;
union ftl_md_vss *dst_end = dst + num_blocks;
assert(offset_blocks + num_blocks <= dev->layout.nvc.total_blocks);
if (!md_buf) {
return;
}
src = ftl_md_get_buffer(vss);
src += offset_blocks;
while (dst < dst_end) {
*dst = *src;
dst++;
src++;
}
}
static inline int
ftl_nv_cache_bdev_readv_blocks_with_md(struct spdk_ftl_dev *dev,
struct spdk_bdev_desc *desc,
struct spdk_io_channel *ch,
struct iovec *iov, int iovcnt, void *md,
uint64_t offset_blocks, uint64_t num_blocks,
spdk_bdev_io_completion_cb cb, void *cb_arg)
{
assert(desc == dev->cache_bdev_desc);
ftl_nv_cache_bdev_get_md(dev, offset_blocks, num_blocks, md);
return spdk_bdev_readv_blocks(desc, ch, iov, iovcnt, offset_blocks,
num_blocks, cb, cb_arg);
}
static inline void
ftl_nv_cache_bdev_set_md(struct spdk_ftl_dev *dev,
uint64_t offset_blocks, uint64_t num_blocks,
void *md_buf)
{
struct ftl_md *vss = dev->layout.md[FTL_LAYOUT_REGION_TYPE_VSS];
union ftl_md_vss *src = md_buf;
union ftl_md_vss *src_end = src + num_blocks;
union ftl_md_vss *dst;
assert(offset_blocks + num_blocks <= dev->layout.nvc.total_blocks);
if (!md_buf) {
return;
}
dst = ftl_md_get_buffer(vss);
dst += offset_blocks;
while (src < src_end) {
*dst = *src;
dst++;
src++;
}
}
static inline int
ftl_nv_cache_bdev_writev_blocks_with_md(struct spdk_ftl_dev *dev,
struct spdk_bdev_desc *desc,
struct spdk_io_channel *ch,
struct iovec *iov, int iovcnt, void *md_buf,
uint64_t offset_blocks, uint64_t num_blocks,
spdk_bdev_io_completion_cb cb, void *cb_arg)
{
assert(desc == dev->cache_bdev_desc);
ftl_nv_cache_bdev_set_md(dev, offset_blocks, num_blocks, md_buf);
return spdk_bdev_writev_blocks(desc, ch, iov, iovcnt,
offset_blocks, num_blocks,
cb, cb_arg);
}
static inline int
ftl_nv_cache_bdev_read_blocks_with_md(struct spdk_ftl_dev *dev,
struct spdk_bdev_desc *desc,
struct spdk_io_channel *ch,
void *buf, void *md,
uint64_t offset_blocks, uint64_t num_blocks,
spdk_bdev_io_completion_cb cb, void *cb_arg)
{
assert(desc == dev->cache_bdev_desc);
ftl_nv_cache_bdev_get_md(dev, offset_blocks, num_blocks, md);
return spdk_bdev_read_blocks(desc, ch, buf, offset_blocks,
num_blocks, cb, cb_arg);
}
static inline int
ftl_nv_cache_bdev_write_blocks_with_md(struct spdk_ftl_dev *dev,
struct spdk_bdev_desc *desc,
struct spdk_io_channel *ch,
void *buf, void *md,
uint64_t offset_blocks, uint64_t num_blocks,
spdk_bdev_io_completion_cb cb, void *cb_arg)
{
assert(desc == dev->cache_bdev_desc);
ftl_nv_cache_bdev_set_md(dev, offset_blocks, num_blocks, md);
return spdk_bdev_write_blocks(desc, ch, buf,
offset_blocks, num_blocks,
cb, cb_arg);
}
#endif
#endif /* FTL_NV_CACHE_IO_H */

View File

@ -203,6 +203,7 @@ ftl_mngt_open_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt
goto error;
}
#ifndef SPDK_FTL_VSS_EMU
if (!spdk_bdev_is_md_separate(bdev)) {
FTL_ERRLOG(dev, "Bdev %s doesn't support separate metadata buffer IO\n",
spdk_bdev_get_name(bdev));
@ -233,6 +234,15 @@ ftl_mngt_open_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt
spdk_bdev_get_name(bdev));
goto error;
}
#else
if (spdk_bdev_is_md_separate(bdev)) {
FTL_ERRLOG(dev, "FTL VSS emulation but NV cache supports VSS\n");
goto error;
}
dev->cache_md_size = 64;
FTL_NOTICELOG(dev, "FTL uses VSS emulation\n");
#endif
ftl_mngt_next_step(mngt);
return;

View File

@ -26,6 +26,9 @@ static bool
is_buffer_needed(enum ftl_layout_region_type type)
{
switch (type) {
#ifdef SPDK_FTL_VSS_EMU
case FTL_LAYOUT_REGION_TYPE_VSS:
#endif
case FTL_LAYOUT_REGION_TYPE_DATA_NVC:
case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
return false;
@ -79,3 +82,37 @@ ftl_mngt_deinit_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
ftl_mngt_next_step(mngt);
}
#ifdef SPDK_FTL_VSS_EMU
void
ftl_mngt_md_init_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
struct ftl_layout *layout = &dev->layout;
struct ftl_layout_region *region = &layout->region[FTL_LAYOUT_REGION_TYPE_VSS];
/* Initialize VSS layout */
ftl_layout_setup_vss_emu(dev);
/* Allocate md buf */
layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = ftl_md_create(dev, region->current.blocks,
region->vss_blksz, NULL, 0, region);
if (NULL == layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) {
ftl_mngt_fail_step(mngt);
return;
}
ftl_mngt_next_step(mngt);
}
void
ftl_mngt_md_deinit_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
struct ftl_layout *layout = &dev->layout;
if (layout->md[FTL_LAYOUT_REGION_TYPE_VSS]) {
ftl_md_destroy(layout->md[FTL_LAYOUT_REGION_TYPE_VSS]);
layout->md[FTL_LAYOUT_REGION_TYPE_VSS] = NULL;
}
ftl_mngt_next_step(mngt);
}
#endif

View File

@ -42,6 +42,13 @@ static const struct ftl_mngt_process_desc desc_startup = {
.action = ftl_mngt_open_cache_bdev,
.cleanup = ftl_mngt_close_cache_bdev
},
#ifdef SPDK_FTL_VSS_EMU
{
.name = "Initialize VSS emu",
.action = ftl_mngt_md_init_vss_emu,
.cleanup = ftl_mngt_md_deinit_vss_emu
},
#endif
{
.name = "Register IO device",
.action = ftl_mngt_register_io_device,

View File

@ -14,6 +14,12 @@ void ftl_mngt_open_base_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *
void ftl_mngt_close_base_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
#ifdef SPDK_FTL_VSS_EMU
void ftl_mngt_md_init_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_md_deinit_vss_emu(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
#endif
void ftl_mngt_open_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_close_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);