Commit 4d367354 authored by Pawel Wodkowski's avatar Pawel Wodkowski Committed by Jim Harris
Browse files

bdev: rework bdev module registration



Currently SPDK_BDEV_MODULE_REGISTER() take many parameters. Extending it
(eg for incoming JSON configuration dump/load) is quite challenging and
error prone. As we are already here in next patches, rework this macro
to take one parameter - the pointer to struct spdk_bdev_module_if.

This patch also remove following macros:
SPDK_GET_BDEV_MODULE - this is not really needed, to find module outside
module translation unit use spdk_bdev_module_list_find()

SPDK_BDEV_MODULE_ASYNC_INIT and SPDK_BDEV_MODULE_ASYNC_FINI - replaced
by bool fields in spdk_bdev_module_if struct.

Change-Id: Ief88e023fbbaee7d5402c838dbecbdffd4dfb259
Signed-off-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/402883


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 4294719e
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -25,13 +25,17 @@ module, add a new directory with a single C file and a Makefile. A great
starting point is to copy the existing 'null' bdev module.

The primary interface that bdev modules will interact with is in
include/spdk_internal/bdev.h. In that header a macro is defined that declares
a new bdev module named SPDK_BDEV_MODULE_REGISTER. This macro takes as
arguments a number of function pointers that are used to initialize, tear
down, and get the configuration of the module. There are also arguments to
specify context size, which is scratch space that will be allocated in each
I/O request for use by this module, and a callback that will be called each
time a new bdev is registered by another module.
include/spdk_internal/bdev.h. In that header a macro is defined that registers
a new bdev module - SPDK_BDEV_MODULE_REGISTER. This macro take as argument a
pointer spdk_bdev_module_if structure that is used to register new bdev module.

The spdk_bdev_module_if structure describes the module properties like
initialization (`module_init`) and teardown (`module_fini`) functions,
the function that returns context size (`get_ctx_size`) - scratch space that
will be allocated in each I/O request for use by this module, and a callback
that will be called each time a new bdev is registered by another module
(`examine`). Please check the documentation of struct spdk_bdev_module_if for
more details.

## Creating Bdevs

+29 −31
Original line number Diff line number Diff line
@@ -119,11 +119,22 @@ struct spdk_bdev_module_if {
	/**
	 * Count of bdev inits/examinations in progress. Used by generic bdev
	 * layer and must not be modified by bdev modules.
	 *
	 * \note Used internally by bdev subsystem, don't change this value in bdev module.
	 */
	uint32_t action_in_progress;

	/**
	 * Denotes if the module_init function may complete asynchronously. If set to true,
	 * the module initialization has to be explicitly completed by calling
	 * spdk_bdev_module_init_done().
	 */
	bool async_init;

	/**
	 * Denotes if the module_fini function may complete asynchronously.
	 * If set to true finishing has to be explicitly completed by calling
	 * spdk_bdev_module_fini_done().
	 */
	bool async_fini;

@@ -515,6 +526,14 @@ void spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io,

void spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module);

/**
 * Find registered module with name pointed by \c name.
 *
 * \param name name of module to be searched for.
 * \return pointer to module or NULL if no module with \c name exist
 */
struct spdk_bdev_module_if *spdk_bdev_module_list_find(const char *name);

static inline struct spdk_bdev_io *
spdk_bdev_io_from_ctx(void *ctx)
{
@@ -571,47 +590,26 @@ int spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_
			     char *product_name);
void spdk_bdev_part_submit_request(struct spdk_bdev_part_channel *ch, struct spdk_bdev_io *bdev_io);

#define SPDK_BDEV_MODULE_REGISTER(_name, init_fn, fini_fn, config_fn, ctx_size_fn, examine_fn)	\
	static struct spdk_bdev_module_if _name ## _if = {					\
	.name		= #_name,								\
	.module_init	= init_fn,								\
	.module_fini	= fini_fn,								\
	.config_text	= config_fn,								\
	.get_ctx_size	= ctx_size_fn,								\
	.examine	= examine_fn,								\
	};											\
	__attribute__((constructor)) static void _name ## _init(void)				\
	{											\
		spdk_bdev_module_list_add(&_name ## _if);					\
	}

#define SPDK_GET_BDEV_MODULE(name) (&name ## _if)

/*
 * Set module initialization to be asynchronous. After using this macro, the module
 * initialization has to be explicitly completed by calling spdk_bdev_module_init_done().
 * Macro used to register module for later initialization.
 */
#define SPDK_BDEV_MODULE_ASYNC_INIT(name)							\
	__attribute__((constructor)) static void name ## _async_init(void)			\
#define SPDK_BDEV_MODULE_REGISTER(_module)							\
	__attribute__((constructor)) static void						\
	SPDK_BDEV_MODULE_REGISTER_FN_NAME(__LINE__)  (void)					\
	{											\
		SPDK_GET_BDEV_MODULE(name)->action_in_progress = 1;				\
	    spdk_bdev_module_list_add(_module);							\
	}

/*
 * Set module finish to be asynchronous. After using this macro, the module
 * finishing has to be explicitly completed by calling spdk_bdev_module_fini_done().
 * This is helper macro for automatic function generation.
 *
 */
#define SPDK_BDEV_MODULE_ASYNC_FINI(name)							\
	__attribute__((constructor)) static void name ## _async_fini(void)			\
	{											\
		SPDK_GET_BDEV_MODULE(name)->async_fini = true;					\
	}
#define SPDK_BDEV_MODULE_REGISTER_FN_NAME(line) SPDK_BDEV_MODULE_REGISTER_FN_NAME_(line)

/*
 * Modules are not required to use this macro.  It allows modules to reference the module with
 * SPDK_GET_BDEV_MODULE() before it is defined by SPDK_BDEV_MODULE_REGISTER.
 *  Second helper macro for "stringize" trick to work.
 */
#define SPDK_DECLARE_BDEV_MODULE(name)								\
	static struct spdk_bdev_module_if name ## _if;
#define SPDK_BDEV_MODULE_REGISTER_FN_NAME_(line) spdk_bdev_module_if_register_ ## line

#endif /* SPDK_INTERNAL_BDEV_H */
+11 −3
Original line number Diff line number Diff line
@@ -59,8 +59,16 @@ bdev_aio_get_ctx_size(void)
	return sizeof(struct bdev_aio_task);
}

SPDK_BDEV_MODULE_REGISTER(aio, bdev_aio_initialize, NULL, bdev_aio_get_spdk_running_config,
			  bdev_aio_get_ctx_size, NULL)
static struct spdk_bdev_module_if aio_if = {
	.name		= "aio",
	.module_init	= bdev_aio_initialize,
	.module_fini	= NULL,
	.config_text	= bdev_aio_get_spdk_running_config,
	.get_ctx_size	= bdev_aio_get_ctx_size,
	.examine	= NULL,
};

SPDK_BDEV_MODULE_REGISTER(&aio_if)

static int
bdev_aio_open(struct file_disk *disk)
@@ -450,7 +458,7 @@ create_aio_disk(const char *name, const char *filename, uint32_t block_size)
		goto error_return;
	}
	fdisk->disk.product_name = "AIO disk";
	fdisk->disk.module = SPDK_GET_BDEV_MODULE(aio);
	fdisk->disk.module = &aio_if;

	fdisk->disk.need_aligned_buffer = 1;
	fdisk->disk.write_cache = 1;
+24 −0
Original line number Diff line number Diff line
@@ -2391,6 +2391,16 @@ spdk_bdev_io_get_iovec(struct spdk_bdev_io *bdev_io, struct iovec **iovp, int *i
void
spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module)
{

	if (spdk_bdev_module_list_find(bdev_module->name)) {
		fprintf(stderr, "ERROR: module '%s' already registered.\n", bdev_module->name);
		assert(false);
	}

	if (bdev_module->async_init) {
		bdev_module->action_in_progress = 1;
	}

	/*
	 * Modules with examine callbacks must be initialized first, so they are
	 *  ready to handle examine callbacks from later modules that will
@@ -2403,6 +2413,20 @@ spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module)
	}
}

struct spdk_bdev_module_if *
spdk_bdev_module_list_find(const char *name)
{
	struct spdk_bdev_module_if *bdev_module;

	TAILQ_FOREACH(bdev_module, &g_bdev_mgr.bdev_modules, tailq) {
		if (strcmp(name, bdev_module->name) == 0) {
			break;
		}
	}

	return bdev_module;
}

static void
spdk_bdev_write_zeroes_split(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{
+17 −8
Original line number Diff line number Diff line
@@ -48,8 +48,6 @@

#include "vbdev_error.h"

SPDK_DECLARE_BDEV_MODULE(error);

struct vbdev_error_info {
	bool				enabled;
	uint32_t			error_type;
@@ -70,6 +68,20 @@ struct error_channel {
static pthread_mutex_t g_vbdev_error_mutex = PTHREAD_MUTEX_INITIALIZER;
static SPDK_BDEV_PART_TAILQ g_error_disks = TAILQ_HEAD_INITIALIZER(g_error_disks);

static int vbdev_error_init(void);

static void vbdev_error_examine(struct spdk_bdev *bdev);

static struct spdk_bdev_module_if error_if = {
	.name = "error",
	.module_init = vbdev_error_init,
	.module_fini = NULL,
	.examine = vbdev_error_examine,

};

SPDK_BDEV_MODULE_REGISTER(&error_if)

static void
spdk_error_free_base(struct spdk_bdev_part_base *base)
{
@@ -235,7 +247,7 @@ spdk_vbdev_error_create(struct spdk_bdev *base_bdev)

	rc = spdk_bdev_part_base_construct(base, base_bdev,
					   spdk_vbdev_error_base_bdev_hotremove_cb,
					   SPDK_GET_BDEV_MODULE(error), &vbdev_error_fn_table,
					   &error_if, &vbdev_error_fn_table,
					   &g_error_disks, spdk_error_free_base,
					   sizeof(struct error_channel), NULL, NULL);
	if (rc) {
@@ -288,7 +300,7 @@ vbdev_error_examine(struct spdk_bdev *bdev)

	sp = spdk_conf_find_section(NULL, "BdevError");
	if (sp == NULL) {
		spdk_bdev_module_examine_done(SPDK_GET_BDEV_MODULE(error));
		spdk_bdev_module_examine_done(&error_if);
		return;
	}

@@ -313,8 +325,5 @@ vbdev_error_examine(struct spdk_bdev *bdev)
		}
	}

	spdk_bdev_module_examine_done(SPDK_GET_BDEV_MODULE(error));
	spdk_bdev_module_examine_done(&error_if);
}

SPDK_BDEV_MODULE_REGISTER(error, vbdev_error_init, NULL, NULL, NULL,
			  vbdev_error_examine)
Loading