Commit c139a7d9 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Jim Harris
Browse files

lib/ftl: persistent cache initialization



Change-Id: I608d420bd115a70d60ee6995220dbfafb7a00731
Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/449242


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent a8b8badb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+14 −2
Original line number Diff line number Diff line
@@ -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;
+97 −22
Original line number Diff line number Diff line
@@ -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,21 +830,31 @@ 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,
	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,
					  ch->elem_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 (!ch->io_pool) {
	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;
}
@@ -812,9 +862,29 @@ ftl_io_channel_create_cb(void *io_device, void *ctx)
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(ioch->io_pool);

	spdk_mempool_free(ch->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);

	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) {
+2 −1
Original line number Diff line number Diff line
@@ -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 */