Skip to content
Snippets Groups Projects
Commit 5927e8e5 authored by Lubos Slovak's avatar Lubos Slovak
Browse files

Added some synchronization to ns and zdb modules.

The synchronization needs revision and some thorough testing!
parent aeb0a37e
No related branches found
No related tags found
No related merge requests found
......@@ -5,6 +5,8 @@
#include <stdio.h>
#include <assert.h>
#include <urcu.h>
//#define NS_DEBUG
/*----------------------------------------------------------------------------*/
......@@ -37,15 +39,16 @@ int ns_answer_request( ns_nameserver *nameserver, const char *query_wire,
query->questions[0].qname);
debug_ns_hex(query->questions[0].qname, strlen(query->questions[0].qname));
// const ck_hash_table_item *item = ck_find_item(
// table, query->questions[0].qname,
// strlen(query->questions[0].qname));
// start of RCU read critical section (getting the node from the database)
rcu_read_lock();
const zn_node *node =
zdb_find_name(nameserver->zone_db, query->questions[0].qname);
dnss_packet *response = dnss_create_empty_packet();
if (response == NULL) {
dnss_destroy_packet(&query);
rcu_read_unlock();
return -1;
}
......@@ -54,6 +57,7 @@ int ns_answer_request( ns_nameserver *nameserver, const char *query_wire,
if (dnss_create_response(query, NULL, 0, &response) != 0) {
dnss_destroy_packet(&query);
dnss_destroy_packet(&response);
rcu_read_unlock();
return -1;
}
} else {
......@@ -63,10 +67,15 @@ int ns_answer_request( ns_nameserver *nameserver, const char *query_wire,
1, &response) != 0) {
dnss_destroy_packet(&query);
dnss_destroy_packet(&response);
rcu_read_unlock();
return -1;
}
}
// end of RCU read critical section (all data copied)
node = NULL;
rcu_read_unlock();
debug_ns("Response ID: %u\n", response->header.id);
if (dnss_wire_format(response, response_wire, rsize) != 0) {
......
......@@ -4,6 +4,8 @@
#include <stdio.h>
#include <assert.h>
#include <urcu.h>
/*----------------------------------------------------------------------------*/
zdb_database *zdb_create()
......@@ -24,6 +26,9 @@ zdb_database *zdb_create()
int zdb_create_zone( zdb_database *database, dnss_dname_wire zone_name,
uint items )
{
// add some lock to avoid multiple zone creations?
// add some check if the zone is not already in db?
zdb_zone *zone = malloc(sizeof(zdb_zone));
if (zone == NULL) {
......@@ -63,17 +68,37 @@ void zdb_find_zone( zdb_database *database, dnss_dname_wire zone_name,
*zone = database->head;
*prev = NULL;
// start of RCU reader critical section
rcu_read_lock();
while ((*zone) != NULL
&& dnss_dname_wire_cmp((*zone)->zone_name, zone_name) != 0) {
(*prev) = (*zone);
(*zone) = (*zone)->next;
}
// end of RCU reader critical section
rcu_read_unlock();
}
/*----------------------------------------------------------------------------*/
void zdb_disconnect_zone( zdb_database *database, zdb_zone *z, zdb_zone *prev )
{
// disconect the zone from the list
if (prev != NULL) {
prev->next = z->next;
} else {
database->head = z->next;
}
}
/*----------------------------------------------------------------------------*/
int zdb_remove_zone( zdb_database *database, dnss_dname_wire zone_name )
{
// add some lock to avoid multiple removals
zdb_zone *z = NULL, *zp = NULL;
zdb_find_zone(database, zone_name, &z, &zp);
......@@ -82,18 +107,15 @@ int zdb_remove_zone( zdb_database *database, dnss_dname_wire zone_name )
return -1;
}
// disconect the zone from the list
if (zp != NULL) {
zp->next = z->next;
} else {
database->head = z->next;
}
zdb_disconnect_zone(database, z, zp);
// wait for all readers to finish
synchronize_rcu();
zds_destroy(&z->zone);
assert(z->zone == NULL);
dnss_dname_wire_destroy(&z->zone_name);
assert(z->zone_name == NULL);
free(z);
return 0;
......@@ -105,6 +127,10 @@ int zdb_insert_name( zdb_database *database, dnss_dname_wire zone_name,
dnss_dname_wire dname, zn_node *node )
{
zdb_zone *z = NULL, *zp = NULL;
// start of RCU reader critical section (the zone should not be removed)
rcu_read_lock();
zdb_find_zone(database, zone_name, &z, &zp);
if (z == NULL) {
......@@ -115,7 +141,11 @@ int zdb_insert_name( zdb_database *database, dnss_dname_wire zone_name,
debug_zdb("Found zone: ");
debug_zdb_hex(z->zone_name, strlen(z->zone_name) + 1);
return zds_insert(z->zone, dname, node);
int res = zds_insert(z->zone, dname, node);
// end of RCU reader critical section
rcu_read_unlock();
return res;
}
/*----------------------------------------------------------------------------*/
......@@ -126,6 +156,10 @@ zdb_zone *zdb_find_zone_for_name( zdb_database *database,
zdb_zone *z = database->head, *best = NULL;
uint most_matched = 0;
// start of RCU reader critical section
// maybe not needed, called only from zdb_find_name()
rcu_read_lock();
while (z != NULL) {
uint matched = dnss_dname_wire_match(&dname, &z->zone_name);
if (matched > most_matched) {
......@@ -135,6 +169,9 @@ zdb_zone *zdb_find_zone_for_name( zdb_database *database,
z = z->next;
}
// end of RCU reader critical section
rcu_read_unlock();
return best;
}
......@@ -142,6 +179,9 @@ zdb_zone *zdb_find_zone_for_name( zdb_database *database,
const zn_node *zdb_find_name( zdb_database *database, dnss_dname_wire dname )
{
// start of RCU reader critical section
rcu_read_lock();
zdb_zone *z = zdb_find_zone_for_name(database, dname);
if (z == NULL) {
......@@ -152,21 +192,31 @@ const zn_node *zdb_find_name( zdb_database *database, dnss_dname_wire dname )
debug_zdb("Found zone: ");
debug_zdb_hex(z->zone_name, strlen(z->zone_name) + 1);
return zds_find(z->zone, dname);
const zn_node *found = zds_find(z->zone, dname);
// end of RCU reader critical section
rcu_read_unlock();
return found;
}
/*----------------------------------------------------------------------------*/
void zdb_destroy( zdb_database **database )
{
zdb_zone *z = (*database)->head;
zdb_zone *zp = NULL;
while (z != NULL) {
zp = z;
z = z->next;
zds_destroy(&zp->zone);
dnss_dname_wire_destroy(&zp->zone_name);
free(zp);
// add some lock to avoid multiple destroys
zdb_zone *z;
while ((*database)->head != NULL) {
z = (*database)->head;
// disconnect the first zone
(*database)->head = z->next;
// wait for all readers to finish
synchronize_rcu();
// destroy zone
zds_destroy(&z->zone);
dnss_dname_wire_destroy(&z->zone_name);
free(z);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment