resolved: reference count the dns servers

We want to reference the servers from their active transactions, so make sure
they stay around as long as the transaction does.
This commit is contained in:
Tom Gundersen 2015-06-24 18:41:46 +02:00
parent a0166609f7
commit 91b14d6ff3
4 changed files with 73 additions and 31 deletions

View File

@ -41,6 +41,7 @@ int dns_server_new(
if (!s)
return -ENOMEM;
s->n_ref = 1;
s->type = type;
s->family = family;
s->address = *in_addr;
@ -74,33 +75,46 @@ int dns_server_new(
return 0;
}
DnsServer* dns_server_free(DnsServer *s) {
DnsServer* dns_server_ref(DnsServer *s) {
if (!s)
return NULL;
if (s->link) {
if (s->type == DNS_SERVER_LINK)
LIST_REMOVE(servers, s->link->dns_servers, s);
assert(s->n_ref > 0);
if (s->link->current_dns_server == s)
link_set_dns_server(s->link, NULL);
}
s->n_ref ++;
if (s->manager) {
if (s->type == DNS_SERVER_SYSTEM)
LIST_REMOVE(servers, s->manager->dns_servers, s);
else if (s->type == DNS_SERVER_FALLBACK)
LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
return s;
}
if (s->manager->current_dns_server == s)
manager_set_dns_server(s->manager, NULL);
}
static DnsServer* dns_server_free(DnsServer *s) {
if (!s)
return NULL;
if (s->link && s->link->current_dns_server == s)
link_set_dns_server(s->link, NULL);
if (s->manager && s->manager->current_dns_server == s)
manager_set_dns_server(s->manager, NULL);
free(s);
return NULL;
}
DnsServer* dns_server_unref(DnsServer *s) {
if (!s)
return NULL;
assert(s->n_ref > 0);
if (s->n_ref == 1)
dns_server_free(s);
else
s->n_ref --;
return NULL;
}
static unsigned long dns_server_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
const DnsServer *s = p;
uint64_t u;

View File

@ -37,6 +37,8 @@ typedef enum DnsServerType {
struct DnsServer {
Manager *manager;
unsigned n_ref;
DnsServerType type;
Link *link;
@ -57,6 +59,7 @@ int dns_server_new(
int family,
const union in_addr_union *address);
DnsServer* dns_server_free(DnsServer *s);
DnsServer* dns_server_ref(DnsServer *s);
DnsServer* dns_server_unref(DnsServer *s);
extern const struct hash_ops dns_server_hash_ops;

View File

@ -58,7 +58,6 @@ int link_new(Manager *m, Link **ret, int ifindex) {
}
Link *link_free(Link *l) {
if (!l)
return NULL;
@ -68,8 +67,12 @@ Link *link_free(Link *l) {
if (l->manager)
hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
while (l->dns_servers)
dns_server_free(l->dns_servers);
while (l->dns_servers) {
DnsServer *s = l->dns_servers;
LIST_REMOVE(servers, l->dns_servers, s);
dns_server_unref(s);
}
dns_scope_free(l->unicast_scope);
dns_scope_free(l->llmnr_ipv4_scope);
@ -182,14 +185,20 @@ static int link_update_dns_servers(Link *l) {
}
LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers)
if (s->marked)
dns_server_free(s);
if (s->marked) {
LIST_REMOVE(servers, l->dns_servers, s);
dns_server_unref(s);
}
return 0;
clear:
while (l->dns_servers)
dns_server_free(l->dns_servers);
while (l->dns_servers) {
s = l->dns_servers;
LIST_REMOVE(servers, l->dns_servers, s);
dns_server_unref(s);
}
return r;
}

View File

@ -603,8 +603,10 @@ int manager_read_resolv_conf(Manager *m) {
}
LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
if (s->marked)
dns_server_free(s);
if (s->marked) {
LIST_REMOVE(servers, m->dns_servers, s);
dns_server_unref(s);
}
/* Whenever /etc/resolv.conf changes, start using the first
* DNS server of it. This is useful to deal with broken
@ -619,8 +621,12 @@ int manager_read_resolv_conf(Manager *m) {
return 0;
clear:
while (m->dns_servers)
dns_server_free(m->dns_servers);
while (m->dns_servers) {
s = m->dns_servers;
LIST_REMOVE(servers, m->dns_servers, s);
dns_server_unref(s);
}
return r;
}
@ -1381,15 +1387,25 @@ void manager_verify_all(Manager *m) {
}
void manager_flush_dns_servers(Manager *m, DnsServerType t) {
DnsServer *s;
assert(m);
if (t == DNS_SERVER_SYSTEM)
while (m->dns_servers)
dns_server_free(m->dns_servers);
while (m->dns_servers) {
s = m->dns_servers;
LIST_REMOVE(servers, m->dns_servers, s);
dns_server_unref(s);
}
if (t == DNS_SERVER_FALLBACK)
while (m->fallback_dns_servers)
dns_server_free(m->fallback_dns_servers);
while (m->fallback_dns_servers) {
s = m->fallback_dns_servers;
LIST_REMOVE(servers, m->fallback_dns_servers, s);
dns_server_unref(s);
}
}
static const char* const support_table[_SUPPORT_MAX] = {