Commit f725ca81 authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Jim Harris
Browse files

ftl: vss emulation

parent 884980d0
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+55 −0
Original line number Diff line number Diff line
@@ -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)
{
+11 −0
Original line number Diff line number Diff line
@@ -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);

+114 −0
Original line number Diff line number Diff line
@@ -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 */
+10 −0
Original line number Diff line number Diff line
@@ -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;
Loading