From 66edf42c51f8591c93204b6490c103fa51346f47 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Thu, 22 Aug 2013 11:02:32 +0200 Subject: LDAP: Make the cleanup task reusable for subdomains Instead of always performing the cleanup on the main domain, the task now accepts a sdap_domain structure to perform the cleanup on. This change will make the cleanup task reusable for subdomains. --- src/providers/ldap/ldap_common.c | 2 +- src/providers/ldap/ldap_common.h | 10 ++-- src/providers/ldap/ldap_id_cleanup.c | 96 +++++++++++++++++++++++------------- src/providers/ldap/sdap.h | 3 ++ src/providers/ldap/sdap_async_enum.c | 4 +- 5 files changed, 73 insertions(+), 42 deletions(-) diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index 05e487a1e..ffa8aae59 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -960,7 +960,7 @@ int sdap_id_setup_tasks(struct sdap_id_ctx *ctx) /* run the first one in a couple of seconds so that we have time to * finish initializations first*/ tv = tevent_timeval_current_ofs(10, 0); - ret = ldap_id_cleanup_set_timer(ctx, tv); + ret = ldap_id_cleanup_create_timer(ctx, ctx->opts->sdom, tv); } return ret; diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 1dd69f4e2..fb45845ef 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -63,9 +63,6 @@ struct sdap_id_ctx { /* connection to a server */ struct sdap_id_conn_ctx *conn; - /* cleanup loop timer */ - struct timeval last_purge; - struct sdap_server_opts *srv_opts; }; @@ -168,8 +165,11 @@ int ldap_get_autofs_options(TALLOC_CTX *memctx, errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, struct sdap_id_conn_ctx *conn, struct sdap_domain *sdom); -errno_t ldap_id_cleanup(struct sdap_id_ctx *ctx); -int ldap_id_cleanup_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); +errno_t ldap_id_cleanup(struct sdap_options *opts, + struct sss_domain_info *dom); +int ldap_id_cleanup_create_timer(struct sdap_id_ctx *ctx, + struct sdap_domain *sdom, + struct timeval tv); void sdap_mark_offline(struct sdap_id_ctx *ctx); diff --git a/src/providers/ldap/ldap_id_cleanup.c b/src/providers/ldap/ldap_id_cleanup.c index 85c0139db..1fd2ff49f 100644 --- a/src/providers/ldap/ldap_id_cleanup.c +++ b/src/providers/ldap/ldap_id_cleanup.c @@ -33,60 +33,90 @@ #include "providers/ldap/sdap_async.h" /* ==Cleanup-Task========================================================= */ +struct ldap_id_cleanup_ctx { + struct sdap_id_ctx *ctx; + struct sdap_domain *sdom; +}; + +static errno_t ldap_id_cleanup_set_timer(struct ldap_id_cleanup_ctx *cctx, + struct timeval tv); + static void ldap_id_cleanup_timer(struct tevent_context *ev, struct tevent_timer *tt, struct timeval tv, void *pvt) { - struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); + struct ldap_id_cleanup_ctx *cctx = talloc_get_type(pvt, + struct ldap_id_cleanup_ctx); int delay; errno_t ret; - if (be_is_offline(ctx->be)) { - DEBUG(4, ("Backend is marked offline, retry later!\n")); + if (be_is_offline(cctx->ctx->be)) { + DEBUG(SSSDBG_TRACE_FUNC, ("Backend is marked offline, retry later!\n")); /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); + delay = dp_opt_get_int(cctx->ctx->opts->basic, + SDAP_CACHE_PURGE_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_cleanup_set_timer(ctx, tv); + ldap_id_cleanup_set_timer(cctx, tv); return; } - ret = ldap_id_cleanup(ctx); + ret = ldap_id_cleanup(cctx->ctx->opts, cctx->sdom->dom); if (ret != EOK) { /* On error schedule starting from now, not the last run */ tv = tevent_timeval_current(); } else { - tv = ctx->last_purge; + tv = cctx->sdom->last_purge; } - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); + delay = dp_opt_get_int(cctx->ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); tv = tevent_timeval_add(&tv, delay, 0); - ldap_id_cleanup_set_timer(ctx, tv); - ctx->last_purge = tevent_timeval_current(); + ldap_id_cleanup_set_timer(cctx, tv); + cctx->sdom->last_purge = tevent_timeval_current(); } -int ldap_id_cleanup_set_timer(struct sdap_id_ctx *ctx, struct timeval tv) +static errno_t ldap_id_cleanup_set_timer(struct ldap_id_cleanup_ctx *cctx, + struct timeval tv) { struct tevent_timer *cleanup_task; - DEBUG(6, ("Scheduling next cleanup at %ld.%ld\n", - (long)tv.tv_sec, (long)tv.tv_usec)); - - cleanup_task = tevent_add_timer(ctx->be->ev, ctx, - tv, ldap_id_cleanup_timer, ctx); - if (!cleanup_task) { - DEBUG(0, ("FATAL: failed to setup cleanup task!\n")); + cleanup_task = tevent_add_timer(cctx->ctx->be->ev, cctx->ctx, + tv, ldap_id_cleanup_timer, cctx); + if (cleanup_task == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("FATAL: failed to setup cleanup task!\n")); return EFAULT; } return EOK; } -static int cleanup_users(TALLOC_CTX *memctx, struct sdap_id_ctx *ctx); +int ldap_id_cleanup_create_timer(struct sdap_id_ctx *ctx, + struct sdap_domain *sdom, + struct timeval tv) +{ + struct ldap_id_cleanup_ctx *cctx; + + DEBUG(SSSDBG_FUNC_DATA, + ("Scheduling next cleanup at %ld.%ld\n", + (long)tv.tv_sec, (long)tv.tv_usec)); + + cctx = talloc(ctx, struct ldap_id_cleanup_ctx); + if (cctx == NULL) { + return ENOMEM; + } + cctx->ctx = ctx; + cctx->sdom = sdom; + + return ldap_id_cleanup_set_timer(cctx, tv); +} + +static int cleanup_users(struct sdap_options *opts, + struct sss_domain_info *dom); static int cleanup_groups(TALLOC_CTX *memctx, struct sysdb_ctx *sysdb, struct sss_domain_info *domain); -errno_t ldap_id_cleanup(struct sdap_id_ctx *ctx) +errno_t ldap_id_cleanup(struct sdap_options *opts, + struct sss_domain_info *dom) { int ret, tret; bool in_transaction = false; @@ -97,26 +127,24 @@ errno_t ldap_id_cleanup(struct sdap_id_ctx *ctx) return ENOMEM; } - ret = sysdb_transaction_start(ctx->be->domain->sysdb); + ret = sysdb_transaction_start(dom->sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); goto done; } in_transaction = true; - ret = cleanup_users(tmp_ctx, ctx); + ret = cleanup_users(opts, dom); if (ret && ret != ENOENT) { goto done; } - ret = cleanup_groups(tmp_ctx, - ctx->be->domain->sysdb, - ctx->be->domain); + ret = cleanup_groups(tmp_ctx, dom->sysdb, dom); if (ret) { goto done; } - ret = sysdb_transaction_commit(ctx->be->domain->sysdb); + ret = sysdb_transaction_commit(dom->sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n")); goto done; @@ -126,7 +154,7 @@ errno_t ldap_id_cleanup(struct sdap_id_ctx *ctx) ret = EOK; done: if (in_transaction) { - tret = sysdb_transaction_cancel(ctx->be->domain->sysdb); + tret = sysdb_transaction_cancel(dom->sysdb); if (tret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n")); } @@ -141,10 +169,11 @@ done: static int cleanup_users_logged_in(hash_table_t *table, const struct ldb_message *msg); -static int cleanup_users(TALLOC_CTX *memctx, struct sdap_id_ctx *ctx) +static int cleanup_users(struct sdap_options *opts, + struct sss_domain_info *dom) { TALLOC_CTX *tmpctx; - struct sysdb_ctx *sysdb = ctx->be->domain->sysdb; + struct sysdb_ctx *sysdb = dom->sysdb; const char *attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL }; time_t now = time(NULL); char *subfilter = NULL; @@ -156,13 +185,12 @@ static int cleanup_users(TALLOC_CTX *memctx, struct sdap_id_ctx *ctx) int ret; int i; - tmpctx = talloc_new(memctx); + tmpctx = talloc_new(NULL); if (!tmpctx) { return ENOMEM; } - account_cache_expiration = dp_opt_get_int(ctx->opts->basic, - SDAP_ACCOUNT_CACHE_EXPIRATION); + account_cache_expiration = dp_opt_get_int(opts->basic, SDAP_ACCOUNT_CACHE_EXPIRATION); DEBUG(9, ("Cache expiration is set to %d days\n", account_cache_expiration)); @@ -189,7 +217,7 @@ static int cleanup_users(TALLOC_CTX *memctx, struct sdap_id_ctx *ctx) goto done; } - ret = sysdb_search_users(tmpctx, sysdb, ctx->be->domain, + ret = sysdb_search_users(tmpctx, sysdb, dom, subfilter, attrs, &count, &msgs); if (ret) { if (ret == ENOENT) { @@ -236,7 +264,7 @@ static int cleanup_users(TALLOC_CTX *memctx, struct sdap_id_ctx *ctx) /* If not logged in or cannot check the table, delete him */ DEBUG(9, ("About to delete user %s\n", name)); - ret = sysdb_delete_user(sysdb, ctx->be->domain, name, 0); + ret = sysdb_delete_user(sysdb, dom, name, 0); if (ret) { goto done; } diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 5da27fe87..441ac904b 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -384,9 +384,12 @@ struct sdap_domain { /* Need to modify the list from a talloc destructor */ struct sdap_domain **head; + /* Enumeration and cleanup periodic task */ struct be_ptask *enum_task; /* enumeration loop timer */ struct timeval last_enum; + /* cleanup loop timer */ + struct timeval last_purge; }; struct sdap_options { diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c index b34b801a3..625db645f 100644 --- a/src/providers/ldap/sdap_async_enum.c +++ b/src/providers/ldap/sdap_async_enum.c @@ -93,7 +93,7 @@ sdap_dom_enum_send(TALLOC_CTX *memctx, sdom->last_enum = tevent_timeval_current(); t = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - if ((ctx->last_purge.tv_sec + t) < sdom->last_enum.tv_sec) { + if ((sdom->last_purge.tv_sec + t) < sdom->last_enum.tv_sec) { state->purge = true; } @@ -311,7 +311,7 @@ static void sdap_dom_enum_services_done(struct tevent_req *subreq) } if (state->purge) { - ret = ldap_id_cleanup(state->ctx); + ret = ldap_id_cleanup(state->ctx->opts, state->sdom->dom); if (ret != EOK) { /* Not fatal, worst case we'll have stale entries that would be * removed on a subsequent online lookup -- cgit