Blame SOURCES/0001-Providers-Delay-online-check-on-startup.patch

5fca41
From dab55626ce859dd519fe108b89fa723a38fb21d1 Mon Sep 17 00:00:00 2001
5fca41
From: Tomas Halman <thalman@redhat.com>
5fca41
Date: Wed, 20 Mar 2019 15:44:02 +0100
5fca41
Subject: [PATCH] Providers: Delay online check on startup
5fca41
5fca41
Typical usecase is system startup or network restart. In such
5fca41
cases SSSD receives several messages from the system about
5fca41
network change and immediately starts connecting.
5fca41
With multiple addresses on interface or multiple interfaces
5fca41
SSSD receives even more messages.
5fca41
5fca41
This patch introduces 1s delay for online check after first
5fca41
message.
5fca41
5fca41
Online callback tries 3 times to go online. There is increasing
5fca41
delay between online checks up to 4s.
5fca41
5fca41
Resolves: https://pagure.io/SSSD/sssd/issue/3467
5fca41
5fca41
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
5fca41
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
5fca41
(cherry picked from commit fe4288088e6cccf7650e5c5def3bd67be90756be)
5fca41
---
5fca41
 src/providers/backend.h          |  1 +
5fca41
 src/providers/data_provider_be.c | 94 ++++++++++++++++++++++++--------
5fca41
 2 files changed, 72 insertions(+), 23 deletions(-)
5fca41
5fca41
diff --git a/src/providers/backend.h b/src/providers/backend.h
5fca41
index 1fe1c2313..5ab47b29a 100644
5fca41
--- a/src/providers/backend.h
5fca41
+++ b/src/providers/backend.h
5fca41
@@ -112,6 +112,7 @@ struct be_ctx {
5fca41
     struct be_refresh_ctx *refresh_ctx;
5fca41
 
5fca41
     size_t check_online_ref_count;
5fca41
+    int check_online_retry_delay;
5fca41
 
5fca41
     struct data_provider *provider;
5fca41
 
5fca41
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
5fca41
index fad6f2801..17513111c 100644
5fca41
--- a/src/providers/data_provider_be.c
5fca41
+++ b/src/providers/data_provider_be.c
5fca41
@@ -50,6 +50,9 @@
5fca41
 #include "resolv/async_resolv.h"
5fca41
 #include "monitor/monitor_interfaces.h"
5fca41
 
5fca41
+#define ONLINE_CB_RETRY 3
5fca41
+#define ONLINE_CB_RETRY_MAX_DELAY 4
5fca41
+
5fca41
 static int data_provider_res_init(struct sbus_request *dbus_req, void *data);
5fca41
 static int data_provider_go_offline(struct sbus_request *dbus_req, void *data);
5fca41
 static int data_provider_reset_offline(struct sbus_request *dbus_req, void *data);
5fca41
@@ -71,7 +74,7 @@ bool be_is_offline(struct be_ctx *ctx)
5fca41
     return ctx->offstat.offline;
5fca41
 }
5fca41
 
5fca41
-static void check_if_online(struct be_ctx *be_ctx);
5fca41
+static void check_if_online(struct be_ctx *be_ctx, int delay);
5fca41
 
5fca41
 static errno_t
5fca41
 try_to_go_online(TALLOC_CTX *mem_ctx,
5fca41
@@ -82,7 +85,7 @@ try_to_go_online(TALLOC_CTX *mem_ctx,
5fca41
 {
5fca41
     struct be_ctx *ctx = (struct be_ctx*) be_ctx_void;
5fca41
 
5fca41
-    check_if_online(ctx);
5fca41
+    check_if_online(ctx, 0);
5fca41
     return EOK;
5fca41
 }
5fca41
 
5fca41
@@ -247,10 +250,39 @@ static errno_t be_check_online_request(struct be_ctx *be_ctx)
5fca41
     return EOK;
5fca41
 }
5fca41
 
5fca41
+static void check_if_online_delayed(struct tevent_context *ev,
5fca41
+                                    struct tevent_timer *tim,
5fca41
+                                    struct timeval current_time,
5fca41
+                                    void *private_data)
5fca41
+{
5fca41
+    errno_t ret;
5fca41
+    struct be_ctx *be_ctx = talloc_get_type(private_data, struct be_ctx);
5fca41
+
5fca41
+    be_run_unconditional_online_cb(be_ctx);
5fca41
+
5fca41
+    if (!be_is_offline(be_ctx)) {
5fca41
+        DEBUG(SSSDBG_TRACE_INTERNAL,
5fca41
+              "Backend is already online, nothing to do.\n");
5fca41
+        be_ctx->check_online_ref_count = 0;
5fca41
+        return;
5fca41
+    }
5fca41
+
5fca41
+    DEBUG(SSSDBG_TRACE_INTERNAL, "Trying to go back online!\n");
5fca41
+
5fca41
+    ret = be_check_online_request(be_ctx);
5fca41
+    if (ret != EOK) {
5fca41
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create check online req.\n");
5fca41
+    } else {
5fca41
+        DEBUG(SSSDBG_TRACE_INTERNAL, "Check online req created.\n");
5fca41
+    }
5fca41
+}
5fca41
+
5fca41
 static void be_check_online_done(struct tevent_req *req)
5fca41
 {
5fca41
     struct be_ctx *be_ctx;
5fca41
     struct dp_reply_std *reply;
5fca41
+    struct tevent_timer *time_event;
5fca41
+    struct timeval schedule;
5fca41
     errno_t ret;
5fca41
 
5fca41
     be_ctx = tevent_req_callback_data(req, struct be_ctx);
5fca41
@@ -285,11 +317,24 @@ static void be_check_online_done(struct tevent_req *req)
5fca41
     be_ctx->check_online_ref_count--;
5fca41
 
5fca41
     if (reply->dp_error != DP_ERR_OK && be_ctx->check_online_ref_count > 0) {
5fca41
-        ret = be_check_online_request(be_ctx);
5fca41
-        if (ret != EOK) {
5fca41
-            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create check online req.\n");
5fca41
+        be_ctx->check_online_retry_delay *= 2;
5fca41
+        if (be_ctx->check_online_retry_delay > ONLINE_CB_RETRY_MAX_DELAY) {
5fca41
+            be_ctx->check_online_retry_delay = ONLINE_CB_RETRY_MAX_DELAY;
5fca41
+        }
5fca41
+
5fca41
+        schedule = tevent_timeval_current_ofs(be_ctx->check_online_retry_delay,
5fca41
+                                              0);
5fca41
+        time_event = tevent_add_timer(be_ctx->ev, be_ctx, schedule,
5fca41
+                                      check_if_online_delayed, be_ctx);
5fca41
+
5fca41
+        if (time_event == NULL) {
5fca41
+            DEBUG(SSSDBG_OP_FAILURE, "Failed to schedule online check\n");
5fca41
             goto done;
5fca41
         }
5fca41
+
5fca41
+        DEBUG(SSSDBG_TRACE_INTERNAL,
5fca41
+              "Schedule check_if_online_delayed in %ds.\n",
5fca41
+              be_ctx->check_online_retry_delay);
5fca41
         return;
5fca41
     }
5fca41
 
5fca41
@@ -303,28 +348,23 @@ done:
5fca41
     }
5fca41
 }
5fca41
 
5fca41
-static void check_if_online(struct be_ctx *be_ctx)
5fca41
+static void check_if_online(struct be_ctx *be_ctx, int delay)
5fca41
 {
5fca41
-    errno_t ret;
5fca41
-
5fca41
-    be_run_unconditional_online_cb(be_ctx);
5fca41
-
5fca41
-    if (!be_is_offline(be_ctx)) {
5fca41
-        DEBUG(SSSDBG_TRACE_INTERNAL,
5fca41
-              "Backend is already online, nothing to do.\n");
5fca41
-        return;
5fca41
-    }
5fca41
+    struct tevent_timer *time_event;
5fca41
+    struct timeval schedule;
5fca41
 
5fca41
     /* Make sure nobody tries to go online while we are checking */
5fca41
     be_ctx->offstat.went_offline = time(NULL);
5fca41
 
5fca41
-    DEBUG(SSSDBG_TRACE_INTERNAL, "Trying to go back online!\n");
5fca41
-
5fca41
     be_ctx->check_online_ref_count++;
5fca41
 
5fca41
     if (be_ctx->check_online_ref_count != 1) {
5fca41
         DEBUG(SSSDBG_TRACE_INTERNAL,
5fca41
               "There is an online check already running.\n");
5fca41
+        /* Do not have more than ONLINE_CB_RETRY retries in the queue */
5fca41
+        if (be_ctx->check_online_ref_count > ONLINE_CB_RETRY) {
5fca41
+            be_ctx->check_online_ref_count--;
5fca41
+        }
5fca41
         return;
5fca41
     }
5fca41
 
5fca41
@@ -334,12 +374,20 @@ static void check_if_online(struct be_ctx *be_ctx)
5fca41
         goto failed;
5fca41
     }
5fca41
 
5fca41
-    ret = be_check_online_request(be_ctx);
5fca41
-    if (ret != EOK) {
5fca41
-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create check online req.\n");
5fca41
+    schedule = tevent_timeval_current_ofs(delay, 0);
5fca41
+    time_event = tevent_add_timer(be_ctx->ev, be_ctx, schedule,
5fca41
+                                  check_if_online_delayed, be_ctx);
5fca41
+
5fca41
+    if (time_event == NULL) {
5fca41
+        DEBUG(SSSDBG_OP_FAILURE,
5fca41
+              "Scheduling check_if_online_delayed failed.\n");
5fca41
         goto failed;
5fca41
     }
5fca41
 
5fca41
+    be_ctx->check_online_ref_count = ONLINE_CB_RETRY;
5fca41
+    be_ctx->check_online_retry_delay = 1;
5fca41
+    DEBUG(SSSDBG_TRACE_INTERNAL,
5fca41
+          "Schedule check_if_online_delayed in %ds.\n", delay);
5fca41
     return;
5fca41
 
5fca41
 failed:
5fca41
@@ -373,7 +421,7 @@ static void signal_be_reset_offline(struct tevent_context *ev,
5fca41
                                     void *private_data)
5fca41
 {
5fca41
     struct be_ctx *ctx = talloc_get_type(private_data, struct be_ctx);
5fca41
-    check_if_online(ctx);
5fca41
+    check_if_online(ctx, 0);
5fca41
 }
5fca41
 
5fca41
 errno_t be_process_init(TALLOC_CTX *mem_ctx,
5fca41
@@ -649,7 +697,7 @@ static int data_provider_res_init(struct sbus_request *dbus_req, void *data)
5fca41
     be_ctx = talloc_get_type(data, struct be_ctx);
5fca41
 
5fca41
     resolv_reread_configuration(be_ctx->be_res->resolv);
5fca41
-    check_if_online(be_ctx);
5fca41
+    check_if_online(be_ctx, 1);
5fca41
 
5fca41
     return monitor_common_res_init(dbus_req, data);
5fca41
 }
5fca41
@@ -666,7 +714,7 @@ static int data_provider_reset_offline(struct sbus_request *dbus_req, void *data
5fca41
 {
5fca41
     struct be_ctx *be_ctx;
5fca41
     be_ctx = talloc_get_type(data, struct be_ctx);
5fca41
-    check_if_online(be_ctx);
5fca41
+    check_if_online(be_ctx, 1);
5fca41
     return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
5fca41
 }
5fca41
 
5fca41
-- 
5fca41
2.19.1
5fca41