|
|
5fca41 |
From 84268efb9de2befd87b5e251bf2c99eb583923b6 Mon Sep 17 00:00:00 2001
|
|
|
5fca41 |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
5fca41 |
Date: Wed, 8 May 2019 23:16:07 +0200
|
|
|
5fca41 |
Subject: [PATCH 54/64] BE: Send refresh requests in batches
|
|
|
5fca41 |
|
|
|
5fca41 |
As we extend the background refresh into larger domains, the amount of
|
|
|
5fca41 |
data that SSSD refreshes on the background might be larger. And
|
|
|
5fca41 |
refreshing all expired entries in a single request might block sssd_be
|
|
|
5fca41 |
for a long time, either triggering the watchdog or starving other
|
|
|
5fca41 |
legitimate requests.
|
|
|
5fca41 |
|
|
|
5fca41 |
Therefore the background refresh will be done in batches of 200 entries.
|
|
|
5fca41 |
The first batch of every type (up to 200 users, up to 200 groups, ...)
|
|
|
5fca41 |
will be scheduled imediatelly and subsequent batches with a 0.5 second
|
|
|
5fca41 |
delay.
|
|
|
5fca41 |
|
|
|
5fca41 |
Related:
|
|
|
5fca41 |
https://pagure.io/SSSD/sssd/issue/4012
|
|
|
5fca41 |
|
|
|
5fca41 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
5fca41 |
(cherry picked from commit 7443498cc074c323e3b307f47ed49d59a5001f64)
|
|
|
5fca41 |
|
|
|
5fca41 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
5fca41 |
---
|
|
|
5fca41 |
src/providers/be_refresh.c | 131 ++++++++++++++++++++++----
|
|
|
5fca41 |
src/tests/cmocka/test_expire_common.c | 6 +-
|
|
|
5fca41 |
src/tests/sss_idmap-tests.c | 8 +-
|
|
|
5fca41 |
src/util/util.h | 8 ++
|
|
|
5fca41 |
4 files changed, 128 insertions(+), 25 deletions(-)
|
|
|
5fca41 |
|
|
|
5fca41 |
diff --git a/src/providers/be_refresh.c b/src/providers/be_refresh.c
|
|
|
5fca41 |
index c4ff71e1f..5d86509bb 100644
|
|
|
5fca41 |
--- a/src/providers/be_refresh.c
|
|
|
5fca41 |
+++ b/src/providers/be_refresh.c
|
|
|
5fca41 |
@@ -204,8 +204,21 @@ struct be_refresh_state {
|
|
|
5fca41 |
struct sss_domain_info *domain;
|
|
|
5fca41 |
enum be_refresh_type index;
|
|
|
5fca41 |
time_t period;
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ char **refresh_values;
|
|
|
5fca41 |
+ size_t refresh_val_size;
|
|
|
5fca41 |
+ size_t refresh_index;
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ size_t batch_size;
|
|
|
5fca41 |
+ char **refresh_batch;
|
|
|
5fca41 |
};
|
|
|
5fca41 |
|
|
|
5fca41 |
+static errno_t be_refresh_batch_step(struct tevent_req *req,
|
|
|
5fca41 |
+ uint32_t msec_delay);
|
|
|
5fca41 |
+static void be_refresh_batch_step_wakeup(struct tevent_context *ev,
|
|
|
5fca41 |
+ struct tevent_timer *tt,
|
|
|
5fca41 |
+ struct timeval tv,
|
|
|
5fca41 |
+ void *pvt);
|
|
|
5fca41 |
static errno_t be_refresh_step(struct tevent_req *req);
|
|
|
5fca41 |
static void be_refresh_done(struct tevent_req *subreq);
|
|
|
5fca41 |
|
|
|
5fca41 |
@@ -236,6 +249,13 @@ struct tevent_req *be_refresh_send(TALLOC_CTX *mem_ctx,
|
|
|
5fca41 |
goto immediately;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
+ state->batch_size = 200;
|
|
|
5fca41 |
+ state->refresh_batch = talloc_zero_array(state, char *, state->batch_size+1);
|
|
|
5fca41 |
+ if (state->refresh_batch == NULL) {
|
|
|
5fca41 |
+ ret = ENOMEM;
|
|
|
5fca41 |
+ goto immediately;
|
|
|
5fca41 |
+ }
|
|
|
5fca41 |
+
|
|
|
5fca41 |
ret = be_refresh_step(req);
|
|
|
5fca41 |
if (ret == EOK) {
|
|
|
5fca41 |
goto immediately;
|
|
|
5fca41 |
@@ -261,8 +281,6 @@ immediately:
|
|
|
5fca41 |
static errno_t be_refresh_step(struct tevent_req *req)
|
|
|
5fca41 |
{
|
|
|
5fca41 |
struct be_refresh_state *state = NULL;
|
|
|
5fca41 |
- struct tevent_req *subreq = NULL;
|
|
|
5fca41 |
- char **values = NULL;
|
|
|
5fca41 |
errno_t ret;
|
|
|
5fca41 |
|
|
|
5fca41 |
state = tevent_req_data(req, struct be_refresh_state);
|
|
|
5fca41 |
@@ -289,42 +307,103 @@ static errno_t be_refresh_step(struct tevent_req *req)
|
|
|
5fca41 |
goto done;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
+ talloc_zfree(state->refresh_values);
|
|
|
5fca41 |
ret = be_refresh_get_values(state, state->index, state->ctx->attr_name,
|
|
|
5fca41 |
- state->domain, state->period, &values);
|
|
|
5fca41 |
+ state->domain, state->period,
|
|
|
5fca41 |
+ &state->refresh_values);
|
|
|
5fca41 |
if (ret != EOK) {
|
|
|
5fca41 |
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to obtain DN list [%d]: %s\n",
|
|
|
5fca41 |
ret, sss_strerror(ret));
|
|
|
5fca41 |
goto done;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
- DEBUG(SSSDBG_TRACE_FUNC, "Refreshing %s in domain %s\n",
|
|
|
5fca41 |
- state->cb->name, state->domain->name);
|
|
|
5fca41 |
+ for (state->refresh_val_size = 0;
|
|
|
5fca41 |
+ state->refresh_values[state->refresh_val_size] != NULL;
|
|
|
5fca41 |
+ state->refresh_val_size++);
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ DEBUG(SSSDBG_TRACE_FUNC, "Refreshing %zu %s in domain %s\n",
|
|
|
5fca41 |
+ state->refresh_val_size, state->cb->name, state->domain->name);
|
|
|
5fca41 |
|
|
|
5fca41 |
- subreq = state->cb->send_fn(state, state->ev, state->be_ctx,
|
|
|
5fca41 |
- state->domain, values, state->cb->pvt);
|
|
|
5fca41 |
- if (subreq == NULL) {
|
|
|
5fca41 |
- ret = ENOMEM;
|
|
|
5fca41 |
+ ret = be_refresh_batch_step(req, 0);
|
|
|
5fca41 |
+ if (ret == EOK) {
|
|
|
5fca41 |
+ state->index++;
|
|
|
5fca41 |
+ continue;
|
|
|
5fca41 |
+ } else if (ret != EAGAIN) {
|
|
|
5fca41 |
goto done;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
-
|
|
|
5fca41 |
- /* make the list disappear with subreq */
|
|
|
5fca41 |
- talloc_steal(subreq, values);
|
|
|
5fca41 |
-
|
|
|
5fca41 |
- tevent_req_set_callback(subreq, be_refresh_done, req);
|
|
|
5fca41 |
+ /* EAGAIN only, refreshing something.. */
|
|
|
5fca41 |
|
|
|
5fca41 |
state->index++;
|
|
|
5fca41 |
- ret = EAGAIN;
|
|
|
5fca41 |
goto done;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
ret = EOK;
|
|
|
5fca41 |
|
|
|
5fca41 |
done:
|
|
|
5fca41 |
- if (ret != EOK && ret != EAGAIN) {
|
|
|
5fca41 |
- talloc_free(values);
|
|
|
5fca41 |
+ return ret;
|
|
|
5fca41 |
+}
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+static errno_t be_refresh_batch_step(struct tevent_req *req,
|
|
|
5fca41 |
+ uint32_t msec_delay)
|
|
|
5fca41 |
+{
|
|
|
5fca41 |
+ struct be_refresh_state *state = tevent_req_data(req, struct be_refresh_state);
|
|
|
5fca41 |
+ struct timeval tv;
|
|
|
5fca41 |
+ struct tevent_timer *timeout = NULL;
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ size_t remaining;
|
|
|
5fca41 |
+ size_t batch_size;
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ memset(state->refresh_batch, 0, sizeof(char *) * state->batch_size);
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ if (state->refresh_index >= state->refresh_val_size) {
|
|
|
5fca41 |
+ DEBUG(SSSDBG_FUNC_DATA, "The batch is done\n");
|
|
|
5fca41 |
+ state->refresh_index = 0;
|
|
|
5fca41 |
+ return EOK;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
- return ret;
|
|
|
5fca41 |
+ remaining = state->refresh_val_size - state->refresh_index;
|
|
|
5fca41 |
+ batch_size = MIN(remaining, state->batch_size);
|
|
|
5fca41 |
+ DEBUG(SSSDBG_FUNC_DATA,
|
|
|
5fca41 |
+ "This batch will refresh %zu entries (so far %zu/%zu)\n",
|
|
|
5fca41 |
+ batch_size, state->refresh_index, state->refresh_val_size);
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ for (size_t i = 0; i < batch_size; i++) {
|
|
|
5fca41 |
+ state->refresh_batch[i] = state->refresh_values[state->refresh_index];
|
|
|
5fca41 |
+ state->refresh_index++;
|
|
|
5fca41 |
+ }
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ tv = tevent_timeval_current_ofs(0, msec_delay * 1000);
|
|
|
5fca41 |
+ timeout = tevent_add_timer(state->be_ctx->ev, req, tv,
|
|
|
5fca41 |
+ be_refresh_batch_step_wakeup, req);
|
|
|
5fca41 |
+ if (timeout == NULL) {
|
|
|
5fca41 |
+ return ENOMEM;
|
|
|
5fca41 |
+ }
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ return EAGAIN;
|
|
|
5fca41 |
+}
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+static void be_refresh_batch_step_wakeup(struct tevent_context *ev,
|
|
|
5fca41 |
+ struct tevent_timer *tt,
|
|
|
5fca41 |
+ struct timeval tv,
|
|
|
5fca41 |
+ void *pvt)
|
|
|
5fca41 |
+{
|
|
|
5fca41 |
+ struct tevent_req *req;
|
|
|
5fca41 |
+ struct tevent_req *subreq = NULL;
|
|
|
5fca41 |
+ struct be_refresh_state *state = NULL;
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ req = talloc_get_type(pvt, struct tevent_req);
|
|
|
5fca41 |
+ state = tevent_req_data(req, struct be_refresh_state);
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Issuing refresh\n");
|
|
|
5fca41 |
+ subreq = state->cb->send_fn(state, state->ev, state->be_ctx,
|
|
|
5fca41 |
+ state->domain,
|
|
|
5fca41 |
+ state->refresh_batch,
|
|
|
5fca41 |
+ state->cb->pvt);
|
|
|
5fca41 |
+ if (subreq == NULL) {
|
|
|
5fca41 |
+ tevent_req_error(req, ENOMEM);
|
|
|
5fca41 |
+ return;
|
|
|
5fca41 |
+ }
|
|
|
5fca41 |
+ tevent_req_set_callback(subreq, be_refresh_done, req);
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
static void be_refresh_done(struct tevent_req *subreq)
|
|
|
5fca41 |
@@ -342,8 +421,24 @@ static void be_refresh_done(struct tevent_req *subreq)
|
|
|
5fca41 |
goto done;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
+ ret = be_refresh_batch_step(req, 500);
|
|
|
5fca41 |
+ if (ret == EAGAIN) {
|
|
|
5fca41 |
+ DEBUG(SSSDBG_TRACE_INTERNAL,
|
|
|
5fca41 |
+ "Another batch in this step in progress\n");
|
|
|
5fca41 |
+ return;
|
|
|
5fca41 |
+ } else if (ret != EOK) {
|
|
|
5fca41 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
5fca41 |
+ "be_refresh_batch_step failed [%d]: %s\n",
|
|
|
5fca41 |
+ ret, sss_strerror(ret));
|
|
|
5fca41 |
+ goto done;
|
|
|
5fca41 |
+ }
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "All batches in this step refreshed\n");
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+ /* Proceed to the next step */
|
|
|
5fca41 |
ret = be_refresh_step(req);
|
|
|
5fca41 |
if (ret == EAGAIN) {
|
|
|
5fca41 |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Another step in progress\n");
|
|
|
5fca41 |
return;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
diff --git a/src/tests/cmocka/test_expire_common.c b/src/tests/cmocka/test_expire_common.c
|
|
|
5fca41 |
index 5d3ea02f3..4f6168190 100644
|
|
|
5fca41 |
--- a/src/tests/cmocka/test_expire_common.c
|
|
|
5fca41 |
+++ b/src/tests/cmocka/test_expire_common.c
|
|
|
5fca41 |
@@ -32,7 +32,7 @@
|
|
|
5fca41 |
#include "tests/common_check.h"
|
|
|
5fca41 |
#include "tests/cmocka/test_expire_common.h"
|
|
|
5fca41 |
|
|
|
5fca41 |
-#define MAX 100
|
|
|
5fca41 |
+#define MAX_VAL 100
|
|
|
5fca41 |
|
|
|
5fca41 |
static char *now_str(TALLOC_CTX *mem_ctx, const char* format, int s)
|
|
|
5fca41 |
{
|
|
|
5fca41 |
@@ -41,10 +41,10 @@ static char *now_str(TALLOC_CTX *mem_ctx, const char* format, int s)
|
|
|
5fca41 |
size_t len;
|
|
|
5fca41 |
char *timestr;
|
|
|
5fca41 |
|
|
|
5fca41 |
- timestr = talloc_array(mem_ctx, char, MAX);
|
|
|
5fca41 |
+ timestr = talloc_array(mem_ctx, char, MAX_VAL);
|
|
|
5fca41 |
|
|
|
5fca41 |
tm = gmtime(&t);
|
|
|
5fca41 |
- len = strftime(timestr, MAX, format, tm);
|
|
|
5fca41 |
+ len = strftime(timestr, MAX_VAL, format, tm);
|
|
|
5fca41 |
if (len == 0) {
|
|
|
5fca41 |
return NULL;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c
|
|
|
5fca41 |
index 885913645..ef6843403 100644
|
|
|
5fca41 |
--- a/src/tests/sss_idmap-tests.c
|
|
|
5fca41 |
+++ b/src/tests/sss_idmap-tests.c
|
|
|
5fca41 |
@@ -140,8 +140,8 @@ void idmap_add_domain_with_sec_slices_setup_cb_fail(void)
|
|
|
5fca41 |
}
|
|
|
5fca41 |
|
|
|
5fca41 |
|
|
|
5fca41 |
-#define MAX 1000
|
|
|
5fca41 |
-char data[MAX];
|
|
|
5fca41 |
+#define DATA_MAX 1000
|
|
|
5fca41 |
+char data[DATA_MAX];
|
|
|
5fca41 |
|
|
|
5fca41 |
enum idmap_error_code cb2(const char *dom_name,
|
|
|
5fca41 |
const char *dom_sid,
|
|
|
5fca41 |
@@ -154,10 +154,10 @@ enum idmap_error_code cb2(const char *dom_name,
|
|
|
5fca41 |
char *p = (char*)pvt;
|
|
|
5fca41 |
size_t len;
|
|
|
5fca41 |
|
|
|
5fca41 |
- len = snprintf(p, MAX, "%s, %s %s, %"PRIu32", %"PRIu32", %" PRIu32,
|
|
|
5fca41 |
+ len = snprintf(p, DATA_MAX, "%s, %s %s, %"PRIu32", %"PRIu32", %" PRIu32,
|
|
|
5fca41 |
dom_name, dom_sid, range_id, min_id, max_id, first_rid);
|
|
|
5fca41 |
|
|
|
5fca41 |
- if (len >= MAX) {
|
|
|
5fca41 |
+ if (len >= DATA_MAX) {
|
|
|
5fca41 |
return IDMAP_OUT_OF_MEMORY;
|
|
|
5fca41 |
}
|
|
|
5fca41 |
return IDMAP_SUCCESS;
|
|
|
5fca41 |
diff --git a/src/util/util.h b/src/util/util.h
|
|
|
5fca41 |
index 3003583b7..fce7e42c3 100644
|
|
|
5fca41 |
--- a/src/util/util.h
|
|
|
5fca41 |
+++ b/src/util/util.h
|
|
|
5fca41 |
@@ -68,6 +68,14 @@
|
|
|
5fca41 |
|
|
|
5fca41 |
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
|
|
|
5fca41 |
|
|
|
5fca41 |
+#ifndef MIN
|
|
|
5fca41 |
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
|
5fca41 |
+#endif
|
|
|
5fca41 |
+
|
|
|
5fca41 |
+#ifndef MAX
|
|
|
5fca41 |
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
|
|
5fca41 |
+#endif
|
|
|
5fca41 |
+
|
|
|
5fca41 |
#define SSSD_MAIN_OPTS SSSD_DEBUG_OPTS
|
|
|
5fca41 |
|
|
|
5fca41 |
#define SSSD_SERVER_OPTS(uid, gid) \
|
|
|
5fca41 |
--
|
|
|
5fca41 |
2.20.1
|
|
|
5fca41 |
|