diff options
author | sr | 2012-09-03 15:27:36 +0200 |
---|---|---|
committer | sr | 2012-09-03 15:27:36 +0200 |
commit | a55be46ec7a281f5c3d41d48edf32e57ef5e4ba1 (patch) | |
tree | d375eaf63e03a6e1b5e199712735a68b448c6d97 /src/server | |
parent | [SERVER] Add list of trusted servers and namespaces (load, display) (diff) | |
download | dnbd3-a55be46ec7a281f5c3d41d48edf32e57ef5e4ba1.tar.gz dnbd3-a55be46ec7a281f5c3d41d48edf32e57ef5e4ba1.tar.xz dnbd3-a55be46ec7a281f5c3d41d48edf32e57ef5e4ba1.zip |
[*] Fixed and unified formatting
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/ipc.c | 27 | ||||
-rw-r--r-- | src/server/ipc.h | 8 | ||||
-rw-r--r-- | src/server/job.c | 24 | ||||
-rw-r--r-- | src/server/job.h | 2 | ||||
-rw-r--r-- | src/server/memlog.c | 20 | ||||
-rw-r--r-- | src/server/memlog.h | 2 | ||||
-rw-r--r-- | src/server/net.c | 535 | ||||
-rw-r--r-- | src/server/server.c | 405 | ||||
-rw-r--r-- | src/server/server.h | 34 | ||||
-rw-r--r-- | src/server/utils.c | 121 | ||||
-rw-r--r-- | src/server/utils.h | 2 |
11 files changed, 599 insertions, 581 deletions
diff --git a/src/server/ipc.c b/src/server/ipc.c index e988abc..339dcc6 100644 --- a/src/server/ipc.c +++ b/src/server/ipc.c @@ -600,7 +600,8 @@ get_info_reply_cleanup: xmlFree(image.file); xmlFree(image.cache_file); } - } END_FOR_EACH; + } + END_FOR_EACH; if (count == 0) header.error = htonl(ERROR_MISSING_ARGUMENT); } @@ -723,11 +724,12 @@ void dnbd3_ipc_send(int cmd) wname = MAX(wname, xmlStrlen(vid)); wrid = MAX(wrid, xmlStrlen(rid)); // Too lazy to free vars, client will exit anyways - } END_FOR_EACH; + } + END_FOR_EACH; char format[100]; snprintf(format, 100, - "%%-%ds %%-%ds %%%ds %%s\n", watime, wname, wrid); + "%%-%ds %%-%ds %%%ds %%s\n", watime, wname, wrid); // Print images printf("Exported images\n"); @@ -745,7 +747,8 @@ void dnbd3_ipc_send(int cmd) 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; + } + END_FOR_EACH; char_repeat_br('=', term_width); printf("\nNumber of images: %d\n\n", count); @@ -762,7 +765,8 @@ void dnbd3_ipc_send(int cmd) 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; + } + END_FOR_EACH; char_repeat_br('=', term_width); printf("\nNumber clients: %d\n\n", count); @@ -796,7 +800,8 @@ void dnbd3_ipc_send(int cmd) putchar('\n'); } // Too lazy to free vars, client will exit anyways - } END_FOR_EACH; + } + END_FOR_EACH; char_repeat_br('=', term_width); printf("\nNumber servers: %d\n\n", count); @@ -831,7 +836,7 @@ static int is_password_correct(xmlDocPtr doc) xmlChar *pass = getTextFromPath(doc, "/data/password"); if (pass == NULL) return 0; - if (strcmp((char*)pass, _ipc_password) == 0) + if (strcmp((char *)pass, _ipc_password) == 0) { xmlFree(pass); return 1; @@ -842,8 +847,8 @@ static int is_password_correct(xmlDocPtr doc) static int get_terminal_width() { - struct winsize w; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) - return 80; - return w.ws_col; + struct winsize w; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) + return 80; + return w.ws_col; } diff --git a/src/server/ipc.h b/src/server/ipc.h index d4ec7db..36d1f60 100644 --- a/src/server/ipc.h +++ b/src/server/ipc.h @@ -27,7 +27,7 @@ #define IPC_ADDIMG 3 #define IPC_DELIMG 4 -void* dnbd3_ipc_mainloop(); +void *dnbd3_ipc_mainloop(); void dnbd3_ipc_shutdown(); @@ -38,9 +38,9 @@ void dnbd3_ipc_send(int cmd); typedef struct { uint32_t handle;// 4byte - uint32_t cmd; // 4byte - uint32_t size; // 4byte - uint32_t error; // 4byte + uint32_t cmd; // 4byte + uint32_t size; // 4byte + uint32_t error; // 4byte } dnbd3_ipc_t; #pragma pack(0) diff --git a/src/server/job.c b/src/server/job.c index b50a7f3..1f10cb6 100644 --- a/src/server/job.c +++ b/src/server/job.c @@ -32,12 +32,12 @@ static int num_devices = 0; static char keep_running = TRUE; // Private functions -static char* get_free_device(); +static char *get_free_device(); static void query_servers(); // -void* dnbd3_job_thread(void *data) +void *dnbd3_job_thread(void *data) { int i, j; // Determine number of available dnbd3 devices, which are needed for proxy mode @@ -74,18 +74,18 @@ void* dnbd3_job_thread(void *data) const time_t starttime = time(NULL); // // TODO: Update image atime - // 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); - } + // 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) // Query other servers for new images/status/... - query_servers(); + 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 + // 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); @@ -114,7 +114,7 @@ static void query_servers() * Get full name of an available dnbd3 device, eg. /dev/dnbd4 * Returned buffer is owned by this module, do not modify or free! */ -static char* get_free_device() +static char *get_free_device() { if (devices == NULL) return NULL; diff --git a/src/server/job.h b/src/server/job.h index 87be5d5..d8bb090 100644 --- a/src/server/job.h +++ b/src/server/job.h @@ -1,6 +1,6 @@ #ifndef JOB_H_ #define JOB_H_ -void* dnbd3_job_thread(void *data); +void *dnbd3_job_thread(void *data); #endif diff --git a/src/server/memlog.c b/src/server/memlog.c index 9809e64..6d4ec09 100644 --- a/src/server/memlog.c +++ b/src/server/memlog.c @@ -58,11 +58,11 @@ void memlogf(const char *fmt, ...) va_list ap; int ret; time_t rawtime; - struct tm * timeinfo; + struct tm *timeinfo; time(&rawtime); timeinfo = localtime(&rawtime); pthread_spin_lock(&logLock); - LogLine * const line = (LogLine *)&(logBuffer[bufferPos % LINE_COUNT]); + LogLine *const line = (LogLine *)&(logBuffer[bufferPos % LINE_COUNT]); const size_t offset = strftime(line->text, LINE_LEN, "[%d.%m. %H:%M:%S] ", timeinfo); if (offset == 0) *line->text = '\0'; va_start(ap, fmt); @@ -79,7 +79,7 @@ void memlogf(const char *fmt, ...) puts(line->text); } -char * fetchlog(int maxlines) +char *fetchlog(int maxlines) { if (!logBuffer) return NULL; if (maxlines <= 0 || maxlines > LINE_COUNT) maxlines = LINE_COUNT; @@ -88,8 +88,10 @@ char * fetchlog(int maxlines) //printf("Outputting log from %d to %d\n", start, bufferPos); pthread_spin_lock(&logLock); // Determine required buffer space for all log lines - for (i = start; i < bufferPos; ++i) { - if (logBuffer[i % LINE_COUNT].len > 0) { + for (i = start; i < bufferPos; ++i) + { + if (logBuffer[i % LINE_COUNT].len > 0) + { len += logBuffer[i % LINE_COUNT].len + 1; } } @@ -99,9 +101,11 @@ char * fetchlog(int maxlines) if (retval == NULL) goto endFunction; // Concatenate all log lines, delimit using '\n' char *pos = retval; - for (i = start; i < bufferPos; ++i) { - LogLine * const line = (LogLine *)&(logBuffer[i % LINE_COUNT]); - if (line->len > 0) { + for (i = start; i < bufferPos; ++i) + { + LogLine *const line = (LogLine *)&(logBuffer[i % LINE_COUNT]); + if (line->len > 0) + { memcpy(pos, (char *)line->text, line->len); pos += line->len; *pos++ = '\n'; diff --git a/src/server/memlog.h b/src/server/memlog.h index 24e3880..38c4349 100644 --- a/src/server/memlog.h +++ b/src/server/memlog.h @@ -34,6 +34,6 @@ void memlogf(char *text, ...); * Returns NULL on error * maxlines - Limit number of lines returned, 0 = everything */ -char * fetchlog(int maxlines); +char *fetchlog(int maxlines); #endif /* MEMLOG_H_ */ diff --git a/src/server/net.c b/src/server/net.c index bcbf056..afb7077 100644 --- a/src/server/net.c +++ b/src/server/net.c @@ -43,29 +43,29 @@ static inline char recv_request_header(int sock, dnbd3_request_t *request) { int ret; // Read request header from socket - if ((ret = recv(sock, request, sizeof(*request), MSG_WAITALL)) != sizeof(*request)) - { - if (ret == 0) return 0; - printf("[DEBUG] Error receiving request: Could not read message header (%d/%d)\n", ret, (int)sizeof(*request)); - return 0; - } - // Make sure all bytes are in the right order (endianness) - fixup_request(*request); - if (request->magic != dnbd3_packet_magic) - { - printf("[DEBUG] Magic in client request incorrect (cmd: %d, len: %d)\n", (int)request->cmd, (int)request->size); - return 0; - } - // Payload sanity check - if (request->cmd != CMD_GET_BLOCK && request->size > MAX_PAYLOAD) - { - memlogf("[WARNING] Client tries to send a packet of type %d with %d bytes payload. Dropping client.", (int)request->cmd, (int)request->size); - return 0; - } + if ((ret = recv(sock, request, sizeof(*request), MSG_WAITALL)) != sizeof(*request)) + { + if (ret == 0) return 0; + printf("[DEBUG] Error receiving request: Could not read message header (%d/%d)\n", ret, (int)sizeof(*request)); + return 0; + } + // Make sure all bytes are in the right order (endianness) + fixup_request(*request); + if (request->magic != dnbd3_packet_magic) + { + printf("[DEBUG] Magic in client request incorrect (cmd: %d, len: %d)\n", (int)request->cmd, (int)request->size); + return 0; + } + // Payload sanity check + if (request->cmd != CMD_GET_BLOCK && request->size > MAX_PAYLOAD) + { + memlogf("[WARNING] Client tries to send a packet of type %d with %d bytes payload. Dropping client.", (int)request->cmd, (int)request->size); + return 0; + } #ifdef _DEBUG - if (_fake_delay) usleep(_fake_delay); + if (_fake_delay) usleep(_fake_delay); #endif - return 1; + return 1; } static inline char recv_request_payload(int sock, uint32_t size, serialized_buffer_t *payload) @@ -120,44 +120,44 @@ static inline char send_reply(int sock, dnbd3_reply_t *reply, void *payload) void *dnbd3_handle_query(void *dnbd3_client) { - dnbd3_client_t *client = (dnbd3_client_t *) (uintptr_t) dnbd3_client; - dnbd3_request_t request; - dnbd3_reply_t reply; - - dnbd3_image_t *image = NULL; - int image_file = -1, image_cache = -1; - - int i, num; - - uint64_t map_y; - char map_x, bit_mask; - serialized_buffer_t payload; - char *image_name; - uint16_t rid, client_version; - - uint64_t todo_size = 0; - uint64_t todo_offset = 0; - uint64_t cur_offset = 0; - uint64_t last_offset = 0; - - dnbd3_server_entry_t server_list[NUMBER_SERVERS]; - - int dirty = 0; - - reply.magic = dnbd3_packet_magic; - - // Receive first packet. This must be CMD_GET_SIZE by protocol specification - if (recv_request_header(client->sock, &request)) - { - if (request.cmd != CMD_GET_SIZE) - { - printf("[DEBUG] Client sent invalid handshake (%d). Dropping Client\n", (int)request.cmd); - } - else - { - if (recv_request_payload(client->sock, request.size, &payload)) - { - client_version = serializer_get_uint16(&payload); + dnbd3_client_t *client = (dnbd3_client_t *) (uintptr_t) dnbd3_client; + dnbd3_request_t request; + dnbd3_reply_t reply; + + dnbd3_image_t *image = NULL; + int image_file = -1, image_cache = -1; + + int i, num; + + uint64_t map_y; + char map_x, bit_mask; + serialized_buffer_t payload; + char *image_name; + uint16_t rid, client_version; + + uint64_t todo_size = 0; + uint64_t todo_offset = 0; + uint64_t cur_offset = 0; + uint64_t last_offset = 0; + + dnbd3_server_entry_t server_list[NUMBER_SERVERS]; + + int dirty = 0; + + reply.magic = dnbd3_packet_magic; + + // Receive first packet. This must be CMD_GET_SIZE by protocol specification + if (recv_request_header(client->sock, &request)) + { + if (request.cmd != CMD_GET_SIZE) + { + printf("[DEBUG] Client sent invalid handshake (%d). Dropping Client\n", (int)request.cmd); + } + else + { + if (recv_request_payload(client->sock, request.size, &payload)) + { + client_version = serializer_get_uint16(&payload); image_name = serializer_get_string(&payload); rid = serializer_get_uint16(&payload); client->is_server = serializer_get_uint8(&payload); @@ -182,7 +182,7 @@ void *dnbd3_handle_query(void *dnbd3_client) printf("[DEBUG] Client requested non-existent image '%s' (rid:%d)\n", image_name, (int)rid); } else if ((image->delete_soft != 0 && image->delete_soft < now) - || (image->delete_hard != 0 && image->delete_hard < now)) + || (image->delete_hard != 0 && image->delete_hard < now)) { printf("[DEBUG] Client requested end-of-life image '%s' (rid:%d)\n", image_name, (int)rid); } @@ -220,221 +220,224 @@ void *dnbd3_handle_query(void *dnbd3_client) pthread_spin_unlock(&_spinlock); } } - } + } } - if (image) while (recv_request_header(client->sock, &request)) - { - switch (request.cmd) - { - - case CMD_GET_BLOCK: - if (request.offset >= image->filesize) - { // Sanity check - memlogf("[WARNING] Client requested non-existent block"); - reply.size = 0; - reply.cmd = CMD_ERROR; - send_reply(client->sock, &reply, NULL); - break; - } - if (request.offset + request.size > image->filesize) - { // Sanity check - memlogf("[WARNING] Client requested data block that extends beyond image size"); - reply.size = 0; - reply.cmd = CMD_ERROR; - send_reply(client->sock, &reply, NULL); - break; - } - if (request.size > image->filesize) - { // Sanity check - memlogf("[WARNING] Client requested data block that is bigger than the image size"); - reply.size = 0; - reply.cmd = CMD_ERROR; - send_reply(client->sock, &reply, NULL); - break; - } - - reply.cmd = CMD_GET_BLOCK; - reply.size = request.size; - reply.handle = request.handle; - - fixup_reply(reply); - if (send(client->sock, &reply, sizeof(dnbd3_reply_t), MSG_MORE) != sizeof(dnbd3_reply_t)) + if (image) while (recv_request_header(client->sock, &request)) + { + switch (request.cmd) { - printf("[DEBUG] Sending CMD_GET_BLOCK header failed\n"); - return 0; + + case CMD_GET_BLOCK: + if (request.offset >= image->filesize) + { + // Sanity check + memlogf("[WARNING] Client requested non-existent block"); + reply.size = 0; + reply.cmd = CMD_ERROR; + send_reply(client->sock, &reply, NULL); + break; + } + if (request.offset + request.size > image->filesize) + { + // Sanity check + memlogf("[WARNING] Client requested data block that extends beyond image size"); + reply.size = 0; + reply.cmd = CMD_ERROR; + send_reply(client->sock, &reply, NULL); + break; + } + if (request.size > image->filesize) + { + // Sanity check + memlogf("[WARNING] Client requested data block that is bigger than the image size"); + reply.size = 0; + reply.cmd = CMD_ERROR; + send_reply(client->sock, &reply, NULL); + break; + } + + reply.cmd = CMD_GET_BLOCK; + reply.size = request.size; + reply.handle = request.handle; + + fixup_reply(reply); + if (send(client->sock, &reply, sizeof(dnbd3_reply_t), MSG_MORE) != sizeof(dnbd3_reply_t)) + { + printf("[DEBUG] Sending CMD_GET_BLOCK header failed\n"); + return 0; + } + + if (request.size == 0) // Request for 0 bytes, done after sending header + break; + + // caching is off + if (image_cache == -1) + { + if (sendfile(client->sock, image_file, (off_t *)&request.offset, request.size) != request.size) + { + printf("[ERROR] sendfile failed (image to net)\n"); + close(client->sock); + client->sock = -1; + } + break; + } + + // caching is on + dirty = 0; + todo_size = 0; + todo_offset = request.offset; + cur_offset = request.offset; + last_offset = request.offset + request.size; + + // first make sure the whole requested part is in the local cache file + while(cur_offset < last_offset) + { + map_y = cur_offset >> 15; // div 32768 + map_x = (cur_offset >> 12) & 7; // (X div 4096) mod 8 + bit_mask = 0b00000001 << (map_x); + + cur_offset += 4096; + + if ((image->cache_map[map_y] & bit_mask) != 0) // cache hit + { + if (todo_size != 0) // fetch missing chunks + { + lseek(image_cache, todo_offset, SEEK_SET); + if (sendfile(image_cache, image_file, (off_t *) &todo_offset, todo_size) != todo_size) + { + printf("[ERROR] sendfile failed (copy to cache 1)\n"); + close(client->sock); + client->sock = -1; + // Reset these so we don't update the cache map with false information + dirty = 0; + todo_size = 0; + break; + } + todo_size = 0; + dirty = 1; + } + todo_offset = cur_offset; + } + else + { + todo_size += 4096; + } + } + + // whole request was missing + if (todo_size != 0) + { + lseek(image_cache, todo_offset, SEEK_SET); + if (sendfile(image_cache, image_file, (off_t *) &todo_offset, todo_size) != todo_size) + { + printf("[ERROR] sendfile failed (copy to cache 2)\n"); + close(client->sock); + client->sock = -1; + break; + } + dirty = 1; + } + + if (dirty) // cache map needs to be updated as something was missing locally + { + // set 1 in cache map for whole request + cur_offset = request.offset; + while(cur_offset < last_offset) + { + map_y = cur_offset >> 15; + map_x = (cur_offset >> 12) & 7; // mod 8 + bit_mask = 0b00000001 << (map_x); + image->cache_map[map_y] |= bit_mask; + cur_offset += 4096; + } + } + + // send data to client + if (sendfile(client->sock, image_cache, (off_t *) &request.offset, request.size) != request.size) + { + memlogf("[ERROR] sendfile failed (cache to net)\n"); + close(client->sock); + client->sock = -1; + } + break; + + + 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++) + { + if (image->servers[i].hostaddrtype == 0 || image->servers[i].failures > 200) continue; + memcpy(server_list + num++, image->servers + i, sizeof(dnbd3_server_entry_t)); + } + reply.cmd = CMD_GET_SERVERS; + reply.size = num * sizeof(dnbd3_server_entry_t); + send_reply(client->sock, &reply, server_list); + break; + + case CMD_KEEPALIVE: + reply.cmd = CMD_KEEPALIVE; + reply.size = 0; + send_reply(client->sock, &reply, NULL); + break; + + case CMD_SET_CLIENT_MODE: + client->is_server = FALSE; + break; + + default: + memlogf("ERROR: Unknown command\n"); + break; + } - if (request.size == 0) // Request for 0 bytes, done after sending header - break; - - // caching is off - if (image_cache == -1) - { - if (sendfile(client->sock, image_file, (off_t *)&request.offset, request.size) != request.size) - { - printf("[ERROR] sendfile failed (image to net)\n"); - close(client->sock); - client->sock = -1; - } - break; - } - - // caching is on - dirty = 0; - todo_size = 0; - todo_offset = request.offset; - cur_offset = request.offset; - last_offset = request.offset + request.size; - - // first make sure the whole requested part is in the local cache file - while(cur_offset < last_offset) - { - map_y = cur_offset >> 15; // div 32768 - map_x = (cur_offset >> 12) & 7; // (X div 4096) mod 8 - bit_mask = 0b00000001 << (map_x); - - cur_offset += 4096; - - if ((image->cache_map[map_y] & bit_mask) != 0) // cache hit - { - if (todo_size != 0) // fetch missing chunks - { - lseek(image_cache, todo_offset, SEEK_SET); - if (sendfile(image_cache, image_file, (off_t *) &todo_offset, todo_size) != todo_size) - { - printf("[ERROR] sendfile failed (copy to cache 1)\n"); - close(client->sock); - client->sock = -1; - // Reset these so we don't update the cache map with false information - dirty = 0; - todo_size = 0; - break; - } - todo_size = 0; - dirty = 1; - } - todo_offset = cur_offset; - } - else - { - todo_size += 4096; - } - } - - // whole request was missing - if (todo_size != 0) - { - lseek(image_cache, todo_offset, SEEK_SET); - if (sendfile(image_cache, image_file, (off_t *) &todo_offset, todo_size) != todo_size) - { - printf("[ERROR] sendfile failed (copy to cache 2)\n"); - close(client->sock); - client->sock = -1; - break; - } - dirty = 1; - } - - if (dirty) // cache map needs to be updated as something was missing locally - { - // set 1 in cache map for whole request - cur_offset = request.offset; - while(cur_offset < last_offset) - { - map_y = cur_offset >> 15; - map_x = (cur_offset >> 12) & 7; // mod 8 - bit_mask = 0b00000001 << (map_x); - image->cache_map[map_y] |= bit_mask; - cur_offset += 4096; - } - } - - // send data to client - if (sendfile(client->sock, image_cache, (off_t *) &request.offset, request.size) != request.size) - { - memlogf("[ERROR] sendfile failed (cache to net)\n"); - close(client->sock); - client->sock = -1; - } - break; - - - 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++) - { - if (image->servers[i].hostaddrtype == 0 || image->servers[i].failures > 200) continue; - memcpy(server_list + num++, image->servers + i, sizeof(dnbd3_server_entry_t)); - } - reply.cmd = CMD_GET_SERVERS; - reply.size = num * sizeof(dnbd3_server_entry_t); - send_reply(client->sock, &reply, server_list); - break; - - case CMD_KEEPALIVE: - reply.cmd = CMD_KEEPALIVE; - reply.size = 0; - send_reply(client->sock, &reply, NULL); - break; - - case CMD_SET_CLIENT_MODE: - client->is_server = FALSE; - break; - - default: - memlogf("ERROR: Unknown command\n"); - break; - - } - - } - pthread_spin_lock(&_spinlock); - _dnbd3_clients = g_slist_remove(_dnbd3_clients, client); - pthread_spin_unlock(&_spinlock); - if (client->sock != -1) - close(client->sock); - if (image_file != -1) close(image_file); - if (image_cache != -1) close(image_cache); - g_free(client); - pthread_exit((void *) 0); + } + pthread_spin_lock(&_spinlock); + _dnbd3_clients = g_slist_remove(_dnbd3_clients, client); + pthread_spin_unlock(&_spinlock); + if (client->sock != -1) + close(client->sock); + if (image_file != -1) close(image_file); + if (image_cache != -1) close(image_cache); + g_free(client); + pthread_exit((void *) 0); } int dnbd3_setup_socket() { - int sock; - struct sockaddr_in server; - - // Create socket - sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock < 0) - { - memlogf("ERROR: Socket setup failure\n"); - return -1; - } - const int opt = 1; + int sock; + struct sockaddr_in server; + + // Create socket + sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock < 0) + { + memlogf("ERROR: Socket setup failure\n"); + return -1; + } + const int opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - memset(&server, 0, sizeof(server)); - server.sin_family = AF_INET; // IPv4 - server.sin_addr.s_addr = htonl(INADDR_ANY); // Take all IPs - server.sin_port = htons(PORT); // set port number - - // Bind to socket - if (bind(sock, (struct sockaddr*) &server, sizeof(server)) < 0) - { - memlogf("ERROR: Bind failure\n"); - return -1; - } - - // Listen on socket - if (listen(sock, 100) == -1) - { - memlogf("ERROR: Listen failure\n"); - return -1; - } - - return sock; + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; // IPv4 + server.sin_addr.s_addr = htonl(INADDR_ANY); // Take all IPs + server.sin_port = htons(PORT); // set port number + + // Bind to socket + if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) + { + memlogf("ERROR: Bind failure\n"); + return -1; + } + + // Listen on socket + if (listen(sock, 100) == -1) + { + memlogf("ERROR: Listen failure\n"); + return -1; + } + + return sock; } diff --git a/src/server/server.c b/src/server/server.c index feee30b..9fc5383 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -49,225 +49,226 @@ char *_ipc_password = NULL; GSList *_dnbd3_images = NULL; // of dnbd3_image_t GSList *_trusted_servers = NULL; -void dnbd3_print_help(char* argv_0) +void dnbd3_print_help(char *argv_0) { - printf("Usage: %s [OPTIONS]...\n", argv_0); - printf("Start the DNBD3 server\n"); - printf("-f or --file Configuration file (default /etc/dnbd3-server.conf)\n"); + printf("Usage: %s [OPTIONS]...\n", argv_0); + printf("Start the DNBD3 server\n"); + printf("-f or --file Configuration file (default /etc/dnbd3-server.conf)\n"); #ifdef _DEBUG - printf("-d or --delay Add a fake network delay of X µs\n"); + printf("-d or --delay Add a fake network delay of X µs\n"); #endif - printf("-n or --nodaemon Start server in foreground\n"); - printf("-r or --reload Reload configuration file\n"); - printf("-s or --stop Stop running dnbd3-server\n"); - printf("-i or --info Print connected clients and used images\n"); - printf("-H or --help Show this help text and quit\n"); - printf("-V or --version Show version and quit\n"); - exit(0); + printf("-n or --nodaemon Start server in foreground\n"); + printf("-r or --reload Reload configuration file\n"); + printf("-s or --stop Stop running dnbd3-server\n"); + printf("-i or --info Print connected clients and used images\n"); + printf("-H or --help Show this help text and quit\n"); + printf("-V or --version Show version and quit\n"); + exit(0); } void dnbd3_print_version() { - printf("Version: %s\n", VERSION_STRING); - exit(0); + printf("Version: %s\n", VERSION_STRING); + exit(0); } void dnbd3_cleanup() { - int fd; - memlogf("INFO: Cleanup...\n"); - - close(sock); - sock = -1; - - dnbd3_ipc_shutdown(); - - pthread_spin_lock(&_spinlock); - GSList *iterator = NULL; - for (iterator = _dnbd3_clients; iterator; iterator = iterator->next) - { - dnbd3_client_t *client = iterator->data; - shutdown(client->sock, SHUT_RDWR); - pthread_join(client->thread, NULL); - g_free(client); - } - g_slist_free(_dnbd3_clients); - - - for (iterator = _dnbd3_images; iterator; iterator = iterator->next) - { - // save cache maps to files - dnbd3_image_t *image = iterator->data; - if (image->cache_file) - { - char tmp[strlen(image->cache_file)+4]; - strcpy(tmp, image->cache_file); - strcat(tmp, ".map"); - fd = open(tmp, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); - - if (fd > 0) - write(fd, image->cache_map, ((image->filesize + (1 << 15) - 1) >> 15) * sizeof(char)); - - close(fd); - } - - free(image->cache_map); - free(image->config_group); - free(image->low_name); - free(image->file); - free(image->cache_file); - g_free(image); - } - g_slist_free(_dnbd3_images); - - pthread_spin_unlock(&_spinlock); + int fd; + memlogf("INFO: Cleanup...\n"); + + close(sock); + sock = -1; + + dnbd3_ipc_shutdown(); + + pthread_spin_lock(&_spinlock); + GSList *iterator = NULL; + for (iterator = _dnbd3_clients; iterator; iterator = iterator->next) + { + dnbd3_client_t *client = iterator->data; + shutdown(client->sock, SHUT_RDWR); + pthread_join(client->thread, NULL); + g_free(client); + } + g_slist_free(_dnbd3_clients); + + + for (iterator = _dnbd3_images; iterator; iterator = iterator->next) + { + // save cache maps to files + dnbd3_image_t *image = iterator->data; + if (image->cache_file) + { + char tmp[strlen(image->cache_file)+4]; + strcpy(tmp, image->cache_file); + strcat(tmp, ".map"); + fd = open(tmp, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + + if (fd > 0) + write(fd, image->cache_map, ((image->filesize + (1 << 15) - 1) >> 15) * sizeof(char)); + + close(fd); + } + + free(image->cache_map); + free(image->config_group); + free(image->low_name); + free(image->file); + free(image->cache_file); + g_free(image); + } + g_slist_free(_dnbd3_images); + + pthread_spin_unlock(&_spinlock); #ifndef IPC_TCP - unlink(UNIX_SOCKET); + unlink(UNIX_SOCKET); #endif - exit(EXIT_SUCCESS); + exit(EXIT_SUCCESS); } -int main(int argc, char* argv[]) +int main(int argc, char *argv[]) { - int demonize = 1; - int opt = 0; - int longIndex = 0; - static const char *optString = "f:d:nrsiHV?"; - static const struct option longOpts[] = - { - { "file", required_argument, NULL, 'f' }, - { "delay", required_argument, NULL, 'd' }, - { "nodaemon", no_argument, NULL, 'n' }, - { "reload", no_argument, NULL, 'r' }, - { "stop", no_argument, NULL, 's' }, - { "info", no_argument, NULL, 'i' }, - { "help", no_argument, NULL, 'H' }, - { "version", no_argument, NULL, 'V' } }; - - opt = getopt_long(argc, argv, optString, longOpts, &longIndex); - - while (opt != -1) - { - switch (opt) - { - case 'f': - _config_file_name = strdup(optarg); - break; - case 'd': + int demonize = 1; + int opt = 0; + int longIndex = 0; + static const char *optString = "f:d:nrsiHV?"; + static const struct option longOpts[] = + { + { "file", required_argument, NULL, 'f' }, + { "delay", required_argument, NULL, 'd' }, + { "nodaemon", no_argument, NULL, 'n' }, + { "reload", no_argument, NULL, 'r' }, + { "stop", no_argument, NULL, 's' }, + { "info", no_argument, NULL, 'i' }, + { "help", no_argument, NULL, 'H' }, + { "version", no_argument, NULL, 'V' } + }; + + opt = getopt_long(argc, argv, optString, longOpts, &longIndex); + + while (opt != -1) + { + switch (opt) + { + case 'f': + _config_file_name = strdup(optarg); + break; + case 'd': #ifdef _DEBUG - _fake_delay = atoi(optarg); - break; + _fake_delay = atoi(optarg); + break; #else - printf("This option is only available in debug builds.\n\n"); - return EXIT_FAILURE; + printf("This option is only available in debug builds.\n\n"); + return EXIT_FAILURE; #endif - case 'n': - demonize = 0; - break; - case 'r': - printf("INFO: Reloading configuration file...\n\n"); - dnbd3_ipc_send(IPC_RELOAD); - return EXIT_SUCCESS; - case 's': - printf("INFO: Stopping running server...\n\n"); - dnbd3_ipc_send(IPC_EXIT); - return EXIT_SUCCESS; - case 'i': - printf("INFO: Requesting information...\n\n"); - dnbd3_ipc_send(IPC_INFO); - return EXIT_SUCCESS; - case 'H': - dnbd3_print_help(argv[0]); - break; - case 'V': - dnbd3_print_version(); - break; - case '?': - dnbd3_print_help(argv[0]); - break; - } - opt = getopt_long(argc, argv, optString, longOpts, &longIndex); - } - - if (demonize) - daemon(1, 0); - - pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE); - - initmemlog(); - memlogf("DNBD3 server starting.... Machine type: " ENDIAN_MODE); - - // load config file - dnbd3_load_config(); - - // setup signal handler - signal(SIGPIPE, dnbd3_handle_sigpipe); - signal(SIGTERM, dnbd3_handle_sigterm); - signal(SIGINT, dnbd3_handle_sigterm); - - // setup network - sock = dnbd3_setup_socket(); - if (sock < 0) - exit(EXIT_FAILURE); - struct sockaddr_in client; - unsigned int len = sizeof(client); - int fd; - struct timeval timeout; - timeout.tv_sec = SOCKET_TIMEOUT_SERVER; - timeout.tv_usec = 0; - - // setup ipc - pthread_t thread_ipc; - pthread_create(&(thread_ipc), NULL, &dnbd3_ipc_mainloop, NULL); - - memlogf("[INFO] Server is ready..."); - - // main loop - while (1) - { - fd = accept(sock, (struct sockaddr*) &client, &len); - if (fd < 0) - { - memlogf("[ERROR] Accept failure"); - continue; - } - //memlogf("INFO: Client %s connected\n", inet_ntoa(client.sin_addr)); - - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof(timeout)); - setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, sizeof(timeout)); - - dnbd3_client_t *dnbd3_client = g_new0(dnbd3_client_t, 1); - if (dnbd3_client == NULL) - { - memlogf("[ERROR] Could not alloc dnbd3_client_t for new client."); - close(fd); - continue; - } - // TODO: Extend this if you ever want to add IPv6 (something like:) - // dnbd3_client->addrtype = AF_INET6; - // memcpy(dnbd3_client->ipaddr, &(client.sin6_addr), 16); - dnbd3_client->addrtype = AF_INET; - memcpy(dnbd3_client->ipaddr, &(client.sin_addr), 4); - dnbd3_client->sock = fd; - dnbd3_client->image = NULL; - - // This has to be done before creating the thread, otherwise a race condition might occur when the new thread dies faster than this thread adds the client to the list after creating the thread - pthread_spin_lock(&_spinlock); - _dnbd3_clients = g_slist_prepend(_dnbd3_clients, dnbd3_client); - pthread_spin_unlock(&_spinlock); - - if (0 != pthread_create(&(dnbd3_client->thread), NULL, dnbd3_handle_query, (void *) (uintptr_t) dnbd3_client)) - { - memlogf("[ERROR] Could not start thread for new client."); - pthread_spin_lock(&_spinlock); - _dnbd3_clients = g_slist_remove(_dnbd3_clients, dnbd3_client); - pthread_spin_unlock(&_spinlock); - g_free(dnbd3_client); - close(fd); - continue; - } - pthread_detach(dnbd3_client->thread); - } - - dnbd3_cleanup(); + case 'n': + demonize = 0; + break; + case 'r': + printf("INFO: Reloading configuration file...\n\n"); + dnbd3_ipc_send(IPC_RELOAD); + return EXIT_SUCCESS; + case 's': + printf("INFO: Stopping running server...\n\n"); + dnbd3_ipc_send(IPC_EXIT); + return EXIT_SUCCESS; + case 'i': + printf("INFO: Requesting information...\n\n"); + dnbd3_ipc_send(IPC_INFO); + return EXIT_SUCCESS; + case 'H': + dnbd3_print_help(argv[0]); + break; + case 'V': + dnbd3_print_version(); + break; + case '?': + dnbd3_print_help(argv[0]); + break; + } + opt = getopt_long(argc, argv, optString, longOpts, &longIndex); + } + + if (demonize) + daemon(1, 0); + + pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE); + + initmemlog(); + memlogf("DNBD3 server starting.... Machine type: " ENDIAN_MODE); + + // load config file + dnbd3_load_config(); + + // setup signal handler + signal(SIGPIPE, dnbd3_handle_sigpipe); + signal(SIGTERM, dnbd3_handle_sigterm); + signal(SIGINT, dnbd3_handle_sigterm); + + // setup network + sock = dnbd3_setup_socket(); + if (sock < 0) + exit(EXIT_FAILURE); + struct sockaddr_in client; + unsigned int len = sizeof(client); + int fd; + struct timeval timeout; + timeout.tv_sec = SOCKET_TIMEOUT_SERVER; + timeout.tv_usec = 0; + + // setup ipc + pthread_t thread_ipc; + pthread_create(&(thread_ipc), NULL, &dnbd3_ipc_mainloop, NULL); + + memlogf("[INFO] Server is ready..."); + + // main loop + while (1) + { + fd = accept(sock, (struct sockaddr *) &client, &len); + if (fd < 0) + { + memlogf("[ERROR] Accept failure"); + continue; + } + //memlogf("INFO: Client %s connected\n", inet_ntoa(client.sin_addr)); + + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof(timeout)); + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, sizeof(timeout)); + + dnbd3_client_t *dnbd3_client = g_new0(dnbd3_client_t, 1); + if (dnbd3_client == NULL) + { + memlogf("[ERROR] Could not alloc dnbd3_client_t for new client."); + close(fd); + continue; + } + // TODO: Extend this if you ever want to add IPv6 (something like:) + // dnbd3_client->addrtype = AF_INET6; + // memcpy(dnbd3_client->ipaddr, &(client.sin6_addr), 16); + dnbd3_client->addrtype = AF_INET; + memcpy(dnbd3_client->ipaddr, &(client.sin_addr), 4); + dnbd3_client->sock = fd; + dnbd3_client->image = NULL; + + // This has to be done before creating the thread, otherwise a race condition might occur when the new thread dies faster than this thread adds the client to the list after creating the thread + pthread_spin_lock(&_spinlock); + _dnbd3_clients = g_slist_prepend(_dnbd3_clients, dnbd3_client); + pthread_spin_unlock(&_spinlock); + + if (0 != pthread_create(&(dnbd3_client->thread), NULL, dnbd3_handle_query, (void *) (uintptr_t) dnbd3_client)) + { + memlogf("[ERROR] Could not start thread for new client."); + pthread_spin_lock(&_spinlock); + _dnbd3_clients = g_slist_remove(_dnbd3_clients, dnbd3_client); + pthread_spin_unlock(&_spinlock); + g_free(dnbd3_client); + close(fd); + continue; + } + pthread_detach(dnbd3_client->thread); + } + + dnbd3_cleanup(); } diff --git a/src/server/server.h b/src/server/server.h index 1e17048..c608066 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -41,27 +41,27 @@ typedef struct { char *config_group; // exact name of group in config file that represents this image char *low_name; // full (global) name of image, lowercased for comparison, eg. "uni-freiburg/rz/ubuntu-12.04" - int rid; // revision of provided image - char *file; // path to image file or device - uint64_t filesize; // size of image - dnbd3_server_entry_t servers[NUMBER_SERVERS]; // known alt servers that also offer that image - time_t atime; // last access time - uint8_t *cache_map; // cache map telling which parts are locally cached - char *cache_file; // path to local cache of image (in case the image is read from a dnbd3 device) - char working; // whether this image is considered working. local images are "working" if the local file exists, proxied images have to have at least one working upstream server or a complete local cache file - time_t delete_soft; // unixtime telling when this image should be deleted. if there are still clients using this image it weill be kept, but new clients requesting the image will be rejected. 0 = never - time_t delete_hard; // unixtime telling when this image should be deleted, no matter if there are still clients connected. 0 = never - uint8_t relayed; // TRUE if relayed from other server (needs dnbd3 client module loaded) + int rid; // revision of provided image + char *file; // path to image file or device + uint64_t filesize; // size of image + dnbd3_server_entry_t servers[NUMBER_SERVERS]; // known alt servers that also offer that image + time_t atime; // last access time + uint8_t *cache_map; // cache map telling which parts are locally cached + char *cache_file; // path to local cache of image (in case the image is read from a dnbd3 device) + char working; // whether this image is considered working. local images are "working" if the local file exists, proxied images have to have at least one working upstream server or a complete local cache file + time_t delete_soft; // unixtime telling when this image should be deleted. if there are still clients using this image it weill be kept, but new clients requesting the image will be rejected. 0 = never + time_t delete_hard; // unixtime telling when this image should be deleted, no matter if there are still clients connected. 0 = never + uint8_t relayed; // TRUE if relayed from other server (needs dnbd3 client module loaded) } dnbd3_image_t; typedef struct { - int sock; - uint8_t ipaddr[16]; - uint8_t addrtype; // ip version (AF_INET or AF_INET6) - uint8_t is_server; // TRUE if a server in proxy mode, FALSE if real client - pthread_t thread; - dnbd3_image_t *image; + int sock; + uint8_t ipaddr[16]; + uint8_t addrtype; // ip version (AF_INET or AF_INET6) + uint8_t is_server; // TRUE if a server in proxy mode, FALSE if real client + pthread_t thread; + dnbd3_image_t *image; } dnbd3_client_t; typedef struct diff --git a/src/server/utils.c b/src/server/utils.c index dc3d6c4..ad40322 100644 --- a/src/server/utils.c +++ b/src/server/utils.c @@ -32,13 +32,13 @@ #include "memlog.h" // Keep parsed config file in memory so it doesn't need to be parsed again every time it's modified -static GKeyFile* _config_handle = NULL; +static GKeyFile *_config_handle = NULL; static char parse_address(char *string, uint8_t *af, uint8_t *addr, uint16_t *port); static char is_valid_namespace(char *namespace); static char is_valid_imagename(char *namespace); static void strtolower(char *string); -static dnbd3_image_t* prepare_image(char *image_name, int rid, char *image_file, char *cache_file, gchar **servers, gsize num_servers); +static dnbd3_image_t *prepare_image(char *image_name, int rid, char *image_file, char *cache_file, gchar **servers, gsize num_servers); static int save_config(); //static char* get_local_image_name(char *global_name); @@ -120,8 +120,8 @@ static char is_valid_namespace(char *namespace) while (*namespace) { if (*namespace != '/' && *namespace != '-' && (*namespace < 'a' || *namespace > 'z') - && (*namespace < 'A' || *namespace > 'Z') - && (*namespace < '0' || *namespace > '9')) + && (*namespace < 'A' || *namespace > 'Z') + && (*namespace < '0' || *namespace > '9')) return 0; ++namespace; } @@ -135,11 +135,12 @@ static char is_valid_imagename(char *namespace) if (*namespace == '\0' || *namespace == ' ') return 0; // Invalid: Length = 0 or starting with a space while (*namespace) - { // Check for invalid chars + { + // Check for invalid chars if (*namespace != '.' && *namespace != '-' && *namespace != ' ' - && *namespace != '(' && *namespace != ')' - && (*namespace < 'a' || *namespace > 'z') && (*namespace < 'A' || *namespace > 'Z') - && (*namespace < '0' || *namespace > '9')) + && *namespace != '(' && *namespace != ')' + && (*namespace < 'a' || *namespace > 'z') && (*namespace < 'A' || *namespace > 'Z') + && (*namespace < '0' || *namespace > '9')) return 0; ++namespace; } @@ -148,11 +149,11 @@ 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) +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))); + && (a->port == b->port) + && (0 == memcmp(a->hostaddr, b->hostaddr, (a->hostaddrtype == AF_INET ? 4 : 16))); } static void strtolower(char *string) @@ -220,6 +221,7 @@ void dnbd3_load_config() if (strcmp(keys[j], "address") == 0) continue; char *flags = g_key_file_get_string(_config_handle, groups[i], keys[j], NULL); + g_key_file_remove_key(_config_handle, groups[i], keys[j], NULL); dnbd3_add_trusted_namespace(server, keys[j], flags); g_free(flags); } @@ -290,19 +292,19 @@ int dnbd3_add_image(dnbd3_image_t *image) } // Adding image was successful, write config file - g_key_file_set_integer(_config_handle, image->config_group, "rid", image->rid); - g_key_file_set_string(_config_handle, image->config_group, "file", image->file); - //g_key_file_set_string(_config_handle, image->name, "servers", image->serverss); // TODO: Save servers as string - g_key_file_set_string(_config_handle, image->config_group, "cache", image->cache_file); - - pthread_spin_unlock(&_spinlock); - - const int ret = save_config(); - if (ret == ERROR_OK) - memlogf("[INFO] Added new image '%s' (rid %d)", newimage->config_group, newimage->rid); - else - memlogf("[INFO] Added new image '%s' (rid %d), but config file could not be written (%s)", newimage->config_group, newimage->rid, _config_file_name); - return ret; + g_key_file_set_integer(_config_handle, image->config_group, "rid", image->rid); + g_key_file_set_string(_config_handle, image->config_group, "file", image->file); + //g_key_file_set_string(_config_handle, image->name, "servers", image->serverss); // TODO: Save servers as string + g_key_file_set_string(_config_handle, image->config_group, "cache", image->cache_file); + + pthread_spin_unlock(&_spinlock); + + const int ret = save_config(); + if (ret == ERROR_OK) + memlogf("[INFO] Added new image '%s' (rid %d)", newimage->config_group, newimage->rid); + else + memlogf("[INFO] Added new image '%s' (rid %d), but config file could not be written (%s)", newimage->config_group, newimage->rid, _config_file_name); + return ret; } int dnbd3_del_image(dnbd3_image_t *image) @@ -326,41 +328,41 @@ int dnbd3_del_image(dnbd3_image_t *image) dnbd3_exec_delete(FALSE); existing_image = NULL; - const int ret = save_config(); - if (ret == ERROR_OK) - memlogf("[INFO] Marked for deletion: '%s' (rid %d)", image->config_group, image->rid); - else - memlogf("[WARNING] Marked for deletion: '%s' (rid %d), but config file could not be written (%s)", image->config_group, image->rid, _config_file_name); - return ret; + const int ret = save_config(); + if (ret == ERROR_OK) + memlogf("[INFO] Marked for deletion: '%s' (rid %d)", image->config_group, image->rid); + else + memlogf("[WARNING] Marked for deletion: '%s' (rid %d), but config file could not be written (%s)", image->config_group, image->rid, _config_file_name); + return ret; } static int save_config() { pthread_spin_lock(&_spinlock); - char* data = (char*)g_key_file_to_data(_config_handle, NULL, NULL); - if (data == NULL) - { - pthread_spin_unlock(&_spinlock); - memlogf("[ERROR] g_key_file_to_data() failed"); - return ERROR_UNSPECIFIED_ERROR; - } - - FILE *f = fopen(_config_file_name, "w"); - if (f < 0) - { - pthread_spin_unlock(&_spinlock); - g_free(data); - return ERROR_CONFIG_FILE_PERMISSIONS; - } - fputs("# Do not edit this file while dnbd3-server is running\n", f); - fputs(data, f); - fclose(f); - pthread_spin_unlock(&_spinlock); - g_free(data); - return 0; + char *data = (char *)g_key_file_to_data(_config_handle, NULL, NULL); + if (data == NULL) + { + pthread_spin_unlock(&_spinlock); + memlogf("[ERROR] g_key_file_to_data() failed"); + return ERROR_UNSPECIFIED_ERROR; + } + + FILE *f = fopen(_config_file_name, "w"); + if (f < 0) + { + pthread_spin_unlock(&_spinlock); + g_free(data); + return ERROR_CONFIG_FILE_PERMISSIONS; + } + fputs("# Do not edit this file while dnbd3-server is running\n", f); + fputs(data, f); + fclose(f); + pthread_spin_unlock(&_spinlock); + g_free(data); + return 0; } -dnbd3_image_t* dnbd3_get_image(char *name_orig, int rid, const char do_lock) +dnbd3_image_t *dnbd3_get_image(char *name_orig, int rid, const char do_lock) { dnbd3_image_t *result = NULL, *image; GSList *iterator; @@ -450,7 +452,8 @@ static dnbd3_image_t *prepare_image(char *image_name, int rid, char *image_file, } if (strchr(image_name, '/') == NULL) - { // Local image, build global name + { + // Local image, build global name image->low_name = calloc(strlen(_local_namespace) + strlen(image_name) + 2, sizeof(char)); sprintf(image->low_name, "%s/%s", _local_namespace, image_name); } @@ -494,14 +497,14 @@ static dnbd3_image_t *prepare_image(char *image_name, int rid, char *image_file, if (size <= 0) { memlogf("[ERROR] File '%s' of image '%s' has size '%lld'. Image ignored.", - image->file, image_name, (long long)size); + image->file, image_name, (long long)size); goto error; } image->filesize = (uint64_t)size; if (image->filesize & 4095) { memlogf("[WARNING] Size of image '%s' is not a multiple of 4096. Last incomplete block will be ignored!", - image->file); + image->file); image->filesize &= ~(uint64_t)4095; } close(fd); @@ -513,7 +516,7 @@ static dnbd3_image_t *prepare_image(char *image_name, int rid, char *image_file, for (k = 0, j = 0; j < MIN(num_servers, NUMBER_SERVERS); ++j) { if (parse_address(servers[j], &(image->servers[k].hostaddrtype), image->servers[k].hostaddr, - &(image->servers[k].port))) + &(image->servers[k].port))) { ++k; continue; @@ -533,7 +536,8 @@ static dnbd3_image_t *prepare_image(char *image_name, int rid, char *image_file, close(fd); } if (image->filesize & 4095) - { // Cache files should always be truncated to 4kib boundaries already + { + // Cache files should always be truncated to 4kib boundaries already memlogf("[WARNING] Size of cache file '%s' is not a multiple of 4096. Something's fishy!", image->cache_file); image->filesize = 0; } @@ -649,7 +653,8 @@ void dnbd3_exec_delete(int save_if_changed) { const dnbd3_client_t *client = client_iterator->data; if (client->image == image) - { // Yep, still in use, keep it + { + // Yep, still in use, keep it delete_now = FALSE; break; } diff --git a/src/server/utils.h b/src/server/utils.h index 53dc076..e254cfd 100644 --- a/src/server/utils.h +++ b/src/server/utils.h @@ -47,7 +47,7 @@ int dnbd3_del_image(dnbd3_image_t *image); void dnbd3_exec_delete(int save_if_changed); -dnbd3_image_t* dnbd3_get_image(char *name, int rid, const char do_lock); +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); |