* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "spdk_internal/event.h"
+#include "spdk/stdinc.h"
+
+#include "spdk/log.h"
-#include <stddef.h>
-#include <stdbool.h>
-#include <string.h>
+#include "spdk_internal/event.h"
+#include "spdk/env.h"
-static TAILQ_HEAD(spdk_subsystem_list, spdk_subsystem) g_subsystems =
- TAILQ_HEAD_INITIALIZER(g_subsystems);
-static TAILQ_HEAD(subsystem_depend, spdk_subsystem_depend) g_depends =
- TAILQ_HEAD_INITIALIZER(g_depends);
+struct spdk_subsystem_list g_subsystems = TAILQ_HEAD_INITIALIZER(g_subsystems);
+struct spdk_subsystem_depend_list g_subsystems_deps = TAILQ_HEAD_INITIALIZER(g_subsystems_deps);
+static struct spdk_subsystem *g_next_subsystem;
+static bool g_subsystems_initialized = false;
+static struct spdk_event *g_app_start_event;
+static struct spdk_event *g_app_stop_event;
+static uint32_t g_fini_core;
void
spdk_add_subsystem(struct spdk_subsystem *subsystem)
void
spdk_add_subsystem_depend(struct spdk_subsystem_depend *depend)
{
- TAILQ_INSERT_TAIL(&g_depends, depend, tailq);
+ TAILQ_INSERT_TAIL(&g_subsystems_deps, depend, tailq);
}
-static struct spdk_subsystem *
+struct spdk_subsystem *
spdk_subsystem_find(struct spdk_subsystem_list *list, const char *name)
{
struct spdk_subsystem *iter;
while (!TAILQ_EMPTY(&g_subsystems)) {
TAILQ_FOREACH_SAFE(subsystem, &g_subsystems, tailq, subsystem_tmp) {
depends_on = false;
- TAILQ_FOREACH(subsystem_dep, &g_depends, tailq) {
+ TAILQ_FOREACH(subsystem_dep, &g_subsystems_deps, tailq) {
if (strcmp(subsystem->name, subsystem_dep->name) == 0) {
depends_on = true;
depends_on_sorted = !!spdk_subsystem_find(&subsystems_list, subsystem_dep->depends_on);
- if (depends_on_sorted)
+ if (depends_on_sorted) {
continue;
+ }
break;
}
}
}
}
-int
-spdk_subsystem_init(void)
+void
+spdk_subsystem_init_next(int rc)
+{
+ if (rc) {
+ SPDK_ERRLOG("Init subsystem %s failed\n", g_next_subsystem->name);
+ spdk_app_stop(rc);
+ return;
+ }
+
+ if (!g_next_subsystem) {
+ g_next_subsystem = TAILQ_FIRST(&g_subsystems);
+ } else {
+ g_next_subsystem = TAILQ_NEXT(g_next_subsystem, tailq);
+ }
+
+ if (!g_next_subsystem) {
+ g_subsystems_initialized = true;
+ spdk_event_call(g_app_start_event);
+ return;
+ }
+
+ if (g_next_subsystem->init) {
+ g_next_subsystem->init();
+ } else {
+ spdk_subsystem_init_next(0);
+ }
+}
+
+static void
+spdk_subsystem_verify(void *arg1, void *arg2)
{
- int rc = 0;
- struct spdk_subsystem *subsystem;
struct spdk_subsystem_depend *dep;
/* Verify that all dependency name and depends_on subsystems are registered */
- TAILQ_FOREACH(dep, &g_depends, tailq) {
+ TAILQ_FOREACH(dep, &g_subsystems_deps, tailq) {
if (!spdk_subsystem_find(&g_subsystems, dep->name)) {
- fprintf(stderr, "subsystem %s is missing\n", dep->name);
- return -1;
+ SPDK_ERRLOG("subsystem %s is missing\n", dep->name);
+ spdk_app_stop(-1);
+ return;
}
if (!spdk_subsystem_find(&g_subsystems, dep->depends_on)) {
- fprintf(stderr, "subsystem %s dependency %s is missing\n",
- dep->name, dep->depends_on);
- return -1;
+ SPDK_ERRLOG("subsystem %s dependency %s is missing\n",
+ dep->name, dep->depends_on);
+ spdk_app_stop(-1);
+ return;
}
}
subsystem_sort();
- TAILQ_FOREACH(subsystem, &g_subsystems, tailq) {
- if (subsystem->init) {
- rc = subsystem->init();
- if (rc)
- return rc;
- }
- }
- return rc;
+ spdk_subsystem_init_next(0);
}
-int
-spdk_subsystem_fini(void)
+void
+spdk_subsystem_init(struct spdk_event *app_start_event)
{
- int rc = 0;
- struct spdk_subsystem *cur;
+ struct spdk_event *verify_event;
- cur = TAILQ_LAST(&g_subsystems, spdk_subsystem_list);
+ g_app_start_event = app_start_event;
- while (cur) {
- if (cur->fini) {
- rc = cur->fini();
- if (rc)
- return rc;
+ verify_event = spdk_event_allocate(spdk_env_get_current_core(), spdk_subsystem_verify, NULL, NULL);
+ spdk_event_call(verify_event);
+}
+
+static void
+_spdk_subsystem_fini_next(void *arg1, void *arg2)
+{
+ assert(g_fini_core == spdk_env_get_current_core());
+
+ if (!g_next_subsystem) {
+ /* If the initialized flag is false, then we've failed to initialize
+ * the very first subsystem and no de-init is needed
+ */
+ if (g_subsystems_initialized) {
+ g_next_subsystem = TAILQ_LAST(&g_subsystems, spdk_subsystem_list);
+ }
+ } else {
+ /* We rewind the g_next_subsystem unconditionally - even when some subsystem failed
+ * to initialize. It is assumed that subsystem which failed to initialize does not
+ * need to be deinitialized.
+ */
+ g_next_subsystem = TAILQ_PREV(g_next_subsystem, spdk_subsystem_list, tailq);
+ }
+
+ while (g_next_subsystem) {
+ if (g_next_subsystem->fini) {
+ g_next_subsystem->fini();
+ return;
}
- cur = TAILQ_PREV(cur, spdk_subsystem_list, tailq);
+ g_next_subsystem = TAILQ_PREV(g_next_subsystem, spdk_subsystem_list, tailq);
+ }
+
+ spdk_event_call(g_app_stop_event);
+ return;
+}
+
+void
+spdk_subsystem_fini_next(void)
+{
+ if (g_fini_core != spdk_env_get_current_core()) {
+ struct spdk_event *event;
+
+ event = spdk_event_allocate(g_fini_core, _spdk_subsystem_fini_next, NULL, NULL);
+ spdk_event_call(event);
+ } else {
+ _spdk_subsystem_fini_next(NULL, NULL);
}
+}
+
+void
+spdk_subsystem_fini(struct spdk_event *app_stop_event)
+{
+ g_app_stop_event = app_stop_event;
+ g_fini_core = spdk_env_get_current_core();
- return rc;
+ spdk_subsystem_fini_next();
}
void
struct spdk_subsystem *subsystem;
TAILQ_FOREACH(subsystem, &g_subsystems, tailq) {
- if (subsystem->config)
+ if (subsystem->config) {
subsystem->config(fp);
+ }
+ }
+}
+
+void
+spdk_subsystem_config_json(struct spdk_json_write_ctx *w, struct spdk_subsystem *subsystem,
+ struct spdk_event *done_ev)
+{
+ if (subsystem && subsystem->write_config_json) {
+ subsystem->write_config_json(w, done_ev);
+ } else {
+ spdk_json_write_null(w);
+ spdk_event_call(done_ev);
}
}