Commit e49ccfc8 authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Konrad Sztyber
Browse files

ftl: device startup and shutdown



Signed-off-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: default avatarKozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: Ia4a3439a2ac79e24bc6dc11a5c131d44ecb2ad80
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13291


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
parent 9f6a3243
Loading
Loading
Loading
Loading
+39 −3
Original line number Diff line number Diff line
@@ -18,6 +18,12 @@ extern "C" {
struct spdk_ftl_dev;

struct spdk_ftl_conf {
	/* Device's name */
	char					*name;

	/* Device UUID (valid when restoring device from disk) */
	struct spdk_uuid			uuid;

	/* Percentage of base device blocks not exposed to the user */
	uint64_t				overprovisioning;

@@ -35,9 +41,6 @@ struct spdk_ftl_conf {

	/* Name of cache block device (must support extended metadata) */
	char					*cache_bdev;

	/* Base bdev reclaim unit size */
	uint64_t				base_bdev_reclaim_unit_size;
};

enum spdk_ftl_mode {
@@ -45,6 +48,39 @@ enum spdk_ftl_mode {
	SPDK_FTL_MODE_CREATE = (1 << 0),
};

typedef void (*spdk_ftl_fn)(void *cb_arg, int status);
typedef void (*spdk_ftl_init_fn)(struct spdk_ftl_dev *dev, void *cb_arg, int status);

/**
 * Initialize the FTL on the given pair of bdevs - base and cache bdev.
 * Upon receiving a successful completion callback user is free to use I/O calls.
 *
 * \param conf configuration for new device
 * \param cb callback function to call when the device is created
 * \param cb_arg callback's argument
 *
 * \return 0 if initialization was started successfully, negative errno otherwise.
 */
int spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb, void *cb_arg);

/**
 * Deinitialize and free given device.
 *
 * \param dev device
 * \param cb callback function to call when the device is freed
 * \param cb_arg callback's argument
 *
 * \return 0 if deinitialization was started successfully, negative errno otherwise.
 */
int spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb, void *cb_arg);

/**
 * Initialize FTL configuration structure with default values.
 *
 * \param conf FTL configuration to initialize
 */
void spdk_ftl_get_default_conf(struct spdk_ftl_conf *conf);

#ifdef __cplusplus
}
#endif
+6 −2
Original line number Diff line number Diff line
@@ -9,12 +9,16 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 5
SO_MINOR := 0

ifneq ($(strip $(SPDK_FTL_ZONE_EMU_BLOCKS)),)
CFLAGS += -DSPDK_FTL_ZONE_EMU_BLOCKS=$(SPDK_FTL_ZONE_EMU_BLOCKS)
endif

CFLAGS += -I.

FTL_SUBDIRS := mngt utils

C_SRCS = ftl_core.c
C_SRCS += mngt/ftl_mngt.c
C_SRCS = ftl_core.c ftl_init.c
C_SRCS += mngt/ftl_mngt.c mngt/ftl_mngt_bdev.c mngt/ftl_mngt_shutdown.c mngt/ftl_mngt_startup.c
C_SRCS += utils/ftl_conf.c

SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_ftl.map)
+31 −5
Original line number Diff line number Diff line
@@ -20,11 +20,8 @@
#include "utils/ftl_log.h"

struct spdk_ftl_dev {
	/* Device instance */
	struct spdk_uuid		uuid;

	/* Device name */
	char				*name;
	/* Configuration */
	struct spdk_ftl_conf		conf;

	/* Underlying device */
	struct spdk_bdev_desc		*base_bdev_desc;
@@ -92,4 +89,33 @@ struct spdk_ftl_dev {
	TAILQ_HEAD(, ftl_io)		wr_sq;
};

static inline uint64_t
ftl_get_num_blocks_in_band(const struct spdk_ftl_dev *dev)
{
	return dev->num_blocks_in_band;
}

static inline size_t
ftl_get_num_zones_in_band(const struct spdk_ftl_dev *dev)
{
	return dev->num_zones_in_band;
}

static inline size_t
ftl_get_num_blocks_in_zone(const struct spdk_ftl_dev *dev)
{
	return dev->num_blocks_in_zone;
}

static inline uint32_t
ftl_get_write_unit_size(struct spdk_bdev *bdev)
{
	if (spdk_bdev_is_zoned(bdev)) {
		return spdk_bdev_get_write_unit_size(bdev);
	}

	/* TODO: this should be passed via input parameter */
	return 32;
}

#endif /* FTL_CORE_H */

lib/ftl/ftl_init.c

0 → 100644
+207 −0
Original line number Diff line number Diff line
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (c) Intel Corporation.
 *   All rights reserved.
 */

#include "spdk/stdinc.h"
#include "spdk/nvme.h"
#include "spdk/thread.h"
#include "spdk/string.h"
#include "spdk/likely.h"
#include "spdk/ftl.h"
#include "spdk/likely.h"
#include "spdk/string.h"
#include "spdk/bdev_zone.h"
#include "spdk/bdev_module.h"
#include "spdk/config.h"

#include "ftl_core.h"
#include "ftl_utils.h"
#include "mngt/ftl_mngt.h"

struct ftl_dev_init_ctx {
	spdk_ftl_init_fn		cb_fn;
	/* Callback's argument */
	void				*cb_arg;
};

struct ftl_dev_free_ctx {
	spdk_ftl_fn			cb_fn;
	/* Callback's argument */
	void				*cb_arg;
};

static int
init_core_thread(struct spdk_ftl_dev *dev)
{
	struct spdk_cpuset cpumask = {};

	/*
	 * If core mask is provided create core thread on first cpu that match with the mask,
	 * otherwise use current user thread
	 */
	if (dev->conf.core_mask) {
		if (spdk_cpuset_parse(&cpumask, dev->conf.core_mask)) {
			return -EINVAL;
		}
		dev->core_thread = spdk_thread_create("ftl_core_thread", &cpumask);
	} else {
		dev->core_thread = spdk_get_thread();
	}

	if (dev->core_thread == NULL) {
		FTL_ERRLOG(dev, "Cannot create thread for mask %s\n", dev->conf.core_mask);
		return -ENOMEM;
	}

	return 0;
}

static void
exit_thread(void *ctx)
{
	struct spdk_thread *thread = ctx;

	spdk_thread_exit(thread);
}

static void
deinit_core_thread(struct spdk_ftl_dev *dev)
{
	if (dev->core_thread && dev->conf.core_mask) {
		spdk_thread_send_msg(dev->core_thread, exit_thread,
				     dev->core_thread);
		dev->core_thread = NULL;
	}
}

static void
free_dev(struct spdk_ftl_dev *dev)
{
	if (!dev) {
		return;
	}

	deinit_core_thread(dev);
	ftl_conf_deinit(&dev->conf);
	free(dev);
}

static struct spdk_ftl_dev *
allocate_dev(const struct spdk_ftl_conf *conf, int *error)
{
	int rc;
	struct spdk_ftl_dev *dev = calloc(1, sizeof(*dev));

	if (!dev) {
		FTL_ERRLOG(dev, "Cannot allocate FTL device\n");
		*error = -ENOMEM;
		return NULL;
	}

	rc = ftl_conf_init_dev(dev, conf);
	if (rc) {
		*error = rc;
		goto error;
	}

	rc = init_core_thread(dev);
	if (rc) {
		*error = rc;
		goto error;
	}

	TAILQ_INIT(&dev->rd_sq);
	TAILQ_INIT(&dev->wr_sq);

	return dev;
error:
	free_dev(dev);
	return NULL;
}

static void
dev_init_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
{
	struct ftl_dev_init_ctx *ctx = _ctx;

	if (status) {
		free_dev(dev);
		dev = NULL;
	}
	ctx->cb_fn(dev, ctx->cb_arg, status);
	free(ctx);
}

int
spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb_fn, void *cb_arg)
{
	int rc = -1;
	struct ftl_dev_init_ctx *ctx;
	struct spdk_ftl_dev *dev = NULL;

	ctx = calloc(1, sizeof(*ctx));
	if (!ctx) {
		rc = -ENOMEM;
		goto error;
	}
	ctx->cb_fn = cb_fn;
	ctx->cb_arg = cb_arg;

	dev = allocate_dev(conf, &rc);
	if (!dev) {
		goto error;
	}

	rc = ftl_mngt_call_dev_startup(dev, dev_init_cb, ctx);
	if (rc) {
		goto error;
	}

	return 0;

error:
	free(ctx);
	free_dev(dev);
	return rc;
}

static void
dev_free_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
{
	struct ftl_dev_free_ctx *ctx = _ctx;

	if (!status) {
		free_dev(dev);
	}
	ctx->cb_fn(ctx->cb_arg, status);
	free(ctx);
}

int
spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
{
	int rc = -1;
	struct ftl_dev_free_ctx *ctx;

	ctx = calloc(1, sizeof(*ctx));
	if (!ctx) {
		rc = -ENOMEM;
		goto error;
	}
	ctx->cb_fn = cb_fn;
	ctx->cb_arg = cb_arg;

	rc = ftl_mngt_call_dev_shutdown(dev, dev_free_cb, ctx);
	if (rc) {
		goto error;
	}

	return 0;

error:
	free(ctx);
	return rc;
}

SPDK_LOG_REGISTER_COMPONENT(ftl_init)
+2 −0
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@

/* Marks address as invalid */
#define FTL_ADDR_INVALID	((ftl_addr)-1)
/* Smallest data unit size */
#define FTL_BLOCK_SIZE		4096ULL

/*
 * This type represents address in the ftl address space. Values from 0 to based bdev size are
Loading