summaryrefslogtreecommitdiffstats
path: root/src/spdk/module/event
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdk/module/event')
-rw-r--r--src/spdk/module/event/Makefile44
-rw-r--r--src/spdk/module/event/rpc/Makefile45
-rw-r--r--src/spdk/module/event/rpc/app_rpc.c543
-rw-r--r--src/spdk/module/event/rpc/subsystem_rpc.c118
-rw-r--r--src/spdk/module/event/subsystems/Makefile61
-rw-r--r--src/spdk/module/event/subsystems/accel/Makefile45
-rw-r--r--src/spdk/module/event/subsystems/accel/accel.c71
-rw-r--r--src/spdk/module/event/subsystems/bdev/Makefile45
-rw-r--r--src/spdk/module/event/subsystems/bdev/bdev.c84
-rw-r--r--src/spdk/module/event/subsystems/iscsi/Makefile46
-rw-r--r--src/spdk/module/event/subsystems/iscsi/iscsi.c80
-rw-r--r--src/spdk/module/event/subsystems/nbd/Makefile45
-rw-r--r--src/spdk/module/event/subsystems/nbd/nbd.c72
-rw-r--r--src/spdk/module/event/subsystems/net/Makefile45
-rw-r--r--src/spdk/module/event/subsystems/net/net.c98
-rw-r--r--src/spdk/module/event/subsystems/nvmf/Makefile45
-rw-r--r--src/spdk/module/event/subsystems/nvmf/conf.c709
-rw-r--r--src/spdk/module/event/subsystems/nvmf/event_nvmf.h67
-rw-r--r--src/spdk/module/event/subsystems/nvmf/nvmf_rpc.c153
-rw-r--r--src/spdk/module/event/subsystems/nvmf/nvmf_tgt.c476
-rw-r--r--src/spdk/module/event/subsystems/scsi/Makefile45
-rw-r--r--src/spdk/module/event/subsystems/scsi/scsi.c65
-rw-r--r--src/spdk/module/event/subsystems/sock/Makefile44
-rw-r--r--src/spdk/module/event/subsystems/sock/sock.c62
-rw-r--r--src/spdk/module/event/subsystems/vhost/Makefile45
-rw-r--r--src/spdk/module/event/subsystems/vhost/vhost.c73
-rw-r--r--src/spdk/module/event/subsystems/vmd/Makefile45
-rw-r--r--src/spdk/module/event/subsystems/vmd/event_vmd.h39
-rw-r--r--src/spdk/module/event/subsystems/vmd/vmd.c132
-rw-r--r--src/spdk/module/event/subsystems/vmd/vmd_rpc.c55
30 files changed, 3497 insertions, 0 deletions
diff --git a/src/spdk/module/event/Makefile b/src/spdk/module/event/Makefile
new file mode 100644
index 000000000..f4caea64e
--- /dev/null
+++ b/src/spdk/module/event/Makefile
@@ -0,0 +1,44 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+DIRS-y = subsystems rpc
+
+.PHONY: all clean $(DIRS-y)
+
+all: $(DIRS-y)
+clean: $(DIRS-y)
+
+include $(SPDK_ROOT_DIR)/mk/spdk.subdirs.mk
diff --git a/src/spdk/module/event/rpc/Makefile b/src/spdk/module/event/rpc/Makefile
new file mode 100644
index 000000000..1e620aa14
--- /dev/null
+++ b/src/spdk/module/event/rpc/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = app_rpc.c subsystem_rpc.c
+LIBNAME = app_rpc
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/rpc/app_rpc.c b/src/spdk/module/event/rpc/app_rpc.c
new file mode 100644
index 000000000..f223c1734
--- /dev/null
+++ b/src/spdk/module/event/rpc/app_rpc.c
@@ -0,0 +1,543 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation. All rights reserved.
+ * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/event.h"
+#include "spdk/rpc.h"
+#include "spdk/string.h"
+#include "spdk/util.h"
+#include "spdk/env.h"
+#include "spdk/thread.h"
+
+#include "spdk_internal/log.h"
+#include "spdk_internal/event.h"
+#include "spdk_internal/thread.h"
+
+struct rpc_spdk_kill_instance {
+ char *sig_name;
+};
+
+static void
+free_rpc_spdk_kill_instance(struct rpc_spdk_kill_instance *req)
+{
+ free(req->sig_name);
+}
+
+static const struct spdk_json_object_decoder rpc_spdk_kill_instance_decoders[] = {
+ {"sig_name", offsetof(struct rpc_spdk_kill_instance, sig_name), spdk_json_decode_string},
+};
+
+static void
+rpc_spdk_kill_instance(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ static const struct {
+ const char *signal_string;
+ int32_t signal;
+ } signals[] = {
+ {"SIGINT", SIGINT},
+ {"SIGTERM", SIGTERM},
+ {"SIGQUIT", SIGQUIT},
+ {"SIGHUP", SIGHUP},
+ {"SIGKILL", SIGKILL},
+ {"SIGUSR1", SIGUSR1},
+ };
+ size_t i, sig_count;
+ int signal;
+ struct rpc_spdk_kill_instance req = {};
+ struct spdk_json_write_ctx *w;
+
+ if (spdk_json_decode_object(params, rpc_spdk_kill_instance_decoders,
+ SPDK_COUNTOF(rpc_spdk_kill_instance_decoders),
+ &req)) {
+ SPDK_DEBUGLOG(SPDK_LOG_APP_RPC, "spdk_json_decode_object failed\n");
+ goto invalid;
+ }
+
+ sig_count = SPDK_COUNTOF(signals);
+ signal = spdk_strtol(req.sig_name, 10);
+ for (i = 0 ; i < sig_count; i++) {
+ if (strcmp(req.sig_name, signals[i].signal_string) == 0 ||
+ signal == signals[i].signal) {
+ break;
+ }
+ }
+
+ if (i == sig_count) {
+ goto invalid;
+ }
+
+ SPDK_DEBUGLOG(SPDK_LOG_APP_RPC, "sending signal %d\n", signals[i].signal);
+ free_rpc_spdk_kill_instance(&req);
+ kill(getpid(), signals[i].signal);
+
+ w = spdk_jsonrpc_begin_result(request);
+ spdk_json_write_bool(w, true);
+ spdk_jsonrpc_end_result(request, w);
+ return;
+
+invalid:
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
+ free_rpc_spdk_kill_instance(&req);
+}
+SPDK_RPC_REGISTER("spdk_kill_instance", rpc_spdk_kill_instance, SPDK_RPC_RUNTIME)
+SPDK_RPC_REGISTER_ALIAS_DEPRECATED(spdk_kill_instance, kill_instance)
+
+
+struct rpc_framework_monitor_context_switch {
+ bool enabled;
+};
+
+static const struct spdk_json_object_decoder rpc_framework_monitor_context_switch_decoders[] = {
+ {"enabled", offsetof(struct rpc_framework_monitor_context_switch, enabled), spdk_json_decode_bool},
+};
+
+static void
+rpc_framework_monitor_context_switch(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ struct rpc_framework_monitor_context_switch req = {};
+ struct spdk_json_write_ctx *w;
+
+ if (params != NULL) {
+ if (spdk_json_decode_object(params, rpc_framework_monitor_context_switch_decoders,
+ SPDK_COUNTOF(rpc_framework_monitor_context_switch_decoders),
+ &req)) {
+ SPDK_DEBUGLOG(SPDK_LOG_APP_RPC, "spdk_json_decode_object failed\n");
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
+ return;
+ }
+
+ spdk_framework_enable_context_switch_monitor(req.enabled);
+ }
+
+ w = spdk_jsonrpc_begin_result(request);
+ spdk_json_write_object_begin(w);
+
+ spdk_json_write_named_bool(w, "enabled", spdk_framework_context_switch_monitor_enabled());
+
+ spdk_json_write_object_end(w);
+ spdk_jsonrpc_end_result(request, w);
+}
+
+SPDK_RPC_REGISTER("framework_monitor_context_switch", rpc_framework_monitor_context_switch,
+ SPDK_RPC_RUNTIME)
+SPDK_RPC_REGISTER_ALIAS_DEPRECATED(framework_monitor_context_switch, context_switch_monitor)
+
+struct rpc_get_stats_ctx {
+ struct spdk_jsonrpc_request *request;
+ struct spdk_json_write_ctx *w;
+ uint64_t now;
+};
+
+static void
+rpc_thread_get_stats_done(void *arg)
+{
+ struct rpc_get_stats_ctx *ctx = arg;
+
+ spdk_json_write_array_end(ctx->w);
+ spdk_json_write_object_end(ctx->w);
+ spdk_jsonrpc_end_result(ctx->request, ctx->w);
+
+ free(ctx);
+}
+
+static void
+rpc_thread_get_stats_for_each(struct spdk_jsonrpc_request *request, spdk_msg_fn fn)
+{
+ struct rpc_get_stats_ctx *ctx;
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (!ctx) {
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ "Memory allocation error");
+ return;
+ }
+ ctx->request = request;
+
+ ctx->w = spdk_jsonrpc_begin_result(ctx->request);
+ spdk_json_write_object_begin(ctx->w);
+ spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
+ spdk_json_write_named_array_begin(ctx->w, "threads");
+
+ spdk_for_each_thread(fn, ctx, rpc_thread_get_stats_done);
+}
+
+static void
+_rpc_thread_get_stats(void *arg)
+{
+ struct rpc_get_stats_ctx *ctx = arg;
+ struct spdk_thread *thread = spdk_get_thread();
+ struct spdk_poller *poller;
+ struct spdk_thread_stats stats;
+ uint64_t active_pollers_count = 0;
+ uint64_t timed_pollers_count = 0;
+ uint64_t paused_pollers_count = 0;
+
+ TAILQ_FOREACH(poller, &thread->active_pollers, tailq) {
+ active_pollers_count++;
+ }
+ TAILQ_FOREACH(poller, &thread->timed_pollers, tailq) {
+ timed_pollers_count++;
+ }
+ TAILQ_FOREACH(poller, &thread->paused_pollers, tailq) {
+ paused_pollers_count++;
+ }
+
+ if (0 == spdk_thread_get_stats(&stats)) {
+ spdk_json_write_object_begin(ctx->w);
+ spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
+ spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
+ spdk_json_write_named_string(ctx->w, "cpumask",
+ spdk_cpuset_fmt(spdk_thread_get_cpumask(thread)));
+ spdk_json_write_named_uint64(ctx->w, "busy", stats.busy_tsc);
+ spdk_json_write_named_uint64(ctx->w, "idle", stats.idle_tsc);
+ spdk_json_write_named_uint64(ctx->w, "active_pollers_count", active_pollers_count);
+ spdk_json_write_named_uint64(ctx->w, "timed_pollers_count", timed_pollers_count);
+ spdk_json_write_named_uint64(ctx->w, "paused_pollers_count", paused_pollers_count);
+ spdk_json_write_object_end(ctx->w);
+ }
+}
+
+static void
+rpc_thread_get_stats(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ if (params) {
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "'thread_get_stats' requires no arguments");
+ return;
+ }
+
+ rpc_thread_get_stats_for_each(request, _rpc_thread_get_stats);
+}
+
+SPDK_RPC_REGISTER("thread_get_stats", rpc_thread_get_stats, SPDK_RPC_RUNTIME)
+
+static void
+rpc_get_poller(struct spdk_poller *poller, struct spdk_json_write_ctx *w)
+{
+ spdk_json_write_object_begin(w);
+ spdk_json_write_named_string(w, "name", poller->name);
+ spdk_json_write_named_string(w, "state", spdk_poller_state_str(poller->state));
+ spdk_json_write_named_uint64(w, "run_count", poller->run_count);
+ spdk_json_write_named_uint64(w, "busy_count", poller->busy_count);
+ if (poller->period_ticks) {
+ spdk_json_write_named_uint64(w, "period_ticks", poller->period_ticks);
+ }
+ spdk_json_write_object_end(w);
+}
+
+static void
+_rpc_thread_get_pollers(void *arg)
+{
+ struct rpc_get_stats_ctx *ctx = arg;
+ struct spdk_thread *thread = spdk_get_thread();
+ struct spdk_poller *poller;
+
+ spdk_json_write_object_begin(ctx->w);
+ spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
+ spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
+
+ spdk_json_write_named_array_begin(ctx->w, "active_pollers");
+ TAILQ_FOREACH(poller, &thread->active_pollers, tailq) {
+ rpc_get_poller(poller, ctx->w);
+ }
+ spdk_json_write_array_end(ctx->w);
+
+ spdk_json_write_named_array_begin(ctx->w, "timed_pollers");
+ TAILQ_FOREACH(poller, &thread->timed_pollers, tailq) {
+ rpc_get_poller(poller, ctx->w);
+ }
+ spdk_json_write_array_end(ctx->w);
+
+ spdk_json_write_named_array_begin(ctx->w, "paused_pollers");
+ TAILQ_FOREACH(poller, &thread->paused_pollers, tailq) {
+ rpc_get_poller(poller, ctx->w);
+ }
+ spdk_json_write_array_end(ctx->w);
+
+ spdk_json_write_object_end(ctx->w);
+}
+
+static void
+rpc_thread_get_pollers(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ if (params) {
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "'thread_get_pollers' requires no arguments");
+ return;
+ }
+
+ rpc_thread_get_stats_for_each(request, _rpc_thread_get_pollers);
+}
+
+SPDK_RPC_REGISTER("thread_get_pollers", rpc_thread_get_pollers, SPDK_RPC_RUNTIME)
+
+static void
+rpc_get_io_channel(struct spdk_io_channel *ch, struct spdk_json_write_ctx *w)
+{
+ spdk_json_write_object_begin(w);
+ spdk_json_write_named_string(w, "name", spdk_io_device_get_name(ch->dev));
+ spdk_json_write_named_uint32(w, "ref", ch->ref);
+ spdk_json_write_object_end(w);
+}
+
+static void
+_rpc_thread_get_io_channels(void *arg)
+{
+ struct rpc_get_stats_ctx *ctx = arg;
+ struct spdk_thread *thread = spdk_get_thread();
+ struct spdk_io_channel *ch;
+
+ spdk_json_write_object_begin(ctx->w);
+ spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
+
+ spdk_json_write_named_array_begin(ctx->w, "io_channels");
+ TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
+ rpc_get_io_channel(ch, ctx->w);
+ }
+ spdk_json_write_array_end(ctx->w);
+
+ spdk_json_write_object_end(ctx->w);
+}
+
+static void
+rpc_thread_get_io_channels(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ if (params) {
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "'thread_get_io_channels' requires no arguments");
+ return;
+ }
+
+ rpc_thread_get_stats_for_each(request, _rpc_thread_get_io_channels);
+}
+
+SPDK_RPC_REGISTER("thread_get_io_channels", rpc_thread_get_io_channels, SPDK_RPC_RUNTIME);
+
+static void
+rpc_framework_get_reactors_done(void *arg1, void *arg2)
+{
+ struct rpc_get_stats_ctx *ctx = arg1;
+
+ spdk_json_write_array_end(ctx->w);
+ spdk_json_write_object_end(ctx->w);
+ spdk_jsonrpc_end_result(ctx->request, ctx->w);
+
+ free(ctx);
+}
+
+#define GET_DELTA(end, start) (end >= start ? end - start : 0)
+
+static void
+_rpc_framework_get_reactors(void *arg1, void *arg2)
+{
+ struct rpc_get_stats_ctx *ctx = arg1;
+ uint32_t current_core;
+ struct spdk_reactor *reactor;
+ struct spdk_lw_thread *lw_thread;
+ struct spdk_thread *thread;
+
+ current_core = spdk_env_get_current_core();
+ reactor = spdk_reactor_get(current_core);
+
+ assert(reactor != NULL);
+
+ spdk_json_write_object_begin(ctx->w);
+ spdk_json_write_named_uint32(ctx->w, "lcore", current_core);
+ spdk_json_write_named_uint64(ctx->w, "busy", reactor->busy_tsc);
+ spdk_json_write_named_uint64(ctx->w, "idle", reactor->idle_tsc);
+
+ spdk_json_write_named_array_begin(ctx->w, "lw_threads");
+ TAILQ_FOREACH(lw_thread, &reactor->threads, link) {
+ thread = spdk_thread_get_from_ctx(lw_thread);
+
+ spdk_json_write_object_begin(ctx->w);
+ spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
+ spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
+ spdk_json_write_named_string(ctx->w, "cpumask",
+ spdk_cpuset_fmt(spdk_thread_get_cpumask(thread)));
+ spdk_json_write_named_uint64(ctx->w, "elapsed",
+ GET_DELTA(ctx->now, lw_thread->tsc_start));
+ spdk_json_write_object_end(ctx->w);
+ }
+ spdk_json_write_array_end(ctx->w);
+
+ spdk_json_write_object_end(ctx->w);
+}
+
+static void
+rpc_framework_get_reactors(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ struct rpc_get_stats_ctx *ctx;
+
+ if (params) {
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "`framework_get_reactors` requires no arguments");
+ return;
+ }
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (!ctx) {
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ "Memory allocation error");
+ return;
+ }
+
+ ctx->now = spdk_get_ticks();
+ ctx->request = request;
+ ctx->w = spdk_jsonrpc_begin_result(ctx->request);
+
+ spdk_json_write_object_begin(ctx->w);
+ spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
+ spdk_json_write_named_array_begin(ctx->w, "reactors");
+
+ spdk_for_each_reactor(_rpc_framework_get_reactors, ctx, NULL,
+ rpc_framework_get_reactors_done);
+}
+
+SPDK_RPC_REGISTER("framework_get_reactors", rpc_framework_get_reactors, SPDK_RPC_RUNTIME)
+
+struct rpc_thread_set_cpumask_ctx {
+ struct spdk_jsonrpc_request *request;
+ struct spdk_cpuset cpumask;
+ int status;
+ struct spdk_thread *orig_thread;
+};
+
+static void
+rpc_thread_set_cpumask_done(void *_ctx)
+{
+ struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
+ struct spdk_json_write_ctx *w;
+
+ if (ctx->status == 0) {
+ w = spdk_jsonrpc_begin_result(ctx->request);
+ spdk_json_write_bool(w, true);
+ spdk_jsonrpc_end_result(ctx->request, w);
+ } else {
+ spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ spdk_strerror(-ctx->status));
+ }
+
+ free(ctx);
+}
+
+static void
+_rpc_thread_set_cpumask(void *_ctx)
+{
+ struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
+
+ ctx->status = spdk_thread_set_cpumask(&ctx->cpumask);
+
+ spdk_thread_send_msg(ctx->orig_thread, rpc_thread_set_cpumask_done, ctx);
+}
+
+struct rpc_thread_set_cpumask {
+ uint64_t id;
+ char *cpumask;
+};
+
+static const struct spdk_json_object_decoder rpc_thread_set_cpumask_decoders[] = {
+ {"id", offsetof(struct rpc_thread_set_cpumask, id), spdk_json_decode_uint64},
+ {"cpumask", offsetof(struct rpc_thread_set_cpumask, cpumask), spdk_json_decode_string},
+};
+
+static void
+rpc_thread_set_cpumask(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ struct rpc_thread_set_cpumask req = {};
+ struct rpc_thread_set_cpumask_ctx *ctx;
+ struct spdk_thread *thread;
+ int rc;
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (ctx == NULL) {
+ SPDK_ERRLOG("Memory allocation failed\n");
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ "Memory allocation failed");
+ return;
+ }
+
+ if (spdk_json_decode_object(params, rpc_thread_set_cpumask_decoders,
+ SPDK_COUNTOF(rpc_thread_set_cpumask_decoders),
+ &req)) {
+ SPDK_ERRLOG("spdk_json_decode_object failed\n");
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "spdk_json_decode_object failed");
+ goto err;
+ }
+
+ thread = spdk_thread_get_by_id(req.id);
+ if (thread == NULL) {
+ SPDK_ERRLOG("Thread %" PRIu64 " does not exist\n", req.id);
+ spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "Thread %" PRIu64 " does not exist", req.id);
+ goto err;
+ }
+
+ rc = spdk_app_parse_core_mask(req.cpumask, &ctx->cpumask);
+ if (rc != 0) {
+ SPDK_ERRLOG("Invalid cpumask %s\n", req.cpumask);
+ spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ "Invalid cpumask %s", req.cpumask);
+ goto err;
+ }
+
+ if (spdk_cpuset_count(&ctx->cpumask) == 0) {
+ spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ "No CPU is selected from reactor mask %s\n",
+ spdk_cpuset_fmt(spdk_app_get_core_mask()));
+ goto err;
+ }
+
+ ctx->request = request;
+ ctx->orig_thread = spdk_get_thread();
+
+ spdk_thread_send_msg(thread, _rpc_thread_set_cpumask, ctx);
+
+ free(req.cpumask);
+ return;
+
+err:
+ free(req.cpumask);
+ free(ctx);
+}
+SPDK_RPC_REGISTER("thread_set_cpumask", rpc_thread_set_cpumask, SPDK_RPC_RUNTIME)
+SPDK_LOG_REGISTER_COMPONENT("APP_RPC", SPDK_LOG_APP_RPC)
diff --git a/src/spdk/module/event/rpc/subsystem_rpc.c b/src/spdk/module/event/rpc/subsystem_rpc.c
new file mode 100644
index 000000000..293493afa
--- /dev/null
+++ b/src/spdk/module/event/rpc/subsystem_rpc.c
@@ -0,0 +1,118 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk_internal/event.h"
+#include "spdk/rpc.h"
+#include "spdk/string.h"
+#include "spdk/util.h"
+#include "spdk/env.h"
+
+static void
+rpc_framework_get_subsystems(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ struct spdk_json_write_ctx *w;
+ struct spdk_subsystem *subsystem;
+ struct spdk_subsystem_depend *deps;
+
+ if (params) {
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "'framework_get_subsystems' requires no arguments");
+ return;
+ }
+
+ w = spdk_jsonrpc_begin_result(request);
+ spdk_json_write_array_begin(w);
+ subsystem = spdk_subsystem_get_first();
+ while (subsystem != NULL) {
+ spdk_json_write_object_begin(w);
+
+ spdk_json_write_named_string(w, "subsystem", subsystem->name);
+ spdk_json_write_named_array_begin(w, "depends_on");
+ deps = spdk_subsystem_get_first_depend();
+ while (deps != NULL) {
+ if (strcmp(subsystem->name, deps->name) == 0) {
+ spdk_json_write_string(w, deps->depends_on);
+ }
+ deps = spdk_subsystem_get_next_depend(deps);
+ }
+ spdk_json_write_array_end(w);
+ spdk_json_write_object_end(w);
+ subsystem = spdk_subsystem_get_next(subsystem);
+ }
+ spdk_json_write_array_end(w);
+ spdk_jsonrpc_end_result(request, w);
+}
+
+SPDK_RPC_REGISTER("framework_get_subsystems", rpc_framework_get_subsystems, SPDK_RPC_RUNTIME)
+SPDK_RPC_REGISTER_ALIAS_DEPRECATED(framework_get_subsystems, get_subsystems)
+
+struct rpc_framework_get_config_ctx {
+ char *name;
+};
+
+static const struct spdk_json_object_decoder rpc_framework_get_config_ctx[] = {
+ {"name", offsetof(struct rpc_framework_get_config_ctx, name), spdk_json_decode_string},
+};
+
+static void
+rpc_framework_get_config(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ struct rpc_framework_get_config_ctx req = {};
+ struct spdk_json_write_ctx *w;
+ struct spdk_subsystem *subsystem;
+
+ if (spdk_json_decode_object(params, rpc_framework_get_config_ctx,
+ SPDK_COUNTOF(rpc_framework_get_config_ctx), &req)) {
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid arguments");
+ return;
+ }
+
+ subsystem = spdk_subsystem_find(req.name);
+ if (!subsystem) {
+ spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "Subsystem '%s' not found", req.name);
+ free(req.name);
+ return;
+ }
+
+ free(req.name);
+
+ w = spdk_jsonrpc_begin_result(request);
+ spdk_subsystem_config_json(w, subsystem);
+ spdk_jsonrpc_end_result(request, w);
+}
+
+SPDK_RPC_REGISTER("framework_get_config", rpc_framework_get_config, SPDK_RPC_RUNTIME)
+SPDK_RPC_REGISTER_ALIAS_DEPRECATED(framework_get_config, get_subsystem_config)
diff --git a/src/spdk/module/event/subsystems/Makefile b/src/spdk/module/event/subsystems/Makefile
new file mode 100644
index 000000000..a78985ec3
--- /dev/null
+++ b/src/spdk/module/event/subsystems/Makefile
@@ -0,0 +1,61 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+DIRS-y += bdev accel iscsi net nvmf scsi vmd sock
+
+ifeq ($(OS),Linux)
+DIRS-y += nbd
+endif
+
+DIRS-$(CONFIG_VHOST) += vhost
+
+# These dependencies are not based specifically on symbols, but rather
+# the subsystem dependency tree defined within the event subsystem C files
+# themselves. Should that tree change, these dependencies should change
+# accordingly.
+DEPDIRS-bdev := accel vmd sock
+DEPDIRS-iscsi := scsi
+DEPDIRS-nbd := bdev
+DEPDIRS-nvmf := bdev
+DEPDIRS-scsi := bdev
+DEPDIRS-vhost := scsi
+
+.PHONY: all clean $(DIRS-y)
+
+all: $(DIRS-y)
+clean: $(DIRS-y)
+
+include $(SPDK_ROOT_DIR)/mk/spdk.subdirs.mk
diff --git a/src/spdk/module/event/subsystems/accel/Makefile b/src/spdk/module/event/subsystems/accel/Makefile
new file mode 100644
index 000000000..6c8045984
--- /dev/null
+++ b/src/spdk/module/event/subsystems/accel/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = accel.c
+LIBNAME = event_accel
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/accel/accel.c b/src/spdk/module/event/subsystems/accel/accel.c
new file mode 100644
index 000000000..957a49686
--- /dev/null
+++ b/src/spdk/module/event/subsystems/accel/accel.c
@@ -0,0 +1,71 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/accel_engine.h"
+
+#include "spdk_internal/event.h"
+#include "spdk/env.h"
+
+static void
+accel_engine_subsystem_initialize(void)
+{
+ int rc;
+
+ rc = spdk_accel_engine_initialize();
+
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+accel_engine_subsystem_finish_done(void *cb_arg)
+{
+ spdk_subsystem_fini_next();
+}
+
+static void
+accel_engine_subsystem_finish(void)
+{
+ spdk_accel_engine_finish(accel_engine_subsystem_finish_done, NULL);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_accel = {
+ .name = "accel",
+ .init = accel_engine_subsystem_initialize,
+ .fini = accel_engine_subsystem_finish,
+ .config = spdk_accel_engine_config_text,
+ .write_config_json = spdk_accel_write_config_json,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_accel);
diff --git a/src/spdk/module/event/subsystems/bdev/Makefile b/src/spdk/module/event/subsystems/bdev/Makefile
new file mode 100644
index 000000000..4503e327a
--- /dev/null
+++ b/src/spdk/module/event/subsystems/bdev/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = bdev.c
+LIBNAME = event_bdev
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/bdev/bdev.c b/src/spdk/module/event/subsystems/bdev/bdev.c
new file mode 100644
index 000000000..5776cf273
--- /dev/null
+++ b/src/spdk/module/event/subsystems/bdev/bdev.c
@@ -0,0 +1,84 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/bdev.h"
+#include "spdk/env.h"
+#include "spdk/thread.h"
+
+#include "spdk_internal/event.h"
+#include "spdk/env.h"
+
+static void
+bdev_initialize_complete(void *cb_arg, int rc)
+{
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+bdev_subsystem_initialize(void)
+{
+ spdk_bdev_initialize(bdev_initialize_complete, NULL);
+}
+
+static void
+bdev_subsystem_finish_done(void *cb_arg)
+{
+ spdk_subsystem_fini_next();
+}
+
+static void
+bdev_subsystem_finish(void)
+{
+ spdk_bdev_finish(bdev_subsystem_finish_done, NULL);
+}
+
+static void
+bdev_subsystem_config_json(struct spdk_json_write_ctx *w)
+{
+ spdk_bdev_subsystem_config_json(w);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_bdev = {
+ .name = "bdev",
+ .init = bdev_subsystem_initialize,
+ .fini = bdev_subsystem_finish,
+ .config = spdk_bdev_config_text,
+ .write_config_json = bdev_subsystem_config_json,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_bdev);
+SPDK_SUBSYSTEM_DEPEND(bdev, accel)
+SPDK_SUBSYSTEM_DEPEND(bdev, vmd)
+SPDK_SUBSYSTEM_DEPEND(bdev, sock)
diff --git a/src/spdk/module/event/subsystems/iscsi/Makefile b/src/spdk/module/event/subsystems/iscsi/Makefile
new file mode 100644
index 000000000..f418f8bd9
--- /dev/null
+++ b/src/spdk/module/event/subsystems/iscsi/Makefile
@@ -0,0 +1,46 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+CFLAGS += -I$(SPDK_ROOT_DIR)/lib
+C_SRCS = iscsi.c
+LIBNAME = event_iscsi
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/iscsi/iscsi.c b/src/spdk/module/event/subsystems/iscsi/iscsi.c
new file mode 100644
index 000000000..cecefd0a5
--- /dev/null
+++ b/src/spdk/module/event/subsystems/iscsi/iscsi.c
@@ -0,0 +1,80 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "iscsi/iscsi.h"
+
+#include "spdk_internal/event.h"
+
+static void
+iscsi_subsystem_init_complete(void *cb_arg, int rc)
+{
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+iscsi_subsystem_init(void)
+{
+ spdk_iscsi_init(iscsi_subsystem_init_complete, NULL);
+}
+
+static void
+iscsi_subsystem_fini_done(void *arg)
+{
+ spdk_subsystem_fini_next();
+}
+
+static void
+iscsi_subsystem_fini(void)
+{
+ spdk_iscsi_fini(iscsi_subsystem_fini_done, NULL);
+}
+
+static void
+iscsi_subsystem_config_json(struct spdk_json_write_ctx *w)
+{
+ spdk_iscsi_config_json(w);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_iscsi = {
+ .name = "iscsi",
+ .init = iscsi_subsystem_init,
+ .fini = iscsi_subsystem_fini,
+ .config = spdk_iscsi_config_text,
+ .write_config_json = iscsi_subsystem_config_json,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_iscsi);
+SPDK_SUBSYSTEM_DEPEND(iscsi, scsi)
+SPDK_SUBSYSTEM_DEPEND(iscsi, sock)
diff --git a/src/spdk/module/event/subsystems/nbd/Makefile b/src/spdk/module/event/subsystems/nbd/Makefile
new file mode 100644
index 000000000..6991ce76d
--- /dev/null
+++ b/src/spdk/module/event/subsystems/nbd/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = nbd.c
+LIBNAME = event_nbd
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/nbd/nbd.c b/src/spdk/module/event/subsystems/nbd/nbd.c
new file mode 100644
index 000000000..dc1c3cfa3
--- /dev/null
+++ b/src/spdk/module/event/subsystems/nbd/nbd.c
@@ -0,0 +1,72 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/nbd.h"
+
+#include "spdk_internal/event.h"
+
+static void
+nbd_subsystem_init(void)
+{
+ int rc;
+
+ rc = spdk_nbd_init();
+
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+nbd_subsystem_fini(void)
+{
+ spdk_nbd_fini();
+ spdk_subsystem_fini_next();
+}
+
+static void
+nbd_subsystem_write_config_json(struct spdk_json_write_ctx *w)
+{
+ spdk_nbd_write_config_json(w);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_nbd = {
+ .name = "nbd",
+ .init = nbd_subsystem_init,
+ .fini = nbd_subsystem_fini,
+ .config = NULL,
+ .write_config_json = nbd_subsystem_write_config_json,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_nbd);
+SPDK_SUBSYSTEM_DEPEND(nbd, bdev)
diff --git a/src/spdk/module/event/subsystems/net/Makefile b/src/spdk/module/event/subsystems/net/Makefile
new file mode 100644
index 000000000..b90cffae4
--- /dev/null
+++ b/src/spdk/module/event/subsystems/net/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = net.c
+LIBNAME = event_net
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/net/net.c b/src/spdk/module/event/subsystems/net/net.c
new file mode 100644
index 000000000..76694238a
--- /dev/null
+++ b/src/spdk/module/event/subsystems/net/net.c
@@ -0,0 +1,98 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/net.h"
+
+#include "spdk_internal/event.h"
+
+static void
+interface_subsystem_init(void)
+{
+ int rc;
+
+ rc = spdk_interface_init();
+
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+interface_subsystem_destroy(void)
+{
+ spdk_interface_destroy();
+ spdk_subsystem_fini_next();
+}
+
+static struct spdk_subsystem g_spdk_subsystem_interface = {
+ .name = "interface",
+ .init = interface_subsystem_init,
+ .fini = interface_subsystem_destroy,
+ .config = NULL,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_interface);
+
+static void
+net_start_complete(void *cb_arg, int rc)
+{
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+net_subsystem_start(void)
+{
+ spdk_net_framework_start(net_start_complete, NULL);
+}
+
+static void
+net_fini_done(void *cb_arg)
+{
+ spdk_subsystem_fini_next();
+}
+
+static void
+net_subsystem_fini(void)
+{
+ spdk_net_framework_fini(net_fini_done, NULL);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_net_framework = {
+ .name = "net_framework",
+ .init = net_subsystem_start,
+ .fini = net_subsystem_fini,
+ .config = NULL,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_net_framework);
+SPDK_SUBSYSTEM_DEPEND(net_framework, interface)
diff --git a/src/spdk/module/event/subsystems/nvmf/Makefile b/src/spdk/module/event/subsystems/nvmf/Makefile
new file mode 100644
index 000000000..b51962d2f
--- /dev/null
+++ b/src/spdk/module/event/subsystems/nvmf/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = conf.c nvmf_rpc.c nvmf_tgt.c
+LIBNAME = event_nvmf
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/nvmf/conf.c b/src/spdk/module/event/subsystems/nvmf/conf.c
new file mode 100644
index 000000000..b92a92acc
--- /dev/null
+++ b/src/spdk/module/event/subsystems/nvmf/conf.c
@@ -0,0 +1,709 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation. All rights reserved.
+ * Copyright (c) 2018 Mellanox Technologies LTD. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "event_nvmf.h"
+
+#include "spdk/conf.h"
+#include "spdk/log.h"
+#include "spdk/bdev.h"
+#include "spdk/nvme.h"
+#include "spdk/nvmf.h"
+#include "spdk/string.h"
+#include "spdk/util.h"
+
+#define SPDK_NVMF_MAX_NAMESPACES (1 << 14)
+
+struct spdk_nvmf_tgt_conf *g_spdk_nvmf_tgt_conf = NULL;
+uint32_t g_spdk_nvmf_tgt_max_subsystems = 0;
+
+static int
+nvmf_add_discovery_subsystem(void)
+{
+ struct spdk_nvmf_subsystem *subsystem;
+
+ subsystem = spdk_nvmf_subsystem_create(g_spdk_nvmf_tgt, SPDK_NVMF_DISCOVERY_NQN,
+ SPDK_NVMF_SUBTYPE_DISCOVERY, 0);
+ if (subsystem == NULL) {
+ SPDK_ERRLOG("Failed creating discovery nvmf library subsystem\n");
+ return -1;
+ }
+
+ spdk_nvmf_subsystem_set_allow_any_host(subsystem, true);
+
+ return 0;
+}
+
+static void
+nvmf_read_config_file_tgt_max_subsystems(struct spdk_conf_section *sp,
+ int *deprecated_values)
+{
+ int tgt_max_subsystems;
+ int deprecated;
+
+ tgt_max_subsystems = spdk_conf_section_get_intval(sp, "MaxSubsystems");
+ if (tgt_max_subsystems >= 0) {
+ g_spdk_nvmf_tgt_max_subsystems = tgt_max_subsystems;
+ }
+
+ deprecated = spdk_conf_section_get_intval(sp, "MaxQueueDepth");
+ if (deprecated >= 0) {
+ *deprecated_values = -1;
+ }
+
+ deprecated = spdk_conf_section_get_intval(sp, "MaxQueuesPerSession");
+ if (deprecated >= 0) {
+ *deprecated_values = -1;
+ }
+
+ deprecated = spdk_conf_section_get_intval(sp, "InCapsuleDataSize");
+ if (deprecated >= 0) {
+ *deprecated_values = -1;
+ }
+
+ deprecated = spdk_conf_section_get_intval(sp, "MaxIOSize");
+ if (deprecated >= 0) {
+ *deprecated_values = -1;
+ }
+
+ deprecated = spdk_conf_section_get_intval(sp, "IOUnitSize");
+ if (deprecated >= 0) {
+ *deprecated_values = -1;
+ }
+}
+
+static int
+nvmf_read_config_file_tgt_conf(struct spdk_conf_section *sp,
+ struct spdk_nvmf_tgt_conf *conf)
+{
+ int acceptor_poll_rate;
+ const char *conn_scheduler;
+ int rc = 0;
+
+ acceptor_poll_rate = spdk_conf_section_get_intval(sp, "AcceptorPollRate");
+ if (acceptor_poll_rate >= 0) {
+ conf->acceptor_poll_rate = acceptor_poll_rate;
+ }
+
+ conn_scheduler = spdk_conf_section_get_val(sp, "ConnectionScheduler");
+
+ if (conn_scheduler) {
+ SPDK_NOTICELOG("The ConnectionScheduler option is no longer valid. Ignoring it.\n");
+ }
+
+ conf->admin_passthru.identify_ctrlr = spdk_conf_section_get_boolval(sp,
+ "AdminCmdPassthruIdentifyCtrlr", false);
+
+ return rc;
+}
+
+static int
+nvmf_parse_tgt_max_subsystems(void)
+{
+ struct spdk_conf_section *sp;
+ int deprecated_values = 0;
+
+ sp = spdk_conf_find_section(NULL, "Nvmf");
+ if (sp != NULL) {
+ nvmf_read_config_file_tgt_max_subsystems(sp, &deprecated_values);
+ }
+
+ return deprecated_values;
+}
+
+static struct spdk_nvmf_tgt_conf *
+nvmf_parse_tgt_conf(void)
+{
+ struct spdk_nvmf_tgt_conf *conf;
+ struct spdk_conf_section *sp;
+ int rc;
+
+ conf = calloc(1, sizeof(*conf));
+ if (!conf) {
+ SPDK_ERRLOG("calloc() failed for target conf\n");
+ return NULL;
+ }
+
+ conf->acceptor_poll_rate = ACCEPT_TIMEOUT_US;
+ conf->admin_passthru.identify_ctrlr = false;
+
+ sp = spdk_conf_find_section(NULL, "Nvmf");
+ if (sp != NULL) {
+ rc = nvmf_read_config_file_tgt_conf(sp, conf);
+ if (rc) {
+ free(conf);
+ return NULL;
+ }
+ }
+
+ return conf;
+}
+
+static int
+nvmf_parse_nvmf_tgt(void)
+{
+ int rc;
+ int using_deprecated_options;
+ struct spdk_nvmf_target_opts opts = {
+ .name = "nvmf_tgt",
+ .max_subsystems = 0
+ };
+
+ if (!g_spdk_nvmf_tgt_max_subsystems) {
+ using_deprecated_options = nvmf_parse_tgt_max_subsystems();
+ if (using_deprecated_options < 0) {
+ SPDK_ERRLOG("Deprecated options detected for the NVMe-oF target.\n"
+ "The following options are no longer controlled by the target\n"
+ "and should be set in the transport on a per-transport basis:\n"
+ "MaxQueueDepth, MaxQueuesPerSession, InCapsuleDataSize, MaxIOSize, IOUnitSize\n"
+ "This can be accomplished by setting the options through the create_nvmf_transport RPC.\n"
+ "You may also continue to configure these options in the conf file under each transport.");
+ }
+ }
+
+ if (!g_spdk_nvmf_tgt_conf) {
+ g_spdk_nvmf_tgt_conf = nvmf_parse_tgt_conf();
+ if (!g_spdk_nvmf_tgt_conf) {
+ SPDK_ERRLOG("nvmf_parse_tgt_conf() failed\n");
+ return -1;
+ }
+ }
+
+ opts.max_subsystems = g_spdk_nvmf_tgt_max_subsystems;
+ g_spdk_nvmf_tgt = spdk_nvmf_tgt_create(&opts);
+
+ g_spdk_nvmf_tgt_max_subsystems = 0;
+
+ if (!g_spdk_nvmf_tgt) {
+ SPDK_ERRLOG("spdk_nvmf_tgt_create() failed\n");
+ return -1;
+ }
+
+ rc = nvmf_add_discovery_subsystem();
+ if (rc != 0) {
+ SPDK_ERRLOG("nvmf_add_discovery_subsystem failed\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+nvmf_tgt_parse_listen_ip_addr(char *address,
+ struct spdk_nvme_transport_id *trid)
+{
+ char *host;
+ char *port;
+
+ if (spdk_parse_ip_addr(address, &host, &port) < 0) {
+ SPDK_ERRLOG("Unable to parse listen address '%s'\n", address);
+ return -1;
+ }
+
+ if (strchr(host, ':')) {
+ trid->adrfam = SPDK_NVMF_ADRFAM_IPV6;
+ } else {
+ trid->adrfam = SPDK_NVMF_ADRFAM_IPV4;
+ }
+
+ snprintf(trid->traddr, sizeof(trid->traddr), "%s", host);
+ if (port) {
+ snprintf(trid->trsvcid, sizeof(trid->trsvcid), "%s", port);
+ }
+
+ return 0;
+}
+
+static int
+nvmf_tgt_parse_listen_fc_addr(const char *address,
+ struct spdk_nvme_transport_id *trid)
+{
+ /* transport address format and requirements,
+ * "nn-0xWWNN:pn-0xWWPN" - size equals 43 bytes and is required to
+ * contain 'nn' and 'pn'.
+ */
+ if (strlen(address) != 43 || strncmp(address, "nn-0x", 5) ||
+ strncmp(&address[21], ":pn-0x", 6)) {
+ SPDK_ERRLOG("Unable to parse fc address '%s'\n", address);
+ return -1;
+ }
+
+ trid->adrfam = SPDK_NVMF_ADRFAM_FC;
+ snprintf(trid->trsvcid, sizeof(trid->trsvcid), "none");
+ snprintf(trid->traddr, sizeof(trid->traddr), "%s", address);
+
+ return 0;
+}
+
+static void
+nvmf_tgt_listen_done(void *cb_arg, int status)
+{
+ /* TODO: Config parsing should wait for this operation to finish. */
+
+ if (status) {
+ SPDK_ERRLOG("Failed to listen on transport address\n");
+ }
+}
+
+static int
+nvmf_parse_subsystem(struct spdk_conf_section *sp)
+{
+ const char *nqn, *mode;
+ size_t i;
+ int ret = -1;
+ int lcore;
+ bool allow_any_host;
+ bool allow_any_listener = true;
+ const char *sn;
+ const char *mn;
+ struct spdk_nvmf_subsystem *subsystem;
+ int num_ns;
+
+ nqn = spdk_conf_section_get_val(sp, "NQN");
+ if (nqn == NULL) {
+ SPDK_ERRLOG("Subsystem missing NQN\n");
+ return -1;
+ }
+
+ mode = spdk_conf_section_get_val(sp, "Mode");
+ lcore = spdk_conf_section_get_intval(sp, "Core");
+ num_ns = spdk_conf_section_get_intval(sp, "MaxNamespaces");
+
+ if (num_ns < 1) {
+ num_ns = 0;
+ } else if (num_ns > SPDK_NVMF_MAX_NAMESPACES) {
+ num_ns = SPDK_NVMF_MAX_NAMESPACES;
+ }
+
+ /* Mode is no longer a valid parameter, but print out a nice
+ * message if it exists to inform users.
+ */
+ if (mode) {
+ SPDK_NOTICELOG("Mode present in the [Subsystem] section of the config file.\n"
+ "Mode was removed as a valid parameter.\n");
+ if (strcasecmp(mode, "Virtual") == 0) {
+ SPDK_NOTICELOG("Your mode value is 'Virtual' which is now the only possible mode.\n"
+ "Your configuration file will work as expected.\n");
+ } else {
+ SPDK_NOTICELOG("Please remove Mode from your configuration file.\n");
+ return -1;
+ }
+ }
+
+ /* Core is no longer a valid parameter, but print out a nice
+ * message if it exists to inform users.
+ */
+ if (lcore >= 0) {
+ SPDK_NOTICELOG("Core present in the [Subsystem] section of the config file.\n"
+ "Core was removed as an option. Subsystems can now run on all available cores.\n");
+ SPDK_NOTICELOG("Please remove Core from your configuration file. Ignoring it and continuing.\n");
+ }
+
+ sn = spdk_conf_section_get_val(sp, "SN");
+ if (sn == NULL) {
+ SPDK_ERRLOG("Subsystem %s: missing serial number\n", nqn);
+ return -1;
+ }
+
+ subsystem = spdk_nvmf_subsystem_create(g_spdk_nvmf_tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, num_ns);
+ if (subsystem == NULL) {
+ goto done;
+ }
+
+ if (spdk_nvmf_subsystem_set_sn(subsystem, sn)) {
+ SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", nqn, sn);
+ spdk_nvmf_subsystem_destroy(subsystem);
+ subsystem = NULL;
+ goto done;
+ }
+
+ mn = spdk_conf_section_get_val(sp, "MN");
+ if (mn == NULL) {
+ SPDK_NOTICELOG(
+ "Subsystem %s: missing model number, will use default\n",
+ nqn);
+ }
+
+ if (mn != NULL) {
+ if (spdk_nvmf_subsystem_set_mn(subsystem, mn)) {
+ SPDK_ERRLOG("Subsystem %s: invalid model number '%s'\n", nqn, mn);
+ spdk_nvmf_subsystem_destroy(subsystem);
+ subsystem = NULL;
+ goto done;
+ }
+ }
+
+ for (i = 0; ; i++) {
+ struct spdk_nvmf_ns_opts ns_opts;
+ struct spdk_bdev *bdev;
+ const char *bdev_name;
+ const char *uuid_str;
+ char *nsid_str;
+
+ bdev_name = spdk_conf_section_get_nmval(sp, "Namespace", i, 0);
+ if (!bdev_name) {
+ break;
+ }
+
+ bdev = spdk_bdev_get_by_name(bdev_name);
+ if (bdev == NULL) {
+ SPDK_ERRLOG("Could not find namespace bdev '%s'\n", bdev_name);
+ spdk_nvmf_subsystem_destroy(subsystem);
+ subsystem = NULL;
+ goto done;
+ }
+
+ spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
+
+ nsid_str = spdk_conf_section_get_nmval(sp, "Namespace", i, 1);
+ if (nsid_str) {
+ char *end;
+ unsigned long nsid_ul = strtoul(nsid_str, &end, 0);
+
+ if (*end != '\0' || nsid_ul == 0 || nsid_ul >= UINT32_MAX) {
+ SPDK_ERRLOG("Invalid NSID %s\n", nsid_str);
+ spdk_nvmf_subsystem_destroy(subsystem);
+ subsystem = NULL;
+ goto done;
+ }
+
+ ns_opts.nsid = (uint32_t)nsid_ul;
+ }
+
+ uuid_str = spdk_conf_section_get_nmval(sp, "Namespace", i, 2);
+ if (uuid_str) {
+ if (spdk_uuid_parse(&ns_opts.uuid, uuid_str)) {
+ SPDK_ERRLOG("Invalid UUID %s\n", uuid_str);
+ spdk_nvmf_subsystem_destroy(subsystem);
+ subsystem = NULL;
+ goto done;
+ }
+ }
+
+ if (spdk_nvmf_subsystem_add_ns(subsystem, bdev, &ns_opts, sizeof(ns_opts), NULL) == 0) {
+ SPDK_ERRLOG("Unable to add namespace\n");
+ spdk_nvmf_subsystem_destroy(subsystem);
+ subsystem = NULL;
+ goto done;
+ }
+ }
+
+ /* Parse Listen sections */
+ for (i = 0; ; i++) {
+ struct spdk_nvme_transport_id trid = {{0}};
+ const char *transport;
+ const char *address;
+ char *address_dup;
+
+ transport = spdk_conf_section_get_nmval(sp, "Listen", i, 0);
+ if (!transport) {
+ break;
+ }
+
+ if (spdk_nvme_transport_id_populate_trstring(&trid, transport)) {
+ SPDK_ERRLOG("Invalid listen address transport type '%s'\n", transport);
+ continue;
+ }
+
+ if (spdk_nvme_transport_id_parse_trtype(&trid.trtype, transport)) {
+ SPDK_ERRLOG("Invalid listen address transport type '%s'\n", transport);
+ continue;
+ }
+
+ address = spdk_conf_section_get_nmval(sp, "Listen", i, 1);
+ if (!address) {
+ break;
+ }
+
+ address_dup = strdup(address);
+ if (!address_dup) {
+ break;
+ }
+
+ if (trid.trtype == SPDK_NVME_TRANSPORT_RDMA ||
+ trid.trtype == SPDK_NVME_TRANSPORT_TCP) {
+ ret = nvmf_tgt_parse_listen_ip_addr(address_dup, &trid);
+ } else if (trid.trtype == SPDK_NVME_TRANSPORT_FC) {
+ ret = nvmf_tgt_parse_listen_fc_addr(address_dup, &trid);
+ }
+
+ free(address_dup);
+
+ if (ret) {
+ continue;
+ }
+
+ if (spdk_nvmf_tgt_listen(g_spdk_nvmf_tgt, &trid)) {
+ SPDK_ERRLOG("Failed to listen on transport address\n");
+ }
+
+ spdk_nvmf_subsystem_add_listener(subsystem, &trid, nvmf_tgt_listen_done, NULL);
+ allow_any_listener = false;
+ }
+
+ spdk_nvmf_subsystem_allow_any_listener(subsystem, allow_any_listener);
+
+ /* Parse Host sections */
+ for (i = 0; ; i++) {
+ const char *host = spdk_conf_section_get_nval(sp, "Host", i);
+
+ if (!host) {
+ break;
+ }
+
+ spdk_nvmf_subsystem_add_host(subsystem, host);
+ }
+
+ allow_any_host = spdk_conf_section_get_boolval(sp, "AllowAnyHost", false);
+ spdk_nvmf_subsystem_set_allow_any_host(subsystem, allow_any_host);
+
+done:
+ return (subsystem != NULL) ? 0 : -1;
+}
+
+static int
+nvmf_parse_subsystems(void)
+{
+ int rc = 0;
+ struct spdk_conf_section *sp;
+
+ sp = spdk_conf_first_section(NULL);
+ while (sp != NULL) {
+ if (spdk_conf_section_match_prefix(sp, "Subsystem")) {
+ rc = nvmf_parse_subsystem(sp);
+ if (rc < 0) {
+ return -1;
+ }
+ }
+ sp = spdk_conf_next_section(sp);
+ }
+ return 0;
+}
+
+struct nvmf_parse_transport_ctx {
+ struct spdk_conf_section *sp;
+ nvmf_parse_conf_done_fn cb_fn;
+};
+
+static void nvmf_parse_transport(struct nvmf_parse_transport_ctx *ctx);
+
+static void
+nvmf_tgt_add_transport_done(void *cb_arg, int status)
+{
+ struct nvmf_parse_transport_ctx *ctx = cb_arg;
+ int rc;
+
+ if (status < 0) {
+ SPDK_ERRLOG("Add transport to target failed (%d).\n", status);
+ ctx->cb_fn(status);
+ free(ctx);
+ return;
+ }
+
+ /* find next transport */
+ ctx->sp = spdk_conf_next_section(ctx->sp);
+ while (ctx->sp) {
+ if (spdk_conf_section_match_prefix(ctx->sp, "Transport")) {
+ nvmf_parse_transport(ctx);
+ return;
+ }
+ ctx->sp = spdk_conf_next_section(ctx->sp);
+ }
+
+ /* done with transports, parse Subsystem sections */
+ rc = nvmf_parse_subsystems();
+
+ ctx->cb_fn(rc);
+ free(ctx);
+}
+
+static void
+nvmf_parse_transport(struct nvmf_parse_transport_ctx *ctx)
+{
+ const char *type;
+ struct spdk_nvmf_transport_opts opts = { 0 };
+ enum spdk_nvme_transport_type trtype;
+ struct spdk_nvmf_transport *transport;
+ bool bval;
+ int val;
+
+ type = spdk_conf_section_get_val(ctx->sp, "Type");
+ if (type == NULL) {
+ SPDK_ERRLOG("Transport missing Type\n");
+ ctx->cb_fn(-1);
+ free(ctx);
+ return;
+ }
+
+ spdk_nvme_transport_id_parse_trtype(&trtype, type);
+
+ if (spdk_nvmf_tgt_get_transport(g_spdk_nvmf_tgt, type)) {
+ SPDK_ERRLOG("Duplicate transport type '%s'\n", type);
+ ctx->cb_fn(-1);
+ free(ctx);
+ return;
+ }
+
+ if (!spdk_nvmf_transport_opts_init(type, &opts)) {
+ ctx->cb_fn(-1);
+ free(ctx);
+ return;
+ }
+
+ val = spdk_conf_section_get_intval(ctx->sp, "MaxQueueDepth");
+ if (val >= 0) {
+ opts.max_queue_depth = val;
+ }
+ val = spdk_conf_section_get_intval(ctx->sp, "MaxQueuesPerSession");
+ if (val >= 0) {
+ opts.max_qpairs_per_ctrlr = val;
+ }
+ val = spdk_conf_section_get_intval(ctx->sp, "InCapsuleDataSize");
+ if (val >= 0) {
+ opts.in_capsule_data_size = val;
+ }
+ val = spdk_conf_section_get_intval(ctx->sp, "MaxIOSize");
+ if (val >= 0) {
+ opts.max_io_size = val;
+ }
+ val = spdk_conf_section_get_intval(ctx->sp, "IOUnitSize");
+ if (val >= 0) {
+ opts.io_unit_size = val;
+ }
+ val = spdk_conf_section_get_intval(ctx->sp, "MaxAQDepth");
+ if (val >= 0) {
+ opts.max_aq_depth = val;
+ }
+ val = spdk_conf_section_get_intval(ctx->sp, "NumSharedBuffers");
+ if (val >= 0) {
+ opts.num_shared_buffers = val;
+ }
+ val = spdk_conf_section_get_intval(ctx->sp, "BufCacheSize");
+ if (val >= 0) {
+ opts.buf_cache_size = val;
+ }
+
+ if (trtype == SPDK_NVME_TRANSPORT_RDMA) {
+ val = spdk_conf_section_get_intval(ctx->sp, "MaxSRQDepth");
+ if (val >= 0) {
+ opts.max_srq_depth = val;
+ }
+ bval = spdk_conf_section_get_boolval(ctx->sp, "NoSRQ", false);
+ opts.no_srq = bval;
+ }
+
+ if (trtype == SPDK_NVME_TRANSPORT_TCP) {
+ bval = spdk_conf_section_get_boolval(ctx->sp, "C2HSuccess", true);
+ opts.c2h_success = bval;
+
+ val = spdk_conf_section_get_intval(ctx->sp, "SockPriority");
+ if (val >= 0) {
+ opts.sock_priority = val;
+ }
+ }
+
+ bval = spdk_conf_section_get_boolval(ctx->sp, "DifInsertOrStrip", false);
+ opts.dif_insert_or_strip = bval;
+
+ transport = spdk_nvmf_transport_create(type, &opts);
+ if (transport) {
+ spdk_nvmf_tgt_add_transport(g_spdk_nvmf_tgt, transport, nvmf_tgt_add_transport_done, ctx);
+ } else {
+ goto error_out;
+ }
+
+ return;
+
+error_out:
+ ctx->cb_fn(-1);
+ free(ctx);
+ return;
+}
+
+static int
+nvmf_parse_transports(nvmf_parse_conf_done_fn cb_fn)
+{
+ struct nvmf_parse_transport_ctx *ctx;
+
+ ctx = calloc(1, sizeof(struct nvmf_parse_transport_ctx));
+ if (!ctx) {
+ SPDK_ERRLOG("Failed alloc of context memory for parse transports\n");
+ return -ENOMEM;
+ }
+
+ ctx->cb_fn = cb_fn;
+ ctx->sp = spdk_conf_first_section(NULL);
+ if (ctx->sp == NULL) {
+ free(ctx);
+ cb_fn(0);
+
+ return 0;
+ }
+
+ while (ctx->sp != NULL) {
+ if (spdk_conf_section_match_prefix(ctx->sp, "Transport")) {
+ nvmf_parse_transport(ctx);
+ return 0;
+ }
+ ctx->sp = spdk_conf_next_section(ctx->sp);
+ }
+
+ /* if we get here, there are no transports defined in conf file */
+ free(ctx);
+ cb_fn(0);
+ return 0;
+}
+
+int
+nvmf_parse_conf(nvmf_parse_conf_done_fn cb_fn)
+{
+ int rc;
+
+ if (cb_fn == NULL) {
+ SPDK_ERRLOG("Callback function is NULL\n");
+ return -1;
+ }
+
+ /* NVMf section */
+ rc = nvmf_parse_nvmf_tgt();
+ if (rc < 0) {
+ return rc;
+ }
+
+ /* Transport sections */
+ rc = nvmf_parse_transports(cb_fn);
+ if (rc < 0) {
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/src/spdk/module/event/subsystems/nvmf/event_nvmf.h b/src/spdk/module/event/subsystems/nvmf/event_nvmf.h
new file mode 100644
index 000000000..58d3f713b
--- /dev/null
+++ b/src/spdk/module/event/subsystems/nvmf/event_nvmf.h
@@ -0,0 +1,67 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NVMF_TGT_H
+#define NVMF_TGT_H
+
+#include "spdk/stdinc.h"
+
+#include "spdk/nvmf.h"
+#include "spdk/queue.h"
+
+#include "spdk_internal/event.h"
+#include "spdk_internal/log.h"
+
+#define ACCEPT_TIMEOUT_US 10000 /* 10ms */
+
+struct spdk_nvmf_admin_passthru_conf {
+ bool identify_ctrlr;
+};
+
+struct spdk_nvmf_tgt_conf {
+ uint32_t acceptor_poll_rate;
+ uint32_t conn_sched; /* Deprecated. */
+ struct spdk_nvmf_admin_passthru_conf admin_passthru;
+};
+
+extern struct spdk_nvmf_tgt_conf *g_spdk_nvmf_tgt_conf;
+
+extern uint32_t g_spdk_nvmf_tgt_max_subsystems;
+
+extern struct spdk_nvmf_tgt *g_spdk_nvmf_tgt;
+
+typedef void (*nvmf_parse_conf_done_fn)(int status);
+
+int nvmf_parse_conf(nvmf_parse_conf_done_fn cb_fn);
+
+#endif
diff --git a/src/spdk/module/event/subsystems/nvmf/nvmf_rpc.c b/src/spdk/module/event/subsystems/nvmf/nvmf_rpc.c
new file mode 100644
index 000000000..b16ec6686
--- /dev/null
+++ b/src/spdk/module/event/subsystems/nvmf/nvmf_rpc.c
@@ -0,0 +1,153 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation. All rights reserved.
+ * Copyright (c) 2018-2019 Mellanox Technologies LTD. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "event_nvmf.h"
+
+#include "spdk/rpc.h"
+#include "spdk/util.h"
+
+static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_opts_decoder[] = {
+ {"max_subsystems", 0, spdk_json_decode_uint32, true}
+};
+
+static void
+rpc_nvmf_set_max_subsystems(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ struct spdk_json_write_ctx *w;
+ uint32_t max_subsystems = 0;
+
+ if (g_spdk_nvmf_tgt_max_subsystems != 0) {
+ SPDK_ERRLOG("this RPC must not be called more than once.\n");
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ "Must not call more than once");
+ return;
+ }
+
+ if (params != NULL) {
+ if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_opts_decoder,
+ SPDK_COUNTOF(nvmf_rpc_subsystem_tgt_opts_decoder), &max_subsystems)) {
+ SPDK_ERRLOG("spdk_json_decode_object() failed\n");
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "Invalid parameters");
+ return;
+ }
+ }
+
+ g_spdk_nvmf_tgt_max_subsystems = max_subsystems;
+
+ w = spdk_jsonrpc_begin_result(request);
+ spdk_json_write_bool(w, true);
+ spdk_jsonrpc_end_result(request, w);
+}
+SPDK_RPC_REGISTER("nvmf_set_max_subsystems", rpc_nvmf_set_max_subsystems,
+ SPDK_RPC_STARTUP)
+SPDK_RPC_REGISTER_ALIAS_DEPRECATED(nvmf_set_max_subsystems, set_nvmf_target_max_subsystems)
+
+static int decode_conn_sched(const struct spdk_json_val *val, void *out)
+{
+ *(uint32_t *)out = 0;
+
+ SPDK_NOTICELOG("conn_sched is no longer a supported parameter. Ignoring.");
+
+ return 0;
+}
+
+static const struct spdk_json_object_decoder admin_passthru_decoder[] = {
+ {"identify_ctrlr", offsetof(struct spdk_nvmf_admin_passthru_conf, identify_ctrlr), spdk_json_decode_bool}
+};
+
+static int decode_admin_passthru(const struct spdk_json_val *val, void *out)
+{
+ struct spdk_nvmf_admin_passthru_conf *req = (struct spdk_nvmf_admin_passthru_conf *)out;
+
+ if (spdk_json_decode_object(val, admin_passthru_decoder,
+ SPDK_COUNTOF(admin_passthru_decoder),
+ req)) {
+ SPDK_ERRLOG("spdk_json_decode_object failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_conf_decoder[] = {
+ {"acceptor_poll_rate", offsetof(struct spdk_nvmf_tgt_conf, acceptor_poll_rate), spdk_json_decode_uint32, true},
+ {"conn_sched", offsetof(struct spdk_nvmf_tgt_conf, conn_sched), decode_conn_sched, true},
+ {"admin_cmd_passthru", offsetof(struct spdk_nvmf_tgt_conf, admin_passthru), decode_admin_passthru, true}
+};
+
+static void
+rpc_nvmf_set_config(struct spdk_jsonrpc_request *request,
+ const struct spdk_json_val *params)
+{
+ struct spdk_nvmf_tgt_conf *conf;
+ struct spdk_json_write_ctx *w;
+
+ if (g_spdk_nvmf_tgt_conf != NULL) {
+ SPDK_ERRLOG("this RPC must not be called more than once.\n");
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ "Must not call more than once");
+ return;
+ }
+
+ conf = calloc(1, sizeof(*conf));
+ if (conf == NULL) {
+ SPDK_ERRLOG("calloc() failed for target config\n");
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
+ "Out of memory");
+ return;
+ }
+
+ conf->acceptor_poll_rate = ACCEPT_TIMEOUT_US;
+ conf->admin_passthru.identify_ctrlr = false;
+
+ if (params != NULL) {
+ if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_conf_decoder,
+ SPDK_COUNTOF(nvmf_rpc_subsystem_tgt_conf_decoder), conf)) {
+ free(conf);
+ SPDK_ERRLOG("spdk_json_decode_object() failed\n");
+ spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
+ "Invalid parameters");
+ return;
+ }
+ }
+
+ g_spdk_nvmf_tgt_conf = conf;
+
+ w = spdk_jsonrpc_begin_result(request);
+ spdk_json_write_bool(w, true);
+ spdk_jsonrpc_end_result(request, w);
+}
+SPDK_RPC_REGISTER("nvmf_set_config", rpc_nvmf_set_config, SPDK_RPC_STARTUP)
+SPDK_RPC_REGISTER_ALIAS_DEPRECATED(nvmf_set_config, set_nvmf_target_config)
diff --git a/src/spdk/module/event/subsystems/nvmf/nvmf_tgt.c b/src/spdk/module/event/subsystems/nvmf/nvmf_tgt.c
new file mode 100644
index 000000000..0ffac50c6
--- /dev/null
+++ b/src/spdk/module/event/subsystems/nvmf/nvmf_tgt.c
@@ -0,0 +1,476 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "event_nvmf.h"
+
+#include "spdk/bdev.h"
+#include "spdk/event.h"
+#include "spdk/thread.h"
+#include "spdk/log.h"
+#include "spdk/nvme.h"
+#include "spdk/nvmf_cmd.h"
+#include "spdk/util.h"
+
+enum nvmf_tgt_state {
+ NVMF_TGT_INIT_NONE = 0,
+ NVMF_TGT_INIT_PARSE_CONFIG,
+ NVMF_TGT_INIT_CREATE_POLL_GROUPS,
+ NVMF_TGT_INIT_START_SUBSYSTEMS,
+ NVMF_TGT_INIT_START_ACCEPTOR,
+ NVMF_TGT_RUNNING,
+ NVMF_TGT_FINI_STOP_SUBSYSTEMS,
+ NVMF_TGT_FINI_DESTROY_POLL_GROUPS,
+ NVMF_TGT_FINI_STOP_ACCEPTOR,
+ NVMF_TGT_FINI_FREE_RESOURCES,
+ NVMF_TGT_STOPPED,
+ NVMF_TGT_ERROR,
+};
+
+struct nvmf_tgt_poll_group {
+ struct spdk_nvmf_poll_group *group;
+ struct spdk_thread *thread;
+ TAILQ_ENTRY(nvmf_tgt_poll_group) link;
+};
+
+struct spdk_nvmf_tgt *g_spdk_nvmf_tgt = NULL;
+
+static enum nvmf_tgt_state g_tgt_state;
+
+static struct spdk_thread *g_tgt_init_thread = NULL;
+static struct spdk_thread *g_tgt_fini_thread = NULL;
+
+static TAILQ_HEAD(, nvmf_tgt_poll_group) g_poll_groups = TAILQ_HEAD_INITIALIZER(g_poll_groups);
+static size_t g_num_poll_groups = 0;
+
+static struct spdk_poller *g_acceptor_poller = NULL;
+
+static void nvmf_tgt_advance_state(void);
+
+static void
+nvmf_shutdown_cb(void *arg1)
+{
+ /* Still in initialization state, defer shutdown operation */
+ if (g_tgt_state < NVMF_TGT_RUNNING) {
+ spdk_thread_send_msg(spdk_get_thread(), nvmf_shutdown_cb, NULL);
+ return;
+ } else if (g_tgt_state != NVMF_TGT_RUNNING && g_tgt_state != NVMF_TGT_ERROR) {
+ /* Already in Shutdown status, ignore the signal */
+ return;
+ }
+
+ if (g_tgt_state == NVMF_TGT_ERROR) {
+ /* Parse configuration error */
+ g_tgt_state = NVMF_TGT_FINI_FREE_RESOURCES;
+ } else {
+ g_tgt_state = NVMF_TGT_FINI_STOP_SUBSYSTEMS;
+ }
+ nvmf_tgt_advance_state();
+}
+
+static void
+nvmf_subsystem_fini(void)
+{
+ nvmf_shutdown_cb(NULL);
+}
+
+static int
+acceptor_poll(void *arg)
+{
+ struct spdk_nvmf_tgt *tgt = arg;
+ uint32_t count;
+
+ count = spdk_nvmf_tgt_accept(tgt);
+
+ if (count > 0) {
+ return SPDK_POLLER_BUSY;
+ } else {
+ return SPDK_POLLER_IDLE;
+ }
+}
+
+static void
+_nvmf_tgt_destroy_poll_group_done(void *ctx)
+{
+ assert(g_num_poll_groups > 0);
+
+ if (--g_num_poll_groups == 0) {
+ g_tgt_state = NVMF_TGT_FINI_STOP_ACCEPTOR;
+ nvmf_tgt_advance_state();
+ }
+}
+
+static void
+nvmf_tgt_destroy_poll_group_done(void *cb_arg, int status)
+{
+ struct nvmf_tgt_poll_group *pg = cb_arg;
+
+ free(pg);
+
+ spdk_thread_send_msg(g_tgt_fini_thread, _nvmf_tgt_destroy_poll_group_done, NULL);
+
+ spdk_thread_exit(spdk_get_thread());
+}
+
+static void
+nvmf_tgt_destroy_poll_group(void *ctx)
+{
+ struct nvmf_tgt_poll_group *pg = ctx;
+
+ spdk_nvmf_poll_group_destroy(pg->group, nvmf_tgt_destroy_poll_group_done, pg);
+}
+
+static void
+nvmf_tgt_destroy_poll_groups(void)
+{
+ struct nvmf_tgt_poll_group *pg, *tpg;
+
+ g_tgt_fini_thread = spdk_get_thread();
+ assert(g_tgt_fini_thread != NULL);
+
+ TAILQ_FOREACH_SAFE(pg, &g_poll_groups, link, tpg) {
+ TAILQ_REMOVE(&g_poll_groups, pg, link);
+ spdk_thread_send_msg(pg->thread, nvmf_tgt_destroy_poll_group, pg);
+ }
+}
+
+static void
+nvmf_tgt_create_poll_group_done(void *ctx)
+{
+ struct nvmf_tgt_poll_group *pg = ctx;
+
+ TAILQ_INSERT_TAIL(&g_poll_groups, pg, link);
+
+ assert(g_num_poll_groups < spdk_env_get_core_count());
+
+ if (++g_num_poll_groups == spdk_env_get_core_count()) {
+ g_tgt_state = NVMF_TGT_INIT_START_SUBSYSTEMS;
+ nvmf_tgt_advance_state();
+ }
+}
+
+static void
+nvmf_tgt_create_poll_group(void *ctx)
+{
+ struct nvmf_tgt_poll_group *pg;
+
+ pg = calloc(1, sizeof(*pg));
+ if (!pg) {
+ SPDK_ERRLOG("Not enough memory to allocate poll groups\n");
+ spdk_app_stop(-ENOMEM);
+ return;
+ }
+
+ pg->thread = spdk_get_thread();
+ pg->group = spdk_nvmf_poll_group_create(g_spdk_nvmf_tgt);
+
+ spdk_thread_send_msg(g_tgt_init_thread, nvmf_tgt_create_poll_group_done, pg);
+}
+
+static void
+nvmf_tgt_create_poll_groups(void)
+{
+ struct spdk_cpuset tmp_cpumask = {};
+ uint32_t i;
+ char thread_name[32];
+ struct spdk_thread *thread;
+
+ g_tgt_init_thread = spdk_get_thread();
+ assert(g_tgt_init_thread != NULL);
+
+ SPDK_ENV_FOREACH_CORE(i) {
+ spdk_cpuset_zero(&tmp_cpumask);
+ spdk_cpuset_set_cpu(&tmp_cpumask, i, true);
+ snprintf(thread_name, sizeof(thread_name), "nvmf_tgt_poll_group_%u", i);
+
+ thread = spdk_thread_create(thread_name, &tmp_cpumask);
+ assert(thread != NULL);
+
+ spdk_thread_send_msg(thread, nvmf_tgt_create_poll_group, NULL);
+ }
+}
+
+static void
+nvmf_tgt_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
+ void *cb_arg, int status)
+{
+ subsystem = spdk_nvmf_subsystem_get_next(subsystem);
+
+ if (subsystem) {
+ spdk_nvmf_subsystem_start(subsystem, nvmf_tgt_subsystem_started, NULL);
+ return;
+ }
+
+ g_tgt_state = NVMF_TGT_INIT_START_ACCEPTOR;
+ nvmf_tgt_advance_state();
+}
+
+static void
+nvmf_tgt_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem,
+ void *cb_arg, int status)
+{
+ subsystem = spdk_nvmf_subsystem_get_next(subsystem);
+
+ if (subsystem) {
+ spdk_nvmf_subsystem_stop(subsystem, nvmf_tgt_subsystem_stopped, NULL);
+ return;
+ }
+
+ g_tgt_state = NVMF_TGT_FINI_DESTROY_POLL_GROUPS;
+ nvmf_tgt_advance_state();
+}
+
+static void
+nvmf_tgt_destroy_done(void *ctx, int status)
+{
+ g_tgt_state = NVMF_TGT_STOPPED;
+
+ free(g_spdk_nvmf_tgt_conf);
+ g_spdk_nvmf_tgt_conf = NULL;
+ nvmf_tgt_advance_state();
+}
+
+static void
+nvmf_tgt_parse_conf_done(int status)
+{
+ g_tgt_state = (status == 0) ? NVMF_TGT_INIT_CREATE_POLL_GROUPS : NVMF_TGT_ERROR;
+ nvmf_tgt_advance_state();
+}
+
+static void
+nvmf_tgt_parse_conf_start(void *ctx)
+{
+ if (nvmf_parse_conf(nvmf_tgt_parse_conf_done)) {
+ SPDK_ERRLOG("nvmf_parse_conf() failed\n");
+ g_tgt_state = NVMF_TGT_ERROR;
+ nvmf_tgt_advance_state();
+ }
+}
+
+static void
+fixup_identify_ctrlr(struct spdk_nvmf_request *req)
+{
+ uint32_t length;
+ int rc;
+ struct spdk_nvme_ctrlr_data *nvme_cdata;
+ struct spdk_nvme_ctrlr_data nvmf_cdata = {};
+ struct spdk_nvmf_ctrlr *ctrlr = spdk_nvmf_request_get_ctrlr(req);
+ struct spdk_nvme_cpl *rsp = spdk_nvmf_request_get_response(req);
+
+ /* This is the identify data from the NVMe drive */
+ spdk_nvmf_request_get_data(req, (void **)&nvme_cdata, &length);
+
+ /* Get the NVMF identify data */
+ rc = spdk_nvmf_ctrlr_identify_ctrlr(ctrlr, &nvmf_cdata);
+ if (rc != SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE) {
+ rsp->status.sct = SPDK_NVME_SCT_GENERIC;
+ rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
+ return;
+ }
+
+ /* Fixup NVMF identify data with NVMe identify data */
+
+ /* Serial Number (SN) */
+ memcpy(&nvmf_cdata.sn[0], &nvme_cdata->sn[0], sizeof(nvmf_cdata.sn));
+ /* Model Number (MN) */
+ memcpy(&nvmf_cdata.mn[0], &nvme_cdata->mn[0], sizeof(nvmf_cdata.mn));
+ /* Firmware Revision (FR) */
+ memcpy(&nvmf_cdata.fr[0], &nvme_cdata->fr[0], sizeof(nvmf_cdata.fr));
+ /* IEEE OUI Identifier (IEEE) */
+ memcpy(&nvmf_cdata.ieee[0], &nvme_cdata->ieee[0], sizeof(nvmf_cdata.ieee));
+ /* FRU Globally Unique Identifier (FGUID) */
+
+ /* Copy the fixed up data back to the response */
+ memcpy(nvme_cdata, &nvmf_cdata, length);
+}
+
+static int
+nvmf_custom_identify_hdlr(struct spdk_nvmf_request *req)
+{
+ struct spdk_nvme_cmd *cmd = spdk_nvmf_request_get_cmd(req);
+ struct spdk_bdev *bdev;
+ struct spdk_bdev_desc *desc;
+ struct spdk_io_channel *ch;
+ struct spdk_nvmf_subsystem *subsys;
+ int rc;
+
+ if (cmd->cdw10_bits.identify.cns != SPDK_NVME_IDENTIFY_CTRLR) {
+ return -1; /* continue */
+ }
+
+ subsys = spdk_nvmf_request_get_subsystem(req);
+ if (subsys == NULL) {
+ return -1;
+ }
+
+ /* Only procss this request if it has exactly one namespace */
+ if (spdk_nvmf_subsystem_get_max_nsid(subsys) != 1) {
+ return -1;
+ }
+
+ /* Forward to first namespace if it supports NVME admin commands */
+ rc = spdk_nvmf_request_get_bdev(1, req, &bdev, &desc, &ch);
+ if (rc) {
+ /* No bdev found for this namespace. Continue. */
+ return -1;
+ }
+
+ if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_ADMIN)) {
+ return -1;
+ }
+
+ return spdk_nvmf_bdev_ctrlr_nvme_passthru_admin(bdev, desc, ch, req, fixup_identify_ctrlr);
+}
+
+static void
+nvmf_tgt_advance_state(void)
+{
+ enum nvmf_tgt_state prev_state;
+ int rc = -1;
+
+ do {
+ prev_state = g_tgt_state;
+
+ switch (g_tgt_state) {
+ case NVMF_TGT_INIT_NONE: {
+ g_tgt_state = NVMF_TGT_INIT_PARSE_CONFIG;
+ break;
+ }
+ case NVMF_TGT_INIT_PARSE_CONFIG:
+ /* Send message to self to call parse conf func.
+ * Prevents it from possibly performing cb before getting
+ * out of this function, which causes problems. */
+ spdk_thread_send_msg(spdk_get_thread(), nvmf_tgt_parse_conf_start, NULL);
+ break;
+ case NVMF_TGT_INIT_CREATE_POLL_GROUPS:
+ /* Config parsed */
+ if (g_spdk_nvmf_tgt_conf->admin_passthru.identify_ctrlr) {
+ SPDK_NOTICELOG("Custom identify ctrlr handler enabled\n");
+ spdk_nvmf_set_custom_admin_cmd_hdlr(SPDK_NVME_OPC_IDENTIFY, nvmf_custom_identify_hdlr);
+ }
+ /* Create poll group threads, and send a message to each thread
+ * and create a poll group.
+ */
+ nvmf_tgt_create_poll_groups();
+ break;
+ case NVMF_TGT_INIT_START_SUBSYSTEMS: {
+ struct spdk_nvmf_subsystem *subsystem;
+
+ subsystem = spdk_nvmf_subsystem_get_first(g_spdk_nvmf_tgt);
+
+ if (subsystem) {
+ spdk_nvmf_subsystem_start(subsystem, nvmf_tgt_subsystem_started, NULL);
+ } else {
+ g_tgt_state = NVMF_TGT_INIT_START_ACCEPTOR;
+ }
+ break;
+ }
+ case NVMF_TGT_INIT_START_ACCEPTOR:
+ g_acceptor_poller = SPDK_POLLER_REGISTER(acceptor_poll, g_spdk_nvmf_tgt,
+ g_spdk_nvmf_tgt_conf->acceptor_poll_rate);
+ g_tgt_state = NVMF_TGT_RUNNING;
+ break;
+ case NVMF_TGT_RUNNING:
+ spdk_subsystem_init_next(0);
+ break;
+ case NVMF_TGT_FINI_STOP_SUBSYSTEMS: {
+ struct spdk_nvmf_subsystem *subsystem;
+
+ subsystem = spdk_nvmf_subsystem_get_first(g_spdk_nvmf_tgt);
+
+ if (subsystem) {
+ spdk_nvmf_subsystem_stop(subsystem, nvmf_tgt_subsystem_stopped, NULL);
+ } else {
+ g_tgt_state = NVMF_TGT_FINI_DESTROY_POLL_GROUPS;
+ }
+ break;
+ }
+ case NVMF_TGT_FINI_DESTROY_POLL_GROUPS:
+ /* Send a message to each poll group thread, and terminate the thread */
+ nvmf_tgt_destroy_poll_groups();
+ break;
+ case NVMF_TGT_FINI_STOP_ACCEPTOR:
+ spdk_poller_unregister(&g_acceptor_poller);
+ g_tgt_state = NVMF_TGT_FINI_FREE_RESOURCES;
+ break;
+ case NVMF_TGT_FINI_FREE_RESOURCES:
+ spdk_nvmf_tgt_destroy(g_spdk_nvmf_tgt, nvmf_tgt_destroy_done, NULL);
+ break;
+ case NVMF_TGT_STOPPED:
+ spdk_subsystem_fini_next();
+ return;
+ case NVMF_TGT_ERROR:
+ spdk_subsystem_init_next(rc);
+ return;
+ }
+
+ } while (g_tgt_state != prev_state);
+}
+
+static void
+nvmf_subsystem_init(void)
+{
+ g_tgt_state = NVMF_TGT_INIT_NONE;
+ nvmf_tgt_advance_state();
+}
+
+static void
+nvmf_subsystem_write_config_json(struct spdk_json_write_ctx *w)
+{
+ spdk_json_write_array_begin(w);
+
+ spdk_json_write_object_begin(w);
+ spdk_json_write_named_string(w, "method", "nvmf_set_config");
+
+ spdk_json_write_named_object_begin(w, "params");
+ spdk_json_write_named_uint32(w, "acceptor_poll_rate", g_spdk_nvmf_tgt_conf->acceptor_poll_rate);
+ spdk_json_write_named_object_begin(w, "admin_cmd_passthru");
+ spdk_json_write_named_bool(w, "identify_ctrlr",
+ g_spdk_nvmf_tgt_conf->admin_passthru.identify_ctrlr);
+ spdk_json_write_object_end(w);
+ spdk_json_write_object_end(w);
+ spdk_json_write_object_end(w);
+
+ spdk_nvmf_tgt_write_config_json(w, g_spdk_nvmf_tgt);
+ spdk_json_write_array_end(w);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_nvmf = {
+ .name = "nvmf",
+ .init = nvmf_subsystem_init,
+ .fini = nvmf_subsystem_fini,
+ .write_config_json = nvmf_subsystem_write_config_json,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_nvmf)
+SPDK_SUBSYSTEM_DEPEND(nvmf, bdev)
+SPDK_SUBSYSTEM_DEPEND(nvmf, sock)
diff --git a/src/spdk/module/event/subsystems/scsi/Makefile b/src/spdk/module/event/subsystems/scsi/Makefile
new file mode 100644
index 000000000..5d7fc3038
--- /dev/null
+++ b/src/spdk/module/event/subsystems/scsi/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = scsi.c
+LIBNAME = event_scsi
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/scsi/scsi.c b/src/spdk/module/event/subsystems/scsi/scsi.c
new file mode 100644
index 000000000..f63dc783b
--- /dev/null
+++ b/src/spdk/module/event/subsystems/scsi/scsi.c
@@ -0,0 +1,65 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/scsi.h"
+
+#include "spdk_internal/event.h"
+
+static void
+scsi_subsystem_init(void)
+{
+ int rc;
+
+ rc = spdk_scsi_init();
+
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+scsi_subsystem_fini(void)
+{
+ spdk_scsi_fini();
+ spdk_subsystem_fini_next();
+}
+
+static struct spdk_subsystem g_spdk_subsystem_scsi = {
+ .name = "scsi",
+ .init = scsi_subsystem_init,
+ .fini = scsi_subsystem_fini,
+ .config = NULL,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_scsi);
+SPDK_SUBSYSTEM_DEPEND(scsi, bdev)
diff --git a/src/spdk/module/event/subsystems/sock/Makefile b/src/spdk/module/event/subsystems/sock/Makefile
new file mode 100644
index 000000000..5a137d88d
--- /dev/null
+++ b/src/spdk/module/event/subsystems/sock/Makefile
@@ -0,0 +1,44 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 1
+SO_MINOR := 0
+
+C_SRCS = sock.c
+LIBNAME = event_sock
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/sock/sock.c b/src/spdk/module/event/subsystems/sock/sock.c
new file mode 100644
index 000000000..fdcb2160a
--- /dev/null
+++ b/src/spdk/module/event/subsystems/sock/sock.c
@@ -0,0 +1,62 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+#include "spdk/sock.h"
+#include "spdk_internal/event.h"
+
+static void
+sock_subsystem_init(void)
+{
+ spdk_subsystem_init_next(0);
+}
+
+static void
+sock_subsystem_fini(void)
+{
+ spdk_subsystem_fini_next();
+}
+
+static void
+sock_subsystem_write_config_json(struct spdk_json_write_ctx *w)
+{
+ spdk_sock_write_config_json(w);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_sock = {
+ .name = "sock",
+ .init = sock_subsystem_init,
+ .fini = sock_subsystem_fini,
+ .write_config_json = sock_subsystem_write_config_json,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_sock);
diff --git a/src/spdk/module/event/subsystems/vhost/Makefile b/src/spdk/module/event/subsystems/vhost/Makefile
new file mode 100644
index 000000000..a31bba91f
--- /dev/null
+++ b/src/spdk/module/event/subsystems/vhost/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = vhost.c
+LIBNAME = event_vhost
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/vhost/vhost.c b/src/spdk/module/event/subsystems/vhost/vhost.c
new file mode 100644
index 000000000..a0c386d98
--- /dev/null
+++ b/src/spdk/module/event/subsystems/vhost/vhost.c
@@ -0,0 +1,73 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+
+#include "spdk/vhost.h"
+
+#include "spdk_internal/event.h"
+
+static void
+vhost_subsystem_init_done(int rc)
+{
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+vhost_subsystem_init(void)
+{
+ spdk_vhost_init(vhost_subsystem_init_done);
+}
+
+static void
+vhost_subsystem_fini_done(void)
+{
+ spdk_subsystem_fini_next();
+}
+
+static void
+vhost_subsystem_fini(void)
+{
+ spdk_vhost_fini(vhost_subsystem_fini_done);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_vhost = {
+ .name = "vhost",
+ .init = vhost_subsystem_init,
+ .fini = vhost_subsystem_fini,
+ .config = NULL,
+ .write_config_json = spdk_vhost_config_json,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_vhost);
+SPDK_SUBSYSTEM_DEPEND(vhost, scsi)
diff --git a/src/spdk/module/event/subsystems/vmd/Makefile b/src/spdk/module/event/subsystems/vmd/Makefile
new file mode 100644
index 000000000..2089a2b9d
--- /dev/null
+++ b/src/spdk/module/event/subsystems/vmd/Makefile
@@ -0,0 +1,45 @@
+#
+# BSD LICENSE
+#
+# Copyright (c) Intel Corporation.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
+include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
+
+SO_VER := 2
+SO_MINOR := 0
+
+C_SRCS = vmd.c vmd_rpc.c
+LIBNAME = event_vmd
+
+SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
+
+include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
diff --git a/src/spdk/module/event/subsystems/vmd/event_vmd.h b/src/spdk/module/event/subsystems/vmd/event_vmd.h
new file mode 100644
index 000000000..2f4b93f95
--- /dev/null
+++ b/src/spdk/module/event/subsystems/vmd/event_vmd.h
@@ -0,0 +1,39 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EVENT_VMD_H
+#define EVENT_VMD_H
+
+int vmd_subsystem_init(void);
+
+#endif
diff --git a/src/spdk/module/event/subsystems/vmd/vmd.c b/src/spdk/module/event/subsystems/vmd/vmd.c
new file mode 100644
index 000000000..55eb47019
--- /dev/null
+++ b/src/spdk/module/event/subsystems/vmd/vmd.c
@@ -0,0 +1,132 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/stdinc.h"
+#include "spdk/conf.h"
+#include "spdk/thread.h"
+#include "spdk/likely.h"
+
+#include "spdk/vmd.h"
+
+#include "spdk_internal/event.h"
+#include "event_vmd.h"
+
+static struct spdk_poller *g_hotplug_poller;
+static bool g_enabled;
+
+static int
+vmd_hotplug_monitor(void *ctx)
+{
+ return spdk_vmd_hotplug_monitor();
+}
+
+int
+vmd_subsystem_init(void)
+{
+ int rc;
+
+ if (g_enabled) {
+ SPDK_ERRLOG("The initialization has already been performed\n");
+ return -EBUSY;
+ }
+
+ rc = spdk_vmd_init();
+ if (spdk_likely(rc != 0)) {
+ SPDK_ERRLOG("Failed to initialize the VMD library\n");
+ return rc;
+ }
+
+ assert(g_hotplug_poller == NULL);
+
+ g_hotplug_poller = SPDK_POLLER_REGISTER(vmd_hotplug_monitor, NULL, 1000000ULL);
+ if (g_hotplug_poller == NULL) {
+ SPDK_ERRLOG("Failed to register hotplug monitor poller\n");
+ return -ENOMEM;
+ }
+
+ g_enabled = true;
+
+ return 0;
+}
+
+static void
+_vmd_subsystem_init(void)
+{
+ struct spdk_conf_section *sp;
+ int rc = 0;
+
+ sp = spdk_conf_find_section(NULL, "Vmd");
+ if (sp != NULL) {
+ if (spdk_conf_section_get_boolval(sp, "Enable", false)) {
+ rc = vmd_subsystem_init();
+ }
+ }
+
+ spdk_subsystem_init_next(rc);
+}
+
+static void
+vmd_subsystem_fini(void)
+{
+ spdk_poller_unregister(&g_hotplug_poller);
+
+ spdk_vmd_fini();
+
+ spdk_subsystem_fini_next();
+}
+
+static void
+vmd_write_config_json(struct spdk_json_write_ctx *w)
+{
+ spdk_json_write_array_begin(w);
+
+ if (g_enabled) {
+ spdk_json_write_object_begin(w);
+ spdk_json_write_named_string(w, "method", "enable_vmd");
+ spdk_json_write_named_object_begin(w, "params");
+ spdk_json_write_object_end(w);
+ spdk_json_write_object_end(w);
+ }
+
+ spdk_json_write_array_end(w);
+}
+
+static struct spdk_subsystem g_spdk_subsystem_vmd = {
+ .name = "vmd",
+ .init = _vmd_subsystem_init,
+ .fini = vmd_subsystem_fini,
+ .config = NULL,
+ .write_config_json = vmd_write_config_json,
+};
+
+SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_vmd);
diff --git a/src/spdk/module/event/subsystems/vmd/vmd_rpc.c b/src/spdk/module/event/subsystems/vmd/vmd_rpc.c
new file mode 100644
index 000000000..35843e688
--- /dev/null
+++ b/src/spdk/module/event/subsystems/vmd/vmd_rpc.c
@@ -0,0 +1,55 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "spdk/vmd.h"
+
+#include "spdk/rpc.h"
+#include "spdk/util.h"
+
+#include "spdk_internal/log.h"
+#include "event_vmd.h"
+
+static void
+rpc_vmd_enable(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
+{
+ struct spdk_json_write_ctx *w;
+ int rc;
+
+ rc = vmd_subsystem_init();
+
+ w = spdk_jsonrpc_begin_result(request);
+ spdk_json_write_bool(w, rc == 0);
+ spdk_jsonrpc_end_result(request, w);
+}
+
+SPDK_RPC_REGISTER("enable_vmd", rpc_vmd_enable, SPDK_RPC_STARTUP)