lib/ftl: persistent cache initialization

Change-Id: I608d420bd115a70d60ee6995220dbfafb7a00731
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/449242
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Konrad Sztyber 2019-03-26 16:33:45 +01:00 committed by Jim Harris
parent a8b8badb3c
commit c139a7d9ba
4 changed files with 114 additions and 26 deletions

View File

@ -1400,7 +1400,7 @@ spdk_ftl_dev_get_attrs(const struct spdk_ftl_dev *dev, struct spdk_ftl_attrs *at
attrs->lbk_cnt = dev->num_lbas;
attrs->lbk_size = FTL_BLOCK_SIZE;
attrs->range = dev->range;
attrs->cache_bdev_desc = dev->cache_bdev_desc;
attrs->cache_bdev_desc = dev->nv_cache.bdev_desc;
}
static void

View File

@ -103,6 +103,17 @@ struct ftl_global_md {
uint64_t num_lbas;
};
struct ftl_nv_cache {
/* Write buffer cache bdev */
struct spdk_bdev_desc *bdev_desc;
/* Write pointer */
uint64_t current_addr;
/* Number of available blocks left */
uint64_t num_available;
/* Cache lock */
pthread_spinlock_t lock;
};
struct spdk_ftl_dev {
/* Device instance */
struct spdk_uuid uuid;
@ -137,8 +148,9 @@ struct spdk_ftl_dev {
struct spdk_nvme_ns *ns;
/* NVMe transport ID */
struct spdk_nvme_transport_id trid;
/* Write buffer cache */
struct spdk_bdev_desc *cache_bdev_desc;
/* Non-volatile write buffer cache */
struct ftl_nv_cache nv_cache;
/* LBA map memory pool */
struct spdk_mempool *lba_pool;

View File

@ -452,6 +452,46 @@ ftl_dev_nvme_init(struct spdk_ftl_dev *dev, const struct spdk_ftl_dev_init_opts
return 0;
}
static int
ftl_dev_init_nv_cache(struct spdk_ftl_dev *dev, struct spdk_bdev_desc *bdev_desc)
{
struct spdk_bdev *bdev;
if (!bdev_desc) {
return 0;
}
bdev = spdk_bdev_desc_get_bdev(bdev_desc);
SPDK_INFOLOG(SPDK_LOG_FTL_INIT, "Using %s as write buffer cache\n",
spdk_bdev_get_name(bdev));
if (spdk_bdev_get_block_size(bdev) != FTL_BLOCK_SIZE) {
SPDK_ERRLOG("Unsupported block size (%d)\n", spdk_bdev_get_block_size(bdev));
return -1;
}
/* The cache needs to be capable of storing at least two full bands. This requirement comes
* from the fact that cache works as a protection against power loss, so before the data
* inside the cache can be overwritten, the band it's stored on has to be closed.
*/
if (spdk_bdev_get_num_blocks(bdev) < ftl_num_band_lbks(dev) * 2) {
SPDK_ERRLOG("Insufficient number of blocks for write buffer cache(%"PRIu64"\n",
spdk_bdev_get_num_blocks(bdev));
return -1;
}
if (pthread_spin_init(&dev->nv_cache.lock, PTHREAD_PROCESS_PRIVATE)) {
SPDK_ERRLOG("Failed to initialize cache lock\n");
return -1;
}
dev->nv_cache.bdev_desc = bdev_desc;
dev->nv_cache.current_addr = 0;
dev->nv_cache.num_available = spdk_bdev_get_num_blocks(bdev);
return 0;
}
void
spdk_ftl_conf_init_defaults(struct spdk_ftl_conf *conf)
{
@ -790,31 +830,61 @@ ftl_restore_state(struct spdk_ftl_dev *dev, const struct spdk_ftl_dev_init_opts
static int
ftl_io_channel_create_cb(void *io_device, void *ctx)
{
struct ftl_io_channel *ch = ctx;
char mempool_name[32];
struct spdk_ftl_dev *dev = io_device;
struct ftl_io_channel *ioch = ctx;
char mempool_name[32];
snprintf(mempool_name, sizeof(mempool_name), "ftl_io_%p", ch);
ch->elem_size = sizeof(struct ftl_md_io);
ch->io_pool = spdk_mempool_create(mempool_name,
dev->conf.user_io_pool_size,
ch->elem_size,
0,
SPDK_ENV_SOCKET_ID_ANY);
if (!ch->io_pool) {
snprintf(mempool_name, sizeof(mempool_name), "ftl_io_%p", ioch);
ioch->cache_ioch = NULL;
ioch->elem_size = sizeof(struct ftl_md_io);
ioch->io_pool = spdk_mempool_create(mempool_name,
dev->conf.user_io_pool_size,
ioch->elem_size,
0,
SPDK_ENV_SOCKET_ID_ANY);
if (!ioch->io_pool) {
SPDK_ERRLOG("Failed to create IO channel's IO pool\n");
return -1;
}
if (dev->nv_cache.bdev_desc) {
ioch->cache_ioch = spdk_bdev_get_io_channel(dev->nv_cache.bdev_desc);
if (!ioch->cache_ioch) {
SPDK_ERRLOG("Failed to create cache IO channel\n");
spdk_mempool_free(ioch->io_pool);
return -1;
}
}
return 0;
}
static void
ftl_io_channel_destroy_cb(void *io_device, void *ctx)
{
struct ftl_io_channel *ch = ctx;
struct ftl_io_channel *ioch = ctx;
spdk_mempool_free(ch->io_pool);
spdk_mempool_free(ioch->io_pool);
if (ioch->cache_ioch) {
spdk_put_io_channel(ioch->cache_ioch);
}
}
static int
ftl_dev_init_io_channel(struct spdk_ftl_dev *dev)
{
spdk_io_device_register(dev, ftl_io_channel_create_cb, ftl_io_channel_destroy_cb,
sizeof(struct ftl_io_channel),
NULL);
dev->ioch = spdk_get_io_channel(dev);
if (!dev->ioch) {
spdk_io_device_unregister(dev, NULL);
return -1;
}
return 0;
}
int
@ -832,18 +902,12 @@ spdk_ftl_dev_init(const struct spdk_ftl_dev_init_opts *_opts, spdk_ftl_init_fn c
opts.conf = &g_default_conf;
}
spdk_io_device_register(dev, ftl_io_channel_create_cb, ftl_io_channel_destroy_cb,
sizeof(struct ftl_io_channel),
NULL);
TAILQ_INIT(&dev->retry_queue);
dev->conf = *opts.conf;
dev->ioch = spdk_get_io_channel(dev);
dev->init_cb = cb;
dev->init_arg = cb_arg;
dev->range = opts.range;
dev->limit = SPDK_FTL_LIMIT_MAX;
dev->cache_bdev_desc = opts.cache_bdev_desc;
dev->name = strdup(opts.name);
if (!dev->name) {
@ -883,6 +947,11 @@ spdk_ftl_dev_init(const struct spdk_ftl_dev_init_opts *_opts, spdk_ftl_init_fn c
goto fail_sync;
}
if (ftl_dev_init_nv_cache(dev, opts.cache_bdev_desc)) {
SPDK_ERRLOG("Unable to initialize persistent cache\n");
goto fail_sync;
}
dev->rwb = ftl_rwb_init(&dev->conf, dev->geo.ws_opt, dev->md_size);
if (!dev->rwb) {
SPDK_ERRLOG("Unable to initialize rwb structures\n");
@ -895,6 +964,11 @@ spdk_ftl_dev_init(const struct spdk_ftl_dev_init_opts *_opts, spdk_ftl_init_fn c
goto fail_sync;
}
if (ftl_dev_init_io_channel(dev)) {
SPDK_ERRLOG("Unable to initialize IO channels\n");
goto fail_sync;
}
if (ftl_dev_init_threads(dev, &opts)) {
SPDK_ERRLOG("Unable to initialize device threads\n");
goto fail_sync;
@ -905,7 +979,6 @@ spdk_ftl_dev_init(const struct spdk_ftl_dev_init_opts *_opts, spdk_ftl_init_fn c
SPDK_ERRLOG("Failed to setup initial state of the device\n");
goto fail_async;
}
} else {
if (ftl_restore_state(dev, &opts)) {
SPDK_ERRLOG("Unable to restore device's state from the SSD\n");
@ -952,8 +1025,10 @@ ftl_dev_free_sync(struct spdk_ftl_dev *dev)
ftl_dev_dump_bands(dev);
ftl_dev_dump_stats(dev);
spdk_put_io_channel(dev->ioch);
spdk_io_device_unregister(dev, NULL);
if (dev->ioch) {
spdk_put_io_channel(dev->ioch);
spdk_io_device_unregister(dev, NULL);
}
if (dev->bands) {
for (i = 0; i < ftl_dev_num_bands(dev); ++i) {

View File

@ -129,9 +129,10 @@ struct ftl_cb {
struct ftl_io_channel {
/* IO pool element size */
size_t elem_size;
/* IO pool */
struct spdk_mempool *io_pool;
/* Persistent cache IO channel */
struct spdk_io_channel *cache_ioch;
};
/* General IO descriptor */