]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/spdk/lib/event/subsystem.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / spdk / lib / event / subsystem.c
index c25cb262e254439a5429c5f075b7a8a6cd5e83ab..438e7f543c0afe5c5acf63f35383742f62219923 100644 (file)
  *   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)
@@ -51,10 +55,10 @@ 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;
@@ -80,12 +84,13 @@ subsystem_sort(void)
        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;
                                }
                        }
@@ -108,56 +113,122 @@ subsystem_sort(void)
        }
 }
 
-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
@@ -166,7 +237,20 @@ spdk_subsystem_config(FILE *fp)
        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);
        }
 }