Commit 01ea5240 authored by Maciej Szczepaniak's avatar Maciej Szczepaniak Committed by Tomasz Zawadzki
Browse files

lib/ftl: Create l2p on l2p_path file if set in config



New spdk_ftl_conf parameter l2p_path, l2p_path defines
location of existing pmem file or device to use as l2p table.

ftl_dev_l2p_alloc now has two flows:
1. If l2p_path is set perform pmem_map_file (PMDK) of l2p_size on it
2. Else malloc l2p table as usual

l2p_get/set will use atomic_load/store on both of those storage
locations as PMDK pmem_memcpy family of functions is not thread safe.

Signed-off-by: default avatarMaciej Szczepaniak <maciej.szczepaniak@intel.com>
Change-Id: I91806feb7aa0ef8057792bc120b09a39c63c8640
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/649


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarWojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 15a3067b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -102,6 +102,9 @@ struct spdk_ftl_conf {
		/* Maximum number of blocks per one request */
		size_t				max_request_size;
	} nv_cache;

	/* Create l2p table on l2p_path persistent memory file or device instead of in DRAM */
	const char				*l2p_path;
};

enum spdk_ftl_mode {
+2 −0
Original line number Diff line number Diff line
@@ -175,6 +175,8 @@ struct spdk_ftl_dev {
	void					*l2p;
	/* Size of the l2p table */
	uint64_t				num_lbas;
	/* Size of pages mmapped for l2p, valid only for mapping on persistent memory */
	size_t					l2p_pmem_len;

	/* Address size */
	size_t					addr_len;
+73 −11
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include "spdk/string.h"
#include "spdk/bdev_zone.h"
#include "spdk/bdev_module.h"
#include "spdk/config.h"

#include "ftl_core.h"
#include "ftl_io.h"
@@ -49,6 +50,10 @@
#include "ftl_band.h"
#include "ftl_debug.h"

#ifdef SPDK_CONFIG_PMDK
#include "libpmem.h"
#endif /* SPDK_CONFIG_PMDK */

#define FTL_CORE_RING_SIZE	4096
#define FTL_INIT_TIMEOUT	30
#define FTL_NSID		1
@@ -530,32 +535,74 @@ ftl_dev_init_core_thread(struct spdk_ftl_dev *dev, const struct spdk_ftl_dev_ini
}

static int
ftl_dev_l2p_alloc(struct spdk_ftl_dev *dev)
ftl_dev_l2p_alloc_pmem(struct spdk_ftl_dev *dev, size_t l2p_size, const char *l2p_path)
{
	size_t addr_size;
#ifdef SPDK_CONFIG_PMDK
	int is_pmem;

	if (dev->num_lbas == 0) {
		SPDK_DEBUGLOG(SPDK_LOG_FTL_INIT, "Invalid l2p table size\n");
	if ((dev->l2p = pmem_map_file(l2p_path, 0,
				      0, 0, &dev->l2p_pmem_len, &is_pmem)) == NULL) {
		SPDK_ERRLOG("Failed to mmap l2p_path\n");
		return -1;
	}

	if (dev->l2p) {
		SPDK_DEBUGLOG(SPDK_LOG_FTL_INIT, "L2p table already allocated\n");
	if (!is_pmem) {
		SPDK_NOTICELOG("l2p_path mapped on non-pmem device\n");
	}

	if (dev->l2p_pmem_len < l2p_size) {
		SPDK_ERRLOG("l2p_path file is too small\n");
		return -1;
	}

	pmem_memset_persist(dev->l2p, FTL_ADDR_INVALID, l2p_size);

	return 0;
#else /* SPDK_CONFIG_PMDK */
	SPDK_ERRLOG("Libpmem not available, cannot use pmem l2p_path\n");
	return -1;
#endif /* SPDK_CONFIG_PMDK */
}

	addr_size = dev->addr_len >= 32 ? 8 : 4;
	dev->l2p = malloc(dev->num_lbas * addr_size);
static int
ftl_dev_l2p_alloc_dram(struct spdk_ftl_dev *dev, size_t l2p_size)
{
	dev->l2p = malloc(l2p_size);
	if (!dev->l2p) {
		SPDK_DEBUGLOG(SPDK_LOG_FTL_INIT, "Failed to allocate l2p table\n");
		SPDK_ERRLOG("Failed to allocate l2p table\n");
		return -1;
	}

	memset(dev->l2p, FTL_ADDR_INVALID, dev->num_lbas * addr_size);
	memset(dev->l2p, FTL_ADDR_INVALID, l2p_size);

	return 0;
}

static int
ftl_dev_l2p_alloc(struct spdk_ftl_dev *dev)
{
	size_t addr_size = dev->addr_len >= 32 ? 8 : 4;
	size_t l2p_size = dev->num_lbas * addr_size;
	const char *l2p_path = dev->conf.l2p_path;

	if (dev->num_lbas == 0) {
		SPDK_ERRLOG("Invalid l2p table size\n");
		return -1;
	}

	if (dev->l2p) {
		SPDK_ERRLOG("L2p table already allocated\n");
		return -1;
	}

	dev->l2p_pmem_len = 0;
	if (l2p_path) {
		return ftl_dev_l2p_alloc_pmem(dev, l2p_size, l2p_path);
	} else {
		return ftl_dev_l2p_alloc_dram(dev, l2p_size);
	}
}

static void
ftl_dev_free_init_ctx(struct ftl_dev_init_ctx *init_ctx)
{
@@ -1383,7 +1430,14 @@ ftl_dev_free_sync(struct spdk_ftl_dev *dev)
	free(dev->iov_buf);
	free(dev->name);
	free(dev->bands);
	if (dev->l2p_pmem_len != 0) {
#ifdef SPDK_CONFIG_PMDK
		pmem_unmap(dev->l2p, dev->l2p_pmem_len);
#endif /* SPDK_CONFIG_PMDK */
	} else {
		free(dev->l2p);
	}
	free((char *)dev->conf.l2p_path);
	free(dev);
}

@@ -1435,6 +1489,14 @@ spdk_ftl_dev_init(const struct spdk_ftl_dev_init_opts *_opts, spdk_ftl_init_fn c
		goto fail_sync;
	}

	if (opts.conf->l2p_path) {
		dev->conf.l2p_path = strdup(opts.conf->l2p_path);
		if (!dev->conf.l2p_path) {
			rc = -ENOMEM;
			goto fail_sync;
		}
	}

	/* In case of errors, we free all of the memory in ftl_dev_free_sync(), */
	/* so we don't have to clean up in each of the init functions. */
	if (ftl_check_conf(dev, opts.conf)) {