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: Maciej Szczepaniak <maciej.szczepaniak@intel.com> Change-Id: I91806feb7aa0ef8057792bc120b09a39c63c8640 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/649 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Wojciech Malikowski <wojciech.malikowski@intel.com> Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
15a3067b78
commit
01ea524068
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
@ -529,31 +534,73 @@ ftl_dev_init_core_thread(struct spdk_ftl_dev *dev, const struct spdk_ftl_dev_ini
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ftl_dev_l2p_alloc_pmem(struct spdk_ftl_dev *dev, size_t l2p_size, const char *l2p_path)
|
||||
{
|
||||
#ifdef SPDK_CONFIG_PMDK
|
||||
int is_pmem;
|
||||
|
||||
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 (!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 */
|
||||
}
|
||||
|
||||
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_ERRLOG("Failed to allocate l2p table\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
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_DEBUGLOG(SPDK_LOG_FTL_INIT, "Invalid l2p table size\n");
|
||||
SPDK_ERRLOG("Invalid l2p table size\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dev->l2p) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_FTL_INIT, "L2p table already allocated\n");
|
||||
SPDK_ERRLOG("L2p table already allocated\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr_size = dev->addr_len >= 32 ? 8 : 4;
|
||||
dev->l2p = malloc(dev->num_lbas * addr_size);
|
||||
if (!dev->l2p) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_FTL_INIT, "Failed to allocate l2p table\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);
|
||||
}
|
||||
|
||||
memset(dev->l2p, FTL_ADDR_INVALID, dev->num_lbas * addr_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1383,7 +1430,14 @@ ftl_dev_free_sync(struct spdk_ftl_dev *dev)
|
||||
free(dev->iov_buf);
|
||||
free(dev->name);
|
||||
free(dev->bands);
|
||||
free(dev->l2p);
|
||||
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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user