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_VER := 5
|
||||||
SO_MINOR := 0
|
SO_MINOR := 0
|
||||||
|
|
||||||
|
ifdef SPDK_FTL_VSS_EMU
|
||||||
|
CFLAGS += -DSPDK_FTL_VSS_EMU
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(strip $(SPDK_FTL_ZONE_EMU_BLOCKS)),)
|
ifneq ($(strip $(SPDK_FTL_ZONE_EMU_BLOCKS)),)
|
||||||
CFLAGS += -DSPDK_FTL_ZONE_EMU_BLOCKS=$(SPDK_FTL_ZONE_EMU_BLOCKS)
|
CFLAGS += -DSPDK_FTL_ZONE_EMU_BLOCKS=$(SPDK_FTL_ZONE_EMU_BLOCKS)
|
||||||
endif
|
endif
|
||||||
|
@ -27,6 +27,21 @@ blocks2mib(uint64_t blocks)
|
|||||||
#define FTL_LAYOUT_REGION_ALIGNMENT_BLOCKS 32ULL
|
#define FTL_LAYOUT_REGION_ALIGNMENT_BLOCKS 32ULL
|
||||||
#define FTL_LAYOUT_REGION_ALIGNMENT_BYTES (FTL_LAYOUT_REGION_ALIGNMENT_BLOCKS * FTL_BLOCK_SIZE)
|
#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
|
static void
|
||||||
dump_region(struct spdk_ftl_dev *dev, struct ftl_layout_region *region)
|
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 *layout = &dev->layout;
|
||||||
struct ftl_layout_region *region;
|
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 = &layout->region[FTL_LAYOUT_REGION_TYPE_DATA_NVC];
|
||||||
region->type = FTL_LAYOUT_REGION_TYPE_DATA_NVC;
|
region->type = FTL_LAYOUT_REGION_TYPE_DATA_NVC;
|
||||||
region->name = "data_nvc";
|
region->name = "data_nvc";
|
||||||
@ -208,6 +233,36 @@ ftl_layout_setup(struct spdk_ftl_dev *dev)
|
|||||||
return 0;
|
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
|
void
|
||||||
ftl_layout_dump(struct spdk_ftl_dev *dev)
|
ftl_layout_dump(struct spdk_ftl_dev *dev)
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,10 @@ struct spdk_ftl_dev;
|
|||||||
struct ftl_md;
|
struct ftl_md;
|
||||||
|
|
||||||
enum ftl_layout_region_type {
|
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 */
|
/* User data region on the nv cache device */
|
||||||
FTL_LAYOUT_REGION_TYPE_DATA_NVC,
|
FTL_LAYOUT_REGION_TYPE_DATA_NVC,
|
||||||
|
|
||||||
@ -111,6 +115,13 @@ struct ftl_layout {
|
|||||||
*/
|
*/
|
||||||
int ftl_layout_setup(struct spdk_ftl_dev *dev);
|
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);
|
void ftl_layout_dump(struct spdk_ftl_dev *dev);
|
||||||
int ftl_validate_regions(struct spdk_ftl_dev *dev, struct ftl_layout *layout);
|
int ftl_validate_regions(struct spdk_ftl_dev *dev, struct ftl_layout *layout);
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include "spdk/bdev.h"
|
#include "spdk/bdev.h"
|
||||||
#include "ftl_core.h"
|
#include "ftl_core.h"
|
||||||
|
|
||||||
|
#ifndef SPDK_FTL_VSS_EMU
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ftl_nv_cache_bdev_readv_blocks_with_md(struct spdk_ftl_dev *dev,
|
ftl_nv_cache_bdev_readv_blocks_with_md(struct spdk_ftl_dev *dev,
|
||||||
struct spdk_bdev_desc *desc,
|
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);
|
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 */
|
#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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SPDK_FTL_VSS_EMU
|
||||||
if (!spdk_bdev_is_md_separate(bdev)) {
|
if (!spdk_bdev_is_md_separate(bdev)) {
|
||||||
FTL_ERRLOG(dev, "Bdev %s doesn't support separate metadata buffer IO\n",
|
FTL_ERRLOG(dev, "Bdev %s doesn't support separate metadata buffer IO\n",
|
||||||
spdk_bdev_get_name(bdev));
|
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));
|
spdk_bdev_get_name(bdev));
|
||||||
goto error;
|
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);
|
ftl_mngt_next_step(mngt);
|
||||||
return;
|
return;
|
||||||
|
@ -26,6 +26,9 @@ static bool
|
|||||||
is_buffer_needed(enum ftl_layout_region_type type)
|
is_buffer_needed(enum ftl_layout_region_type type)
|
||||||
{
|
{
|
||||||
switch (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_NVC:
|
||||||
case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
|
case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
|
||||||
return false;
|
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);
|
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,
|
.action = ftl_mngt_open_cache_bdev,
|
||||||
.cleanup = ftl_mngt_close_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",
|
.name = "Register IO device",
|
||||||
.action = ftl_mngt_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);
|
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_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);
|
void ftl_mngt_close_cache_bdev(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
|
||||||
|
Loading…
Reference in New Issue
Block a user