diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2015-10-11 15:34:44 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2015-10-23 10:21:13 +0200 |
commit | 10c07e188323a2f9824b5e34379f3b1a9b37759e (patch) | |
tree | 8d8951b12cf5bff8d089cc76d0a2f8bd19a68359 /src/providers/fail_over.c | |
parent | 4a4af8e1b6a9bab7c7a34d86055a400376e3829e (diff) | |
download | sssd-10c07e188323a2f9824b5e34379f3b1a9b37759e.tar.gz sssd-10c07e188323a2f9824b5e34379f3b1a9b37759e.tar.xz sssd-10c07e188323a2f9824b5e34379f3b1a9b37759e.zip |
FO: Use refcount to keep track of servers returned to callers
Resolves:
https://fedorahosted.org/sssd/ticket/2829
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Diffstat (limited to 'src/providers/fail_over.c')
-rw-r--r-- | src/providers/fail_over.c | 95 |
1 files changed, 76 insertions, 19 deletions
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c index b309f1c68..24aed9dfa 100644 --- a/src/providers/fail_over.c +++ b/src/providers/fail_over.c @@ -79,6 +79,8 @@ struct fo_service { }; struct fo_server { + REFCOUNT_COMMON; + struct fo_server *prev; struct fo_server *next; @@ -90,6 +92,8 @@ struct fo_server { struct fo_service *service; struct timeval last_status_change; struct server_common *common; + + TALLOC_CTX *fo_internal_owner; }; struct server_common { @@ -217,6 +221,15 @@ int fo_is_srv_lookup(struct fo_server *s) return s && s->srv_data; } +static void fo_server_free(struct fo_server *server) +{ + if (server == NULL) { + return; + } + + talloc_free(server->fo_internal_owner); +} + static struct fo_server * collapse_srv_lookup(struct fo_server **_server) { @@ -231,12 +244,12 @@ collapse_srv_lookup(struct fo_server **_server) while (server->prev && server->prev->srv_data == meta->srv_data) { tmp = server->prev; DLIST_REMOVE(server->service->server_list, tmp); - talloc_zfree(tmp); + fo_server_free(tmp); } while (server->next && server->next->srv_data == meta->srv_data) { tmp = server->next; DLIST_REMOVE(server->service->server_list, tmp); - talloc_zfree(tmp); + fo_server_free(tmp); } if (server == server->service->active_server) { @@ -249,7 +262,7 @@ collapse_srv_lookup(struct fo_server **_server) /* add back the meta server to denote SRV lookup */ DLIST_ADD_AFTER(server->service->server_list, meta, server); DLIST_REMOVE(server->service->server_list, server); - talloc_zfree(server); + fo_server_free(server); } meta->srv_data->srv_lookup_status = SRV_NEUTRAL; @@ -502,8 +515,9 @@ create_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name) struct server_common *common; common = rc_alloc(mem_ctx, struct server_common); - if (common == NULL) + if (common == NULL) { return NULL; + } common->name = talloc_strdup(common, name); if (common->name == NULL) { @@ -524,6 +538,41 @@ create_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name) return common; } +static struct fo_server * +fo_server_alloc(struct fo_service *service, int port, + void *user_data, bool primary) +{ + static struct fo_server *server; + TALLOC_CTX *server_owner; + + server_owner = talloc_new(service); + if (server_owner == NULL) { + return NULL; + } + + server = rc_alloc(server_owner, struct fo_server); + if (server == NULL) { + return NULL; + } + + server->fo_internal_owner = server_owner; + + server->common = NULL; + server->next = NULL; + server->prev = NULL; + server->srv_data = NULL; + server->last_status_change.tv_sec = 0; + server->last_status_change.tv_usec = 0; + + server->port = port; + server->user_data = user_data; + server->service = service; + server->port_status = DEFAULT_PORT_STATUS; + server->primary = primary; + + return server; +} + int fo_add_srv_server(struct fo_service *service, const char *srv, const char *discovery_domain, const char *sssd_domain, @@ -557,14 +606,11 @@ fo_add_srv_server(struct fo_service *service, const char *srv, } } - server = talloc_zero(service, struct fo_server); - if (server == NULL) + /* SRV servers are always primary */ + server = fo_server_alloc(service, 0, user_data, true); + if (server == NULL) { return ENOMEM; - - server->user_data = user_data; - server->service = service; - server->port_status = DEFAULT_PORT_STATUS; - server->primary = true; /* SRV servers are never back up */ + } /* add the SRV-specific data */ server->srv_data = talloc_zero(service, struct srv_data); @@ -608,7 +654,7 @@ create_fo_server(struct fo_service *service, const char *name, struct fo_server *server; int ret; - server = talloc_zero(service, struct fo_server); + server = fo_server_alloc(service, port, user_data, primary); if (server == NULL) return NULL; @@ -623,11 +669,11 @@ create_fo_server(struct fo_service *service, const char *name, if (ret == ENOENT) { server->common = create_server_common(server, service->ctx, name); if (server->common == NULL) { - talloc_free(server); + fo_server_free(server); return NULL; } } else if (ret != EOK) { - talloc_free(server); + fo_server_free(server); return NULL; } } @@ -760,7 +806,6 @@ static errno_t fo_add_server_list(struct fo_service *service, server = create_fo_server(service, servers[i].host, servers[i].port, user_data, primary); if (server == NULL) { - talloc_free(srv_list); return ENOMEM; } @@ -769,7 +814,7 @@ static errno_t fo_add_server_list(struct fo_service *service, ret = fo_add_server_to_list(&srv_list, service->server_list, server, service->name); if (ret != EOK) { - talloc_zfree(server); + fo_server_free(server); continue; } @@ -803,12 +848,20 @@ fo_add_server(struct fo_service *service, const char *name, int port, ret = fo_add_server_to_list(&service->server_list, service->server_list, server, service->name); if (ret != EOK) { - talloc_free(server); + fo_server_free(server); } return ret; } +void fo_ref_server(TALLOC_CTX *ref_ctx, + struct fo_server *server) +{ + if (server) { + rc_reference(ref_ctx, struct fo_server, server); + } +} + static int get_first_server_entity(struct fo_service *service, struct fo_server **_server) { @@ -1150,7 +1203,9 @@ fo_resolve_service_done(struct tevent_req *subreq) } int -fo_resolve_service_recv(struct tevent_req *req, struct fo_server **server) +fo_resolve_service_recv(struct tevent_req *req, + TALLOC_CTX *ref_ctx, + struct fo_server **server) { struct resolve_service_state *state; @@ -1158,8 +1213,10 @@ fo_resolve_service_recv(struct tevent_req *req, struct fo_server **server) /* always return the server if asked for, otherwise the caller * cannot mark it as faulty in case we return an error */ - if (server) + if (server != NULL) { + fo_ref_server(ref_ctx, state->server); *server = state->server; + } TEVENT_REQ_RETURN_ON_ERROR(req); |