Commit 91e7a24c authored by Ankit Kumar's avatar Ankit Kumar Committed by Konrad Sztyber
Browse files

util: Extended options for spdk_fd_group_add



Added a new API spdk_fd_group_add_ext(), which accepts extended
options for event handler i.e. spdk_event_handler_opts.
The spdk_event_handler_opts has events and fd_type. This provides
flexibility in handling different types of fds, which may require
specific operations to be performed when an event is generated.

Change-Id: I8ce36e5ed72e9ca616c9bdb38e45df6541873b1a
Signed-off-by: default avatarAnkit Kumar <ankit.kumar@samsung.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/25170


Community-CI: Community CI Samsung <spdk.community.ci.samsung@gmail.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
parent 3ab7a1f6
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -37,6 +37,11 @@ change notice to client.

Add `spdk_reduce_vol_get_info()` to get the information for the compressed volume.

### util

Added `spdk_fd_group_add_ext()` API which can receive `spdk_event_handler_opts` structure. This is
to prevent any further expansion of `spdk_fd_group_add()` API.

## v24.09

### accel
+62 −0
Original line number Diff line number Diff line
@@ -17,6 +17,33 @@
extern "C" {
#endif

#include "spdk/assert.h"

/**
 * File descriptor type. The event handler may have extra checks and can do extra
 * processing based on this.
 */
enum spdk_fd_type {
	SPDK_FD_TYPE_DEFAULT		= 0x0,
};

struct spdk_event_handler_opts {
	/**
	 * The size of spdk_event_handler_opts according to the caller of this library is used for
	 * ABI compatibility. The library uses this field to know how many fields in this structure
	 * are valid. And the library will populate any remaining fields with default values.
	 * New added fields should be put at the end of the struct.
	 */
	size_t opts_size;

	/** Event notification types */
	uint32_t events;

	/** fd type \ref spdk_fd_type */
	uint32_t fd_type;
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_event_handler_opts) == 16, "Incorrect size");

/**
 * Callback function registered for the event source file descriptor.
 *
@@ -35,6 +62,15 @@ typedef int (*spdk_fd_fn)(void *ctx);
 */
struct spdk_fd_group;

/**
 * Initialize a spdk_event_handler_opts structure to the default values.
 *
 * \param[out] opts Will be filled with default option.
 * \param opts_size Must be the size of spdk_event_handler_opts structure.
 */
void spdk_fd_group_get_default_event_handler_opts(struct spdk_event_handler_opts *opts,
		size_t opts_size);

/**
 * Initialize one fd_group.
 *
@@ -132,6 +168,25 @@ int spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd,
int spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t events,
				 spdk_fd_fn fn, void *arg,  const char *name);

/**
 * Register one event type stated in spdk_event_handler_opts agrument to the specified fgrp.
 *
 * spdk_event_handler_opts argument consists of event which is a bit mask composed by ORing
 * together enum spdk_interrupt_event_types values. It also consists of fd_type, which can be
 * used by event handler to perform extra checks during the spdk_fd_group_wait call.
 *
 * \param fgrp The fgrp registered to.
 * \param efd File descriptor of the event source.
 * \param fn Called each time there are events in event source.
 * \param arg Function argument for fn.
 * \param name Name of the event source.
 * \param opts Extended event handler option.
 *
 * \return 0 if success or -errno if failed
 */
int spdk_fd_group_add_ext(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn, void *arg,
			  const char *name, struct spdk_event_handler_opts *opts);

/*
 * \brief Register an event source with the name set to the string of the
 * callback function.
@@ -139,6 +194,13 @@ int spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t e
#define SPDK_FD_GROUP_ADD(fgrp, efd, fn, arg) \
	spdk_fd_group_add(fgrp, efd, fn, arg, #fn)

/*
 * \brief Register an event source provided in opts with the name set to the string of the
 * callback function.
 */
#define SPDK_FD_GROUP_ADD_EXT(fgrp, efd, fn, arg, opts) \
	spdk_fd_group_add_ext(fgrp, efd, fn, arg, #fn, opts)

/**
 * Unregister one event source from one fgrp.
 *
+1 −1
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

SO_VER := 10
SO_MINOR := 0
SO_MINOR := 1

C_SRCS = base64.c bit_array.c cpuset.c crc16.c crc32.c crc32c.c crc32_ieee.c crc64.c \
	 dif.c fd.c fd_group.c file.c hexlify.c iov.c math.c net.c \
+101 −3
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include "spdk/env.h"
#include "spdk/log.h"
#include "spdk/queue.h"
#include "spdk/util.h"

#include "spdk/fd_group.h"

@@ -40,6 +41,7 @@ struct event_handler {
	/* file descriptor of the interrupt event */
	int				fd;
	uint32_t			events;
	uint32_t			fd_type;
	char				name[SPDK_MAX_EVENT_NAME_LEN + 1];
};

@@ -251,6 +253,68 @@ spdk_fd_group_nest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
	return 0;
}

void
spdk_fd_group_get_default_event_handler_opts(struct spdk_event_handler_opts *opts,
		size_t opts_size)
{
	if (!opts) {
		SPDK_ERRLOG("opts should not be NULL\n");
		return;
	}

	if (!opts_size) {
		SPDK_ERRLOG("opts_size should not be zero value\n");
		return;
	}

	memset(opts, 0, opts_size);
	opts->opts_size = opts_size;

#define FIELD_OK(field) \
        offsetof(struct spdk_event_handler_opts, field) + sizeof(opts->field) <= opts_size

#define SET_FIELD(field, value) \
        if (FIELD_OK(field)) { \
                opts->field = value; \
        } \

	SET_FIELD(events, EPOLLIN);
	SET_FIELD(fd_type, SPDK_FD_TYPE_DEFAULT);

#undef FIELD_OK
#undef SET_FIELD
}

static void
event_handler_opts_copy(const struct spdk_event_handler_opts *src,
			struct spdk_event_handler_opts *dst)
{
	if (!src->opts_size) {
		SPDK_ERRLOG("opts_size should not be zero value\n");
		assert(false);
	}

#define FIELD_OK(field) \
        offsetof(struct spdk_event_handler_opts, field) + sizeof(src->field) <= src->opts_size

#define SET_FIELD(field) \
        if (FIELD_OK(field)) { \
                dst->field = src->field; \
        } \

	SET_FIELD(events);
	SET_FIELD(fd_type);

	dst->opts_size = src->opts_size;

	/* You should not remove this statement, but need to update the assert statement
	 * if you add a new field, and also add a corresponding SET_FIELD statement */
	SPDK_STATIC_ASSERT(sizeof(struct spdk_event_handler_opts) == 16, "Incorrect size");

#undef FIELD_OK
#undef SET_FIELD
}

int
spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn,
		  void *arg, const char *name)
@@ -261,9 +325,23 @@ spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn,
int
spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t events,
			     spdk_fd_fn fn, void *arg, const char *name)
{
	struct spdk_event_handler_opts opts = {};

	spdk_fd_group_get_default_event_handler_opts(&opts, sizeof(opts));
	opts.events = events;
	opts.fd_type = SPDK_FD_TYPE_DEFAULT;

	return spdk_fd_group_add_ext(fgrp, efd, fn, arg, name, &opts);
}

int
spdk_fd_group_add_ext(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn, void *arg,
		      const char *name, struct spdk_event_handler_opts *opts)
{
	struct event_handler *ehdlr = NULL;
	struct epoll_event epevent = {0};
	struct spdk_event_handler_opts eh_opts = {};
	int rc;
	int epfd;

@@ -272,6 +350,11 @@ spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t event
		return -EINVAL;
	}

	spdk_fd_group_get_default_event_handler_opts(&eh_opts, sizeof(eh_opts));
	if (opts) {
		event_handler_opts_copy(opts, &eh_opts);
	}

	/* check if there is already one function registered for this fd */
	TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) {
		if (ehdlr->fd == efd) {
@@ -289,7 +372,8 @@ spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t event
	ehdlr->fn = fn;
	ehdlr->fn_arg = arg;
	ehdlr->state = EVENT_HANDLER_STATE_WAITING;
	ehdlr->events = events;
	ehdlr->events = eh_opts.events;
	ehdlr->fd_type = eh_opts.fd_type;
	snprintf(ehdlr->name, sizeof(ehdlr->name), "%s", name);

	if (fgrp->parent) {
@@ -550,7 +634,7 @@ spdk_fd_group_wait(struct spdk_fd_group *fgrp, int timeout)
	return nfds;
}

#else
#else /* !__linux__ */

int
spdk_fd_group_get_epoll_event(struct epoll_event *event)
@@ -572,6 +656,20 @@ spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t event
	return -ENOTSUP;
}

int
spdk_fd_group_add_ext(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn, void *arg,
		      const char *name, struct spdk_event_handler_opts *opts)
{
	return -ENOTSUP;
}

void
spdk_fd_group_get_default_event_handler_opts(struct spdk_event_handler_opts *opts,
		size_t opts_size)
{
	assert(false);
}

void
spdk_fd_group_remove(struct spdk_fd_group *fgrp, int efd)
{
@@ -613,4 +711,4 @@ spdk_fd_group_nest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
	return -ENOTSUP;
}

#endif
#endif /* __linux__ */
+2 −0
Original line number Diff line number Diff line
@@ -184,6 +184,8 @@
	spdk_fd_group_wait;
	spdk_fd_group_add;
	spdk_fd_group_add_for_events;
	spdk_fd_group_add_ext;
	spdk_fd_group_get_default_event_handler_opts;
	spdk_fd_group_remove;
	spdk_fd_group_event_modify;
	spdk_fd_group_get_fd;