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:
parent
884980d0aa
commit
f725ca81cf
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user