summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsr2012-09-02 18:49:16 +0200
committersr2012-09-02 18:49:16 +0200
commit8c0712acf701925fa36ca85a548d56a7851543c5 (patch)
treeb5f24197c09549f91c0c1d6de0ed1dc99cf96e0a
parent[KERNEL] Fix off-by-one error (diff)
downloaddnbd3-8c0712acf701925fa36ca85a548d56a7851543c5.tar.gz
dnbd3-8c0712acf701925fa36ca85a548d56a7851543c5.tar.xz
dnbd3-8c0712acf701925fa36ca85a548d56a7851543c5.zip
[SERVER] Add list of trusted servers and namespaces (load, display)
-rw-r--r--src/config.h2
-rw-r--r--src/kernel/net.c28
-rw-r--r--src/server/ipc.c153
-rw-r--r--src/server/job.c39
-rw-r--r--src/server/net.c5
-rw-r--r--src/server/server.c9
-rw-r--r--src/server/server.h17
-rw-r--r--src/server/utils.c111
-rw-r--r--src/server/utils.h4
-rw-r--r--src/types.h13
10 files changed, 310 insertions, 71 deletions
diff --git a/src/config.h b/src/config.h
index ff638d2..2f348aa 100644
--- a/src/config.h
+++ b/src/config.h
@@ -63,7 +63,7 @@
#define KERNEL_SECTOR_SIZE 512
#define DNBD3_BLOCK_SIZE 4096
#define NUMBER_DEVICES 8
-#define DEFAULT_READ_AHEAD_KB 256
+#define DEFAULT_READ_AHEAD_KB 512
// +++++ Misc +++++
#define DEFAULT_SERVER_CONFIG_FILE "/etc/dnbd3/server.conf"
diff --git a/src/kernel/net.c b/src/kernel/net.c
index 57279d6..b116ad6 100644
--- a/src/kernel/net.c
+++ b/src/kernel/net.c
@@ -124,6 +124,8 @@ int dnbd3_net_connect(dnbd3_device_t *dev)
struct timeval timeout;
+ char get_servers = 0, set_client = 0;
+
timeout.tv_sec = SOCKET_TIMEOUT_CLIENT_DATA;
timeout.tv_usec = 0;
@@ -136,11 +138,21 @@ int dnbd3_net_connect(dnbd3_device_t *dev)
memcpy(dev->alt_servers, &dev->initial_server, sizeof(dev->alt_servers[0]));
if (!dev->is_server)
{
- req1 = kmalloc(sizeof(*req1), GFP_ATOMIC);
- if (!req1)
- error_dev("FATAL: Kmalloc(1) failed.");
+ get_servers = 1;
}
}
+ if (dev->better_sock)
+ {
+ set_client = 1;
+ }
+
+ if (get_servers || set_client)
+ {
+ req1 = kmalloc(sizeof(*req1), GFP_ATOMIC);
+ if (!req1)
+ error_dev("FATAL: Kmalloc(1) failed.");
+ }
+
if (dev->cur_server.port == 0 || dev->cur_server.hostaddrtype == 0 || dev->imgname == NULL)
error_dev("FATAL: Host, port or image name not set.");
if (dev->sock)
@@ -224,6 +236,7 @@ int dnbd3_net_connect(dnbd3_device_t *dev)
// store image information
set_capacity(dev->disk, dev->reported_size >> 9); /* 512 Byte blocks */
debug_dev_va("INFO: Filesize: %llu.", dev->reported_size);
+ dev->update_available = 0;
}
else // Switching server, connection is already established and size request was executed
{
@@ -236,15 +249,20 @@ int dnbd3_net_connect(dnbd3_device_t *dev)
dev->panic = 0;
dev->panic_count = 0;
- dev->update_available = 0;
- if (req1) // This connection is established to the initial server (from the ioctl call)
+ if (get_servers) // This connection is established to the initial server (from the ioctl call)
{
// Enqueue request to request_queue_send for a fresh list of alt servers
req1->cmd_type = REQ_TYPE_SPECIAL;
req1->cmd_flags = CMD_GET_SERVERS;
list_add(&req1->queuelist, &dev->request_queue_send);
}
+ else if (set_client)
+ {
+ req1->cmd_type = REQ_TYPE_SPECIAL;
+ req1->cmd_flags = CMD_SET_CLIENT_MODE;
+ list_add(&req1->queuelist, &dev->request_queue_send);
+ }
// create required threads
dev->thread_send = kthread_create(dnbd3_net_send, dev, dev->disk->disk_name);
diff --git a/src/server/ipc.c b/src/server/ipc.c
index 37ca36f..e988abc 100644
--- a/src/server/ipc.c
+++ b/src/server/ipc.c
@@ -361,7 +361,7 @@ static int recv_data(int client_sock, void *buffer_out, int len)
*/
static int ipc_receive(int client_sock)
{
- GSList *iterator = NULL;
+ GSList *iterator, *iterator2;
struct tm *timeinfo;
#define STRBUFLEN 100
@@ -374,7 +374,7 @@ static int ipc_receive(int client_sock)
int ret, locked;
int return_value = 0;
xmlDocPtr docReply = NULL, docRequest = NULL;
- xmlNodePtr root_node, images_node, clients_node, tmp_node, log_parent_node, log_node;
+ xmlNodePtr root_node, parent_node, tmp_node, log_parent_node, log_node, server_node;
xmlChar *xmlbuff;
int buffersize;
@@ -420,10 +420,10 @@ static int ipc_receive(int client_sock)
xmlDocSetRootElement(docReply, root_node);
// Images
- images_node = xmlNewNode(NULL, BAD_CAST "images");
- if (images_node == NULL)
+ parent_node = xmlNewNode(NULL, BAD_CAST "images");
+ if (parent_node == NULL)
goto get_info_reply_cleanup;
- xmlAddChild(root_node, images_node);
+ xmlAddChild(root_node, parent_node);
locked = 1;
pthread_spin_lock(&_spinlock);
for (iterator = _dnbd3_images; iterator; iterator = iterator->next)
@@ -450,13 +450,18 @@ static int ipc_receive(int client_sock)
sprintf(strbuffer, "%d", complete / size);
xmlNewProp(tmp_node, BAD_CAST "cachefill", BAD_CAST image->cache_file);
}
- xmlAddChild(images_node, tmp_node);
+ xmlAddChild(parent_node, tmp_node);
}
+ pthread_spin_unlock(&_spinlock);
+ locked = 0;
+
// Clients
- clients_node = xmlNewNode(NULL, BAD_CAST "clients");
- if (clients_node == NULL)
+ parent_node = xmlNewNode(NULL, BAD_CAST "clients");
+ if (parent_node == NULL)
goto get_info_reply_cleanup;
- xmlAddChild(root_node, clients_node);
+ xmlAddChild(root_node, parent_node);
+ locked = 1;
+ pthread_spin_lock(&_spinlock);
for (iterator = _dnbd3_clients; iterator; iterator = iterator->next)
{
dnbd3_client_t *client = iterator->data;
@@ -469,7 +474,48 @@ static int ipc_receive(int client_sock)
inet_ntop(client->addrtype, client->ipaddr, strbuffer, STRBUFLEN);
xmlNewProp(tmp_node, BAD_CAST "ip", BAD_CAST strbuffer);
xmlNewProp(tmp_node, BAD_CAST "file", BAD_CAST client->image->file);
- xmlAddChild(clients_node, tmp_node);
+ xmlAddChild(parent_node, tmp_node);
+ }
+ }
+ pthread_spin_unlock(&_spinlock);
+ locked = 0;
+
+ // Trusted servers
+ parent_node = xmlNewNode(NULL, BAD_CAST "trusted");
+ if (parent_node == NULL)
+ goto get_info_reply_cleanup;
+ xmlAddChild(root_node, parent_node);
+ locked = 1;
+ pthread_spin_lock(&_spinlock);
+ for (iterator = _trusted_servers; iterator; iterator = iterator->next)
+ {
+ dnbd3_trusted_server_t *server = iterator->data;
+ if (server->hostaddrtype != 0)
+ {
+ tmp_node = xmlNewNode(NULL, BAD_CAST "server");
+ if (tmp_node == NULL)
+ goto get_info_reply_cleanup;
+ *strbuffer = '\0';
+ inet_ntop(server->hostaddrtype, server->hostaddr, strbuffer, STRBUFLEN);
+ xmlNewProp(tmp_node, BAD_CAST "ip", BAD_CAST strbuffer);
+ sprintf(strbuffer, "%d", (int)server->port);
+ xmlNewProp(tmp_node, BAD_CAST "port", BAD_CAST strbuffer);
+ if (server->comment)
+ xmlNewProp(tmp_node, BAD_CAST "comment", BAD_CAST server->comment);
+ for (iterator2 = server->namespaces; iterator2; iterator2 = iterator2->next)
+ {
+ const dnbd3_namespace_t *ns = iterator2->data;
+ server_node = xmlNewNode(NULL, BAD_CAST "namespace");
+ if (server_node == NULL)
+ goto get_info_reply_cleanup;
+ xmlAddChild(tmp_node, server_node);
+ xmlNewProp(server_node, BAD_CAST "name", BAD_CAST ns->name);
+ if (ns->auto_replicate)
+ xmlNewProp(server_node, BAD_CAST "replicate", BAD_CAST "1");
+ if (ns->recursive)
+ xmlNewProp(server_node, BAD_CAST "recursive", BAD_CAST "1");
+ }
+ xmlAddChild(parent_node, tmp_node);
}
}
pthread_spin_unlock(&_spinlock);
@@ -656,7 +702,7 @@ void dnbd3_ipc_send(int cmd)
{
int count;
int term_width = get_terminal_width();
- xmlNodePtr cur;
+ xmlNodePtr cur, childit;
// Print log
xmlChar *log = getTextFromPath(doc, "/data/log");
@@ -668,16 +714,15 @@ void dnbd3_ipc_send(int cmd)
int watime = 0, wname = 0, wrid = 5;
FOR_EACH_NODE(doc, "/data/images/image", cur)
{
- if (cur->type == XML_ELEMENT_NODE)
- {
- xmlChar *atime = xmlGetNoNsProp(cur, BAD_CAST "atime");
- xmlChar *vid = xmlGetNoNsProp(cur, BAD_CAST "name");
- xmlChar *rid = xmlGetNoNsProp(cur, BAD_CAST "rid");
- watime = MAX(watime, xmlStrlen(atime));
- wname = MAX(wname, xmlStrlen(vid));
- wrid = MAX(wrid, xmlStrlen(rid));
- // Too lazy to free vars, client will exit anyways
- }
+ if (cur->type != XML_ELEMENT_NODE)
+ continue;
+ xmlChar *atime = xmlGetNoNsProp(cur, BAD_CAST "atime");
+ xmlChar *vid = xmlGetNoNsProp(cur, BAD_CAST "name");
+ xmlChar *rid = xmlGetNoNsProp(cur, BAD_CAST "rid");
+ watime = MAX(watime, xmlStrlen(atime));
+ wname = MAX(wname, xmlStrlen(vid));
+ wrid = MAX(wrid, xmlStrlen(rid));
+ // Too lazy to free vars, client will exit anyways
} END_FOR_EACH;
char format[100];
@@ -691,16 +736,15 @@ void dnbd3_ipc_send(int cmd)
count = 0;
FOR_EACH_NODE(doc, "/data/images/image", cur)
{
- if (cur->type == XML_ELEMENT_NODE)
- {
- ++count;
- xmlChar *atime = xmlGetNoNsProp(cur, BAD_CAST "atime");
- xmlChar *vid = xmlGetNoNsProp(cur, BAD_CAST "name");
- xmlChar *rid = xmlGetNoNsProp(cur, BAD_CAST "rid");
- xmlChar *file = xmlGetNoNsProp(cur, BAD_CAST "file");
- printf(format, atime, vid, rid, file);
- // Too lazy to free vars, client will exit anyways
- }
+ if (cur->type != XML_ELEMENT_NODE)
+ continue;
+ ++count;
+ xmlChar *atime = xmlGetNoNsProp(cur, BAD_CAST "atime");
+ xmlChar *vid = xmlGetNoNsProp(cur, BAD_CAST "name");
+ xmlChar *rid = xmlGetNoNsProp(cur, BAD_CAST "rid");
+ xmlChar *file = xmlGetNoNsProp(cur, BAD_CAST "file");
+ printf(format, atime, vid, rid, file);
+ // Too lazy to free vars, client will exit anyways
} END_FOR_EACH;
char_repeat_br('=', term_width);
printf("\nNumber of images: %d\n\n", count);
@@ -711,17 +755,50 @@ void dnbd3_ipc_send(int cmd)
count = 0;
FOR_EACH_NODE(doc, "/data/clients/client", cur)
{
- if (cur->type == XML_ELEMENT_NODE)
+ if (cur->type != XML_ELEMENT_NODE)
+ continue;
+ ++count;
+ xmlChar *ip = xmlGetNoNsProp(cur, BAD_CAST "ip");
+ xmlChar *file = xmlGetNoNsProp(cur, BAD_CAST "file");
+ printf("%-40s %s\n", ip, file);
+ // Too lazy to free vars, client will exit anyways
+ } END_FOR_EACH;
+ char_repeat_br('=', term_width);
+ printf("\nNumber clients: %d\n\n", count);
+
+ // Print trusted servers
+ printf("Trusted servers:\n");
+ char_repeat_br('=', term_width);
+ count = 0;
+ FOR_EACH_NODE(doc, "/data/trusted/server", cur)
+ {
+ if (cur->type != XML_ELEMENT_NODE)
+ continue;
+ ++count;
+ xmlChar *ip = xmlGetNoNsProp(cur, BAD_CAST "ip");
+ xmlChar *comment = xmlGetNoNsProp(cur, BAD_CAST "comment");
+ if (comment)
+ printf("%-30s (%s)\n", ip, comment);
+ else
+ printf("%-30s\n", ip);
+ for (childit = cur->children; childit; childit = childit->next)
{
- ++count;
- xmlChar *ip = xmlGetNoNsProp(cur, BAD_CAST "ip");
- xmlChar *file = xmlGetNoNsProp(cur, BAD_CAST "file");
- printf("%-40s %s\n", ip, file);
- // Too lazy to free vars, client will exit anyways
+ if (childit->type != XML_ELEMENT_NODE || childit->name == NULL || strcmp(childit->name, "namespace") != 0)
+ continue;
+ xmlChar *name = xmlGetNoNsProp(childit, BAD_CAST "name");
+ xmlChar *replicate = xmlGetNoNsProp(childit, BAD_CAST "replicate");
+ xmlChar *recursive = xmlGetNoNsProp(childit, BAD_CAST "recursive");
+ printf(" %-40s ", name);
+ if (replicate && *replicate != '0')
+ printf(" replicate");
+ if (recursive && *recursive != '0')
+ printf(" recursive");
+ putchar('\n');
}
+ // Too lazy to free vars, client will exit anyways
} END_FOR_EACH;
char_repeat_br('=', term_width);
- printf("\nNumber clients: %d\n\n", count);
+ printf("\nNumber servers: %d\n\n", count);
// Cleanup
xmlFreeDoc(doc);
diff --git a/src/server/job.c b/src/server/job.c
index 8753c2c..b50a7f3 100644
--- a/src/server/job.c
+++ b/src/server/job.c
@@ -1,10 +1,13 @@
#include "job.h"
+#include "utils.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
+#include <sys/socket.h>
+#include <glib/gslist.h>
#define DEV_STRLEN 12 // INCLUDING NULLCHAR (increase to 13 if you need more than 100 (0-99) devices)
#define MAX_NUM_DEVICES_TO_CHECK 100
@@ -26,10 +29,13 @@ typedef struct
// "/dev/dnbdXX" == 11 bytes per device + nullchar = 12
static device_t *devices = NULL;
static int num_devices = 0;
-
static char keep_running = TRUE;
+// Private functions
static char* get_free_device();
+static void query_servers();
+
+//
void* dnbd3_job_thread(void *data)
{
@@ -38,7 +44,7 @@ void* dnbd3_job_thread(void *data)
char dev[DEV_STRLEN];
for (i = 0; i < MAX_NUM_DEVICES_TO_CHECK; ++i)
{
- sprintf(dev, "/dev/dnbd%d", i);
+ snprintf(dev, DEV_STRLEN, "/dev/dnbd%d", i);
if (access(dev, W_OK | R_OK)) // Need RW access to device to read and do ioctl
continue;
++num_devices;
@@ -49,7 +55,7 @@ void* dnbd3_job_thread(void *data)
for (i = 0, j = 0; i < MAX_NUM_DEVICES_TO_CHECK; ++i)
{
memset(dev, 0, DEV_STRLEN);
- sprintf(dev, "/dev/dnbd%d", i);
+ snprintf(dev, DEV_STRLEN, "/dev/dnbd%d", i);
if (access(dev, W_OK | R_OK))
continue;
if (j >= num_devices) // More available devices during second iteration? :-(
@@ -60,14 +66,26 @@ void* dnbd3_job_thread(void *data)
}
}
//
+ time_t next_delete_invocation = 0;
+ //
// Job/Watchdog mainloop
while (keep_running)
{
+ const time_t starttime = time(NULL);
+ //
// TODO: Update image atime
- // TODO: Handle image deletion
+ // Call image deletion function if last call is more than 5 minutes ago
+ if (starttime < next_delete_invocation)
+ {
+ next_delete_invocation = starttime + 300;
+ dnbd3_exec_delete(TRUE);
+ }
// TODO: Replicate proxied images (limited bandwidth)
- // TODO: Query other servers for new images/status/...
+ // Query other servers for new images/status/...
+ query_servers();
// TODO: Switch server of dnbd device based on more sophisticated inputs than just rtt
+ // Calc sleep timeout for next iteration
+ sleep(30 - (time(NULL) - starttime)); // Sleep 30 seconds, but account for the time it took to execute the loop
}
//
free(devices);
@@ -81,6 +99,17 @@ void dnbd3_job_shutdown()
keep_running = FALSE;
}
+static void query_servers()
+{
+ struct timeval client_timeout;
+ client_timeout.tv_sec = 0;
+ client_timeout.tv_usec = 500 * 1000;
+ int client_sock;
+ // Apply read/write timeout
+ setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, &client_timeout, sizeof(client_timeout));
+ setsockopt(client_sock, SOL_SOCKET, SO_SNDTIMEO, &client_timeout, sizeof(client_timeout));
+}
+
/**
* Get full name of an available dnbd3 device, eg. /dev/dnbd4
* Returned buffer is owned by this module, do not modify or free!
diff --git a/src/server/net.c b/src/server/net.c
index b953e13..bcbf056 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -361,6 +361,7 @@ void *dnbd3_handle_query(void *dnbd3_client)
case CMD_GET_SERVERS:
+ client->is_server = FALSE; // Only clients request list of servers
// Build list of known working alt servers
num = 0;
for (i = 0; i < NUMBER_SERVERS; i++)
@@ -379,6 +380,10 @@ void *dnbd3_handle_query(void *dnbd3_client)
send_reply(client->sock, &reply, NULL);
break;
+ case CMD_SET_CLIENT_MODE:
+ client->is_server = FALSE;
+ break;
+
default:
memlogf("ERROR: Unknown command\n");
break;
diff --git a/src/server/server.c b/src/server/server.c
index 1ca55fa..feee30b 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -47,6 +47,7 @@ char *_config_file_name = DEFAULT_SERVER_CONFIG_FILE;
char *_local_namespace = NULL;
char *_ipc_password = NULL;
GSList *_dnbd3_images = NULL; // of dnbd3_image_t
+GSList *_trusted_servers = NULL;
void dnbd3_print_help(char* argv_0)
{
@@ -211,7 +212,6 @@ int main(int argc, char* argv[])
struct sockaddr_in client;
unsigned int len = sizeof(client);
int fd;
- time_t next_delete_invocation = 0;
struct timeval timeout;
timeout.tv_sec = SOCKET_TIMEOUT_SERVER;
timeout.tv_usec = 0;
@@ -267,13 +267,6 @@ int main(int argc, char* argv[])
continue;
}
pthread_detach(dnbd3_client->thread);
- // Call image deletion function if last call is more than 5 minutes ago
- const time_t now = time(NULL);
- if (now < next_delete_invocation)
- {
- next_delete_invocation = now + 300;
- dnbd3_exec_delete(TRUE);
- }
}
dnbd3_cleanup();
diff --git a/src/server/server.h b/src/server/server.h
index 832777e..1e17048 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -64,10 +64,27 @@ typedef struct
dnbd3_image_t *image;
} dnbd3_client_t;
+typedef struct
+{
+ uint8_t hostaddr[16];
+ uint16_t port;
+ uint8_t hostaddrtype;
+ gchar *comment;
+ GSList *namespaces; // List of dnbd3_namespace_t
+} dnbd3_trusted_server_t;
+
+typedef struct
+{
+ char *name;
+ uint8_t auto_replicate;
+ uint8_t recursive;
+} dnbd3_namespace_t;
+
extern GSList *_dnbd3_clients; // of dnbd3_client_t
extern pthread_spinlock_t _spinlock;
extern char *_config_file_name, *_local_namespace, *_ipc_password;
extern GSList *_dnbd3_images; // of dnbd3_image_t
+extern GSList *_trusted_servers;
#ifdef _DEBUG
diff --git a/src/server/utils.c b/src/server/utils.c
index 391992d..dc3d6c4 100644
--- a/src/server/utils.c
+++ b/src/server/utils.c
@@ -120,7 +120,8 @@ static char is_valid_namespace(char *namespace)
while (*namespace)
{
if (*namespace != '/' && *namespace != '-' && (*namespace < 'a' || *namespace > 'z')
- && (*namespace < 'A' || *namespace > 'Z'))
+ && (*namespace < 'A' || *namespace > 'Z')
+ && (*namespace < '0' || *namespace > '9'))
return 0;
++namespace;
}
@@ -135,8 +136,10 @@ static char is_valid_imagename(char *namespace)
return 0; // Invalid: Length = 0 or starting with a space
while (*namespace)
{ // Check for invalid chars
- if (*namespace != '.' && *namespace != '-' && *namespace != ' ' && *namespace != '(' && *namespace != ')'
- && (*namespace < 'a' || *namespace > 'z') && (*namespace < 'A' || *namespace > 'Z'))
+ if (*namespace != '.' && *namespace != '-' && *namespace != ' '
+ && *namespace != '(' && *namespace != ')'
+ && (*namespace < 'a' || *namespace > 'z') && (*namespace < 'A' || *namespace > 'Z')
+ && (*namespace < '0' || *namespace > '9'))
return 0;
++namespace;
}
@@ -145,6 +148,13 @@ static char is_valid_imagename(char *namespace)
return 1;
}
+static inline int is_same_server(const dnbd3_trusted_server_t * const a, const dnbd3_trusted_server_t * const b)
+{
+ return (a->hostaddrtype == b->hostaddrtype)
+ && (a->port == b->port)
+ && (0 == memcmp(a->hostaddr, b->hostaddr, (a->hostaddrtype == AF_INET ? 4 : 16)));
+}
+
static void strtolower(char *string)
{
while (*string)
@@ -157,7 +167,7 @@ static void strtolower(char *string)
void dnbd3_load_config()
{
- gint i;
+ gint i, j;
if (_config_handle != NULL)
{
@@ -188,9 +198,32 @@ void dnbd3_load_config()
for (i = 0; i < section_count; i++)
{
- // Special group, ignore
- if (strcmp(groups[i], "settings") == 0 || strcmp(groups[i], "trusted") == 0)
+ // Ignore settings section
+ if (strcmp(groups[i], "settings") == 0)
+ continue;
+
+ // List of trusted servers/namespaces
+ if (strncmp(groups[i], "trust:", 6) == 0)
{
+ gchar *addr = g_key_file_get_string(_config_handle, groups[i], "address", NULL);
+ if (addr == NULL)
+ continue;
+ dnbd3_trusted_server_t *server = dnbd3_get_trusted_server(addr, TRUE);
+ g_free(addr);
+ if (server == NULL)
+ continue;
+ server->comment = strdup(groups[i]+6);
+ gsize key_count;
+ gchar **keys = g_key_file_get_keys(_config_handle, groups[i], &key_count, NULL);
+ for (j = 0; j < key_count; ++j)
+ {
+ if (strcmp(keys[j], "address") == 0)
+ continue;
+ char *flags = g_key_file_get_string(_config_handle, groups[i], keys[j], NULL);
+ dnbd3_add_trusted_namespace(server, keys[j], flags);
+ g_free(flags);
+ }
+ g_strfreev(keys);
continue;
}
@@ -216,13 +249,11 @@ void dnbd3_load_config()
gsize num_servers;
gchar **servers = g_key_file_get_string_list(_config_handle, groups[i], "servers", &num_servers, NULL);
- pthread_spin_lock(&_spinlock);
dnbd3_image_t *image = prepare_image(groups[i], rid, image_file, cache_file, servers, num_servers);
if (image)
{
_dnbd3_images = g_slist_prepend(_dnbd3_images, image);
}
- pthread_spin_unlock(&_spinlock);
g_free(image_file);
g_free(cache_file);
@@ -651,6 +682,70 @@ void dnbd3_exec_delete(int save_if_changed)
}
/**
+ * Return pointer to trusted_server matching given address.
+ * If not found and create_if_not_found is TRUE, a new entry will be created,
+ * added to the list and then returned
+ * Returns NULL otherwise, or if the address could not be parsed
+ * !! Lock before calling this function !!
+ */
+dnbd3_trusted_server_t *dnbd3_get_trusted_server(char *address, char create_if_not_found)
+{
+ dnbd3_trusted_server_t server;
+ memset(&server, 0, sizeof(server));
+ if (!parse_address(address, &server.hostaddrtype, server.hostaddr, &server.port))
+ {
+ memlogf("[WARNING] Could not parse address '%s' of trusted server", address);
+ return NULL;
+ }
+ GSList *iterator;
+ for (iterator = _trusted_servers; iterator; iterator = iterator->next)
+ {
+ dnbd3_trusted_server_t *comp = iterator->data;
+ if (is_same_server(comp, &server))
+ return comp;
+ }
+ if (!create_if_not_found)
+ return NULL;
+ dnbd3_trusted_server_t *copy = malloc(sizeof(server));
+ memcpy(copy, &server, sizeof(*copy));
+ _trusted_servers = g_slist_prepend(_trusted_servers, copy);
+ return copy;
+}
+
+/**
+ * Add new trusted namespace to given trusted server, using given flags.
+ * Overwrites any existing entry for the given server and namespace
+ * !! Lock before calling this function !!
+ */
+int dnbd3_add_trusted_namespace(dnbd3_trusted_server_t *server, char *namespace, char *flags)
+{
+ int nslen = strlen(namespace) + 1;
+ char nslow[nslen];
+ memcpy(nslow, namespace, nslen);
+ strtolower(nslow);
+ GSList *iterator;
+ dnbd3_namespace_t *ns = NULL;
+ for (iterator = server->namespaces; iterator; iterator = iterator->next)
+ {
+ dnbd3_namespace_t *cmp = iterator->data;
+ if (strcmp(nslow, cmp->name) == 0)
+ {
+ ns = cmp;
+ break;
+ }
+ }
+ if (ns == NULL)
+ {
+ ns = calloc(1, sizeof(*ns));
+ ns->name = strdup(nslow);
+ server->namespaces = g_slist_prepend(server->namespaces, ns);
+ }
+ ns->auto_replicate = (flags && strstr(flags, "replicate"));
+ ns->recursive = (flags && strstr(flags, "recursive"));
+ return TRUE;
+}
+
+/**
* Return local image name for a global image name
* eg. "uni-freiburg/rz/ubuntu 12.04" -> "ubuntu 12.04"
* ONLY IF the local name space really is "uni-freiburg/rz"
diff --git a/src/server/utils.h b/src/server/utils.h
index e923f82..53dc076 100644
--- a/src/server/utils.h
+++ b/src/server/utils.h
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <sys/types.h>
+#include "server.h"
#include "../config.h"
#ifndef UTILS_H_
@@ -48,6 +49,9 @@ void dnbd3_exec_delete(int save_if_changed);
dnbd3_image_t* dnbd3_get_image(char *name, int rid, const char do_lock);
+dnbd3_trusted_server_t *dnbd3_get_trusted_server(char *address, char create_if_not_found);
+int dnbd3_add_trusted_namespace(dnbd3_trusted_server_t *server, char *namespace, char *flags);
+
void dnbd3_handle_sigpipe(int signum);
void dnbd3_handle_sigterm(int signum);
diff --git a/src/types.h b/src/types.h
index ab3a2f0..72449da 100644
--- a/src/types.h
+++ b/src/types.h
@@ -74,12 +74,13 @@ typedef struct
} dnbd3_ioctl_t;
// network
-#define CMD_GET_BLOCK 1
-#define CMD_GET_SIZE 2
-#define CMD_GET_SERVERS 3
-#define CMD_ERROR 4
-#define CMD_KEEPALIVE 5
-#define CMD_LATEST_RID 6
+#define CMD_GET_BLOCK 1
+#define CMD_GET_SIZE 2
+#define CMD_GET_SERVERS 3
+#define CMD_ERROR 4
+#define CMD_KEEPALIVE 5
+#define CMD_LATEST_RID 6
+#define CMD_SET_CLIENT_MODE 7
#pragma pack(1)
typedef struct