From de01183aa40dbbd274e18f681d8a255a886f493e Mon Sep 17 00:00:00 2001 From: sr Date: Mon, 27 Aug 2012 21:02:49 +0200 Subject: [KERNEL] Refactor and extend sysfs (add data the server will need in proxy mode) [SERVER] Use MSG_MORE instead of cork/uncork to save two syscalls [KERNEL] Fail-Counter for alt servers, ignore servers that fail too often [KERNEL] Add new alt servers to list, instead of replacing the old list [*] Add CMD_LATEST_RID to tell client about new revisions --- src/server/ipc.c | 8 +++++--- src/server/net.c | 38 +++++++++++++++++++------------------- src/server/server.c | 19 +++++++++++++++++-- src/server/server.h | 5 +++++ src/server/utils.c | 4 ++-- 5 files changed, 48 insertions(+), 26 deletions(-) (limited to 'src/server') diff --git a/src/server/ipc.c b/src/server/ipc.c index 5da811c..ece6f07 100644 --- a/src/server/ipc.c +++ b/src/server/ipc.c @@ -403,9 +403,10 @@ void dnbd3_ipc_send(int cmd) if (cmd == IPC_INFO && header.size > 0) { - char* buf = malloc(header.size); + char* buf = malloc(header.size+1); size = recv(client_sock, buf, header.size, MSG_WAITALL); xmlDocPtr doc = xmlReadMemory(buf, size, "noname.xml", NULL, 0); + buf[header.size] = 0; if (doc) { @@ -479,9 +480,10 @@ void dnbd3_ipc_send(int cmd) // xmlDocDump(stdout, doc); - } else + } + else { - printf("ERROR: Failed to parse reply\n"); + printf("ERROR: Failed to parse reply\n-----------\n%s\n-------------\n", buf); } } diff --git a/src/server/net.c b/src/server/net.c index c145beb..49cfb24 100644 --- a/src/server/net.c +++ b/src/server/net.c @@ -39,7 +39,7 @@ #include "../config.h" -static char recv_request_header(int sock, dnbd3_request_t *request) +static inline char recv_request_header(int sock, dnbd3_request_t *request) { int ret; // Read request header from socket @@ -62,10 +62,13 @@ static char recv_request_header(int sock, dnbd3_request_t *request) 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); +#endif return 1; } -static char recv_request_payload(int sock, uint32_t size, serialized_buffer_t *payload) +static inline char recv_request_payload(int sock, uint32_t size, serialized_buffer_t *payload) { if (size == 0) { @@ -87,10 +90,11 @@ static char recv_request_payload(int sock, uint32_t size, serialized_buffer_t *p return 1; } -static char send_reply(int sock, dnbd3_reply_t *reply, void *payload) +static inline char send_reply(int sock, dnbd3_reply_t *reply, void *payload) { + const unsigned int size = reply->size; fixup_reply(*reply); - if (!payload || reply->size == 0) + if (!payload || size == 0) { if (send(sock, reply, sizeof(dnbd3_reply_t), MSG_WAITALL) != sizeof(dnbd3_reply_t)) { @@ -104,10 +108,10 @@ static char send_reply(int sock, dnbd3_reply_t *reply, void *payload) iov[0].iov_base = reply; iov[0].iov_len = sizeof(dnbd3_reply_t); iov[1].iov_base = payload; - iov[1].iov_len = reply->size; - if (writev(sock, iov, 2) != sizeof(dnbd3_reply_t) + reply->size) + iov[1].iov_len = size; + if (writev(sock, iov, 2) != sizeof(dnbd3_reply_t) + size) { - printf("[DEBUG] Send failed (reply with payload of %d bytes)\n", (int)reply->size); + printf("[DEBUG] Send failed (reply with payload of %u bytes)\n", size); return 0; } } @@ -120,9 +124,6 @@ void *dnbd3_handle_query(void *dnbd3_client) dnbd3_request_t request; dnbd3_reply_t reply; - const int cork = 1; - const int uncork = 0; - dnbd3_image_t *image = NULL; int image_file = -1, image_cache = -1; @@ -216,7 +217,6 @@ void *dnbd3_handle_query(void *dnbd3_client) if (image) while (recv_request_header(client->sock, &request)) { - switch (request.cmd) { @@ -246,12 +246,16 @@ void *dnbd3_handle_query(void *dnbd3_client) break; } - // TODO: Try MSG_MORE instead of cork+uncork if performance ever becomes an issue.. - setsockopt(client->sock, SOL_TCP, TCP_CORK, &cork, sizeof(cork)); reply.cmd = CMD_GET_BLOCK; reply.size = request.size; reply.handle = request.handle; - send_reply(client->sock, &reply, NULL); + + 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; @@ -264,8 +268,6 @@ void *dnbd3_handle_query(void *dnbd3_client) printf("[ERROR] sendfile failed (image to net)\n"); close(client->sock); } - - setsockopt(client->sock, SOL_TCP, TCP_CORK, &uncork, sizeof(uncork)); break; } @@ -343,8 +345,6 @@ void *dnbd3_handle_query(void *dnbd3_client) memlogf("[ERROR] sendfile failed (cache to net)\n"); close(client->sock); } - - setsockopt(client->sock, SOL_TCP, TCP_CORK, &uncork, sizeof(uncork)); break; @@ -353,7 +353,7 @@ void *dnbd3_handle_query(void *dnbd3_client) num = 0; for (i = 0; i < NUMBER_SERVERS; i++) { - if (image->servers[i].addrtype == 0 || image->servers[i].failures > 200) continue; + 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; diff --git a/src/server/server.c b/src/server/server.c index b2a36a5..965c368 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -37,6 +37,9 @@ #include "memlog.h" int _sock; +#ifdef _DEBUG +int _fake_delay = 0; +#endif pthread_spinlock_t _spinlock; GSList *_dnbd3_clients = NULL; @@ -48,6 +51,9 @@ void dnbd3_print_help(char* argv_0) printf("Usage: %s [OPTIONS]...\n", argv_0); printf("Start the DNBD3 server\n"); printf("-f or --file \t\t Configuration file (default /etc/dnbd3-server.conf)\n"); +#ifdef _DEBUG + printf("-d or --delay \t\t Add a fake network delay of X µs\n"); +#endif printf("-n or --nodaemon \t Start server in foreground\n"); printf("-r or --reload \t\t Reload configuration file\n"); printf("-s or --stop \t\t Stop running dnbd3-server\n"); @@ -119,10 +125,11 @@ int main(int argc, char* argv[]) int demonize = 1; int opt = 0; int longIndex = 0; - static const char *optString = "f:nrsiHV?"; + 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' }, @@ -137,8 +144,16 @@ int main(int argc, char* argv[]) switch (opt) { case 'f': - _config_file_name = optarg; + _config_file_name = strdup(optarg); break; + case 'd': +#ifdef _DEBUG + _fake_delay = atoi(optarg); + break; +#else + printf("This option is only available in debug builds.\n\n"); + return EXIT_FAILURE; +#endif case 'n': demonize = 0; break; diff --git a/src/server/server.h b/src/server/server.h index 69d597b..7e19f27 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -56,6 +56,11 @@ extern pthread_spinlock_t _spinlock; extern char *_config_file_name; extern GSList *_dnbd3_images; // of dnbd3_image_t + +#ifdef _DEBUG +extern int _fake_delay; +#endif + void dnbd3_cleanup(); #endif /* SERVER_H_ */ diff --git a/src/server/utils.c b/src/server/utils.c index 15e51f8..3fe1900 100644 --- a/src/server/utils.c +++ b/src/server/utils.c @@ -260,11 +260,11 @@ void dnbd3_load_config(char *file) gchar **servers = g_key_file_get_string_list(gkf, groups[i], "servers", &num_servers, NULL); if (servers) for (k = 0, j = 0; j < MIN(num_servers, NUMBER_SERVERS); ++j) { - if (parse_address(servers[j], &(image->servers[k].addrtype), image->servers[k].ipaddr, &(image->servers[k].port))) + if (parse_address(servers[j], &(image->servers[k].hostaddrtype), image->servers[k].hostaddr, &(image->servers[k].port))) { ++k; continue; } - image->servers[k].addrtype = 0; + image->servers[k].hostaddrtype = 0; } g_strfreev(servers); -- cgit v1.2.3-55-g7522