summaryrefslogtreecommitdiffstats
path: root/src/providers/fail_over.c
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2015-10-11 15:34:44 +0200
committerJakub Hrozek <jhrozek@redhat.com>2015-10-23 10:21:13 +0200
commit10c07e188323a2f9824b5e34379f3b1a9b37759e (patch)
tree8d8951b12cf5bff8d089cc76d0a2f8bd19a68359 /src/providers/fail_over.c
parent4a4af8e1b6a9bab7c7a34d86055a400376e3829e (diff)
downloadsssd-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.c95
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);