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:
parent
a8b8badb3c
commit
c139a7d9ba
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user