Blame SOURCES/005-glib-priorities.patch

305287
From 65170ffd5fa10cbda176b3f88e817d534b6331d6 Mon Sep 17 00:00:00 2001
305287
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
305287
Date: Wed, 29 Aug 2018 15:49:58 +0200
305287
Subject: [PATCH 1/2] Low: mainloop: make it possible to specify server's
305287
 priority in mainloop
305287
305287
---
305287
 include/crm/common/mainloop.h | 24 +++++++++++++
305287
 lib/common/mainloop.c         | 82 +++++++++++++++++++++++++++++++++++++++++--
305287
 2 files changed, 103 insertions(+), 3 deletions(-)
305287
305287
diff --git a/include/crm/common/mainloop.h b/include/crm/common/mainloop.h
305287
index 85da1cd..2cfb63e 100644
305287
--- a/include/crm/common/mainloop.h
305287
+++ b/include/crm/common/mainloop.h
305287
@@ -79,6 +79,30 @@ struct ipc_client_callbacks {
305287
 qb_ipcs_service_t *mainloop_add_ipc_server(const char *name, enum qb_ipc_type type,
305287
                                            struct qb_ipcs_service_handlers *callbacks);
305287
 
305287
+/*!
305287
+ * \brief Start server-side API end-point, hooked into the internal event loop
305287
+ *
305287
+ * \param[in] name    name of the IPC end-point ("address" for the client)
305287
+ * \param[in] type    selects libqb's IPC back-end (or use #QB_IPC_NATIVE)
305287
+ * \param[in] callbacks  defines libqb's IPC service-level handlers
305287
+ * \param[in] priority  priority relative to other events handled in the
305287
+ *                      abstract handling loop, use #QB_LOOP_MED when unsure
305287
+ *
305287
+ * \return libqb's opaque handle to the created service abstraction
305287
+ *
305287
+ * \note For portability concerns, do not use this function if you keep
305287
+ *       \p priority as #QB_LOOP_MED, stick with #mainloop_add_ipc_server
305287
+ *       (with exactly such semantics) instead (once you link with this new
305287
+ *       symbol employed, you can't downgrade the library freely anymore).
305287
+ *
305287
+ * \note The intended effect will only get fully reflected when run-time
305287
+ *       linked to patched libqb: https://github.com/ClusterLabs/libqb/pull/352
305287
+ */
305287
+qb_ipcs_service_t *mainloop_add_ipc_server_with_prio(const char *name,
305287
+                                                    enum qb_ipc_type type,
305287
+                                                    struct qb_ipcs_service_handlers *callbacks,
305287
+                                                    enum qb_loop_priority prio);
305287
+
305287
 void mainloop_del_ipc_server(qb_ipcs_service_t * server);
305287
 
305287
 mainloop_io_t *mainloop_add_ipc_client(const char *name, int priority, size_t max_size,
305287
diff --git a/lib/common/mainloop.c b/lib/common/mainloop.c
305287
index 18f7014..17e69f0 100644
305287
--- a/lib/common/mainloop.c
305287
+++ b/lib/common/mainloop.c
305287
@@ -509,6 +509,65 @@ gio_poll_destroy(gpointer data)
305287
     }
305287
 }
305287
 
305287
+/*!
305287
+ * \internal
305287
+ * \brief Convert libqb's poll priority into GLib's one
305287
+ *
305287
+ * \param[in] prio  libqb's poll priority (#QB_LOOP_MED assumed as fallback)
305287
+ *
305287
+ * \return  best matching GLib's priority
305287
+ */
305287
+static gint
305287
+conv_prio_libqb2glib(enum qb_loop_priority prio)
305287
+{
305287
+    gint ret = G_PRIORITY_DEFAULT;
305287
+    switch (prio) {
305287
+        case QB_LOOP_LOW:
305287
+            ret = G_PRIORITY_LOW;
305287
+            break;
305287
+        case QB_LOOP_HIGH:
305287
+            ret = G_PRIORITY_HIGH;
305287
+            break;
305287
+        default:
305287
+            crm_trace("Invalid libqb's loop priority %d, assuming QB_LOOP_MED",
305287
+                      prio);
305287
+            /* fall-through */
305287
+        case QB_LOOP_MED:
305287
+            break;
305287
+    }
305287
+    return ret;
305287
+}
305287
+
305287
+/*!
305287
+ * \internal
305287
+ * \brief Convert libqb's poll priority to rate limiting spec
305287
+ *
305287
+ * \param[in] prio  libqb's poll priority (#QB_LOOP_MED assumed as fallback)
305287
+ *
305287
+ * \return  best matching rate limiting spec
305287
+ */
305287
+static enum qb_ipcs_rate_limit
305287
+conv_libqb_prio2ratelimit(enum qb_loop_priority prio)
305287
+{
305287
+    /* this is an inversion of what libqb's qb_ipcs_request_rate_limit does */
305287
+    enum qb_ipcs_rate_limit ret = QB_IPCS_RATE_NORMAL;
305287
+    switch (prio) {
305287
+        case QB_LOOP_LOW:
305287
+            ret = QB_IPCS_RATE_SLOW;
305287
+            break;
305287
+        case QB_LOOP_HIGH:
305287
+            ret = QB_IPCS_RATE_FAST;
305287
+            break;
305287
+        default:
305287
+            crm_trace("Invalid libqb's loop priority %d, assuming QB_LOOP_MED",
305287
+                      prio);
305287
+            /* fall-through */
305287
+        case QB_LOOP_MED:
305287
+            break;
305287
+    }
305287
+    return ret;
305287
+}
305287
+
305287
 static int32_t
305287
 gio_poll_dispatch_update(enum qb_loop_priority p, int32_t fd, int32_t evts,
305287
                          void *data, qb_ipcs_dispatch_fn_t fn, int32_t add)
305287
@@ -555,8 +614,8 @@ gio_poll_dispatch_update(enum qb_loop_priority p, int32_t fd, int32_t evts,
305287
     adaptor->p = p;
305287
     adaptor->is_used++;
305287
     adaptor->source =
305287
-        g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, evts, gio_read_socket, adaptor,
305287
-                            gio_poll_destroy);
305287
+        g_io_add_watch_full(channel, conv_prio_libqb2glib(p), evts,
305287
+                            gio_read_socket, adaptor, gio_poll_destroy);
305287
 
305287
     /* Now that mainloop now holds a reference to channel,
305287
      * thanks to g_io_add_watch_full(), drop ours from g_io_channel_unix_new().
305287
@@ -640,7 +699,15 @@ pick_ipc_type(enum qb_ipc_type requested)
305287
 
305287
 qb_ipcs_service_t *
305287
 mainloop_add_ipc_server(const char *name, enum qb_ipc_type type,
305287
-                        struct qb_ipcs_service_handlers * callbacks)
305287
+                        struct qb_ipcs_service_handlers *callbacks)
305287
+{
305287
+    return mainloop_add_ipc_server_with_prio(name, type, callbacks, QB_LOOP_MED);
305287
+}
305287
+
305287
+qb_ipcs_service_t *
305287
+mainloop_add_ipc_server_with_prio(const char *name, enum qb_ipc_type type,
305287
+                                  struct qb_ipcs_service_handlers *callbacks,
305287
+                                  enum qb_loop_priority prio)
305287
 {
305287
     int rc = 0;
305287
     qb_ipcs_service_t *server = NULL;
305287
@@ -652,6 +719,15 @@ mainloop_add_ipc_server(const char *name, enum qb_ipc_type type,
305287
     crm_client_init();
305287
     server = qb_ipcs_create(name, 0, pick_ipc_type(type), callbacks);
305287
 
305287
+    if (server == NULL) {
305287
+        crm_err("Could not create %s IPC server: %s (%d)", name, pcmk_strerror(rc), rc);
305287
+        return NULL;
305287
+    }
305287
+
305287
+    if (prio != QB_LOOP_MED) {
305287
+        qb_ipcs_request_rate_limit(server, conv_libqb_prio2ratelimit(prio));
305287
+    }
305287
+
305287
 #ifdef HAVE_IPCS_GET_BUFFER_SIZE
305287
     /* All clients should use at least ipc_buffer_max as their buffer size */
305287
     qb_ipcs_enforce_buffer_size(server, crm_ipc_default_buffer_size());
305287
-- 
305287
1.8.3.1
305287
305287
305287
From 3401f25994e8cc059898550082f9b75f2d07f103 Mon Sep 17 00:00:00 2001
305287
From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= <jpokorny@redhat.com>
305287
Date: Wed, 29 Aug 2018 15:50:57 +0200
305287
Subject: [PATCH 2/2] High: stonith-ng's function cannot be blocked with CIB
305287
 updates forever
305287
305287
In the high-load (or high-rate-config-change) scenarios,
305287
pacemaker-fenced would be unable to provide service when basically DoS'd
305287
with CIB update notifications.  Try to reconcile that with elevated
305287
priority of the server's proper listening interface in the mainloop, at
305287
worst, it will try to fence with slightly outdated config, but appears
305287
to be less bad than not carrying the execution at all, for instance.
305287
Other daemons might be considered as well.
305287
305287
Prerequisites:
305287
- https://github.com/ClusterLabs/libqb/pull/352
305287
  (libqb used to contain a bug due to which one particular step in the
305287
  initial-client-connection-accepting-at-the-server procedure that would
305287
  be carried out with hard-coded (and hence possibly lower than competing
305287
  events') priority, which backfires exactly in this case (once the
305287
  pacemaker part is fixed -- by the means of elevating priority for
305287
  the API end-point of fenced so that it won't get consistently
305287
  overridden with a non-socket-based event source/trigger)
305287
305287
How to verify:
305287
- mocked/based -N (see commit adding that module to mocked based daemon)
305287
---
305287
 lib/common/utils.c | 3 ++-
305287
 1 file changed, 2 insertions(+), 1 deletion(-)
305287
305287
diff --git a/lib/common/utils.c b/lib/common/utils.c
305287
index 758eb1b..d1c3e26 100644
305287
--- a/lib/common/utils.c
305287
+++ b/lib/common/utils.c
305287
@@ -1031,7 +1031,8 @@ attrd_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers
305287
 void
305287
 stonith_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
305287
 {
305287
-    *ipcs = mainloop_add_ipc_server("stonith-ng", QB_IPC_NATIVE, cb);
305287
+    *ipcs = mainloop_add_ipc_server_with_prio("stonith-ng", QB_IPC_NATIVE, cb,
305287
+                                              QB_LOOP_HIGH);
305287
 
305287
     if (*ipcs == NULL) {
305287
         crm_err("Failed to create fencer: exiting and inhibiting respawn.");
305287
-- 
305287
1.8.3.1
305287