From 69d8e13d92733660a366ae845db0dc8a60eee24e Mon Sep 17 00:00:00 2001 From: Frederic Robra Date: Tue, 9 Jul 2019 17:00:54 +0200 Subject: updates list of alt servers --- src/kernel/dnbd3.h | 1 + src/kernel/net.c | 170 +++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 139 insertions(+), 32 deletions(-) diff --git a/src/kernel/dnbd3.h b/src/kernel/dnbd3.h index 0e39dfb..787c7f1 100644 --- a/src/kernel/dnbd3.h +++ b/src/kernel/dnbd3.h @@ -70,6 +70,7 @@ typedef struct dnbd3_device { struct mutex device_lock; // network + uint8_t socks_active; dnbd3_sock socks[NUMBER_CONNECTIONS]; char *imgname; // struct socket *sock; diff --git a/src/kernel/net.c b/src/kernel/net.c index 0c3993d..2931aea 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -47,8 +47,10 @@ } while (0) +static int dnbd3_socket_connect(dnbd3_device *dev, dnbd3_server *server); +static int dnbd3_socket_disconnect(dnbd3_device *dev, dnbd3_server *server, dnbd3_sock *sock); -static void printHost(struct dnbd3_host_t *host, char *msg) +static void print_host(struct dnbd3_host_t *host, char *msg) { if (host->type == HOST_IP4) { printk(KERN_INFO "dnbd3: %s %pI4:%d\n", msg, host->addr, host->port); @@ -57,13 +59,13 @@ static void printHost(struct dnbd3_host_t *host, char *msg) } } -static void printServerList(struct dnbd3_device *dev) +static void print_server_list(struct dnbd3_device *dev) { int i; - printHost(&dev->initial_server.host, "initial server is"); + print_host(&dev->initial_server.host, "initial server is"); for (i = 0; i < NUMBER_SERVERS; i++) { if (dev->alt_servers[i].host.addr[0] != 0) { - printHost(&dev->alt_servers[i].host, "alternative server is"); + print_host(&dev->alt_servers[i].host, "alternative server is"); } } } @@ -263,7 +265,7 @@ consume_payload: } reported_size = serializer_get_uint64(&payload_buffer); - if (dev->reported_size == NULL) { + if (!dev->reported_size) { if (reported_size < 4096) { printk(KERN_ERR "dnbd3: reported size by server is < 4096\n"); goto error; @@ -290,7 +292,6 @@ error: void dnbd3_keepalive(struct timer_list *arg) { struct dnbd3_sock *sock = container_of(arg, struct dnbd3_sock, keepalive_timer); -// schedule_work(&sock->keepalive); queue_work(dnbd3_wq, &sock->keepalive); sock->keepalive_timer.expires = KEEPALIVE_TIMER; add_timer(&sock->keepalive_timer); @@ -328,37 +329,88 @@ static void discovery(struct work_struct *work) struct dnbd3_device *dev = container_of(work, struct dnbd3_device, discovery); dnbd3_sock *sock = &dev->socks[0]; // we use the first sock for discovery struct request *req; + int i, j; + struct dnbd3_server *existing_server = NULL; + struct dnbd3_server *free_server = NULL; + struct dnbd3_server *failed_server = NULL; + dnbd3_server_entry_t *new_server; printk(KERN_DEBUG "dnbd3: starting discovery worker\n"); mutex_lock(&sock->lock); req = kmalloc(sizeof(struct request), GFP_ATOMIC ); // send keepalive if (req) { dnbd3_cmd_to_priv(req, CMD_GET_SERVERS); - dnbd3_send_request(dev, sock, req); // we do not need the device for keepalive + dnbd3_send_request(dev, sock, req); kfree(req); } else { printk(KERN_WARNING "dnbd3: could not create get servers request\n"); } mutex_unlock(&sock->lock); -} + printk(KERN_DEBUG "dnbd3: new server num is %d\n", dev->new_servers_num); + if (dev->new_servers_num) { + mutex_lock(&dev->device_lock); -static int dnbd3_socket_connect(dnbd3_device *dev, dnbd3_sock *sock) -{ - int result = -EIO; - struct request *req = NULL; - struct timeval timeout; - struct dnbd3_server *server = sock->server; - printk(KERN_DEBUG "dnbd3: socket connect device %i\n", dev->minor); + for (i = 0; i < dev->new_servers_num; i++) { + new_server = &dev->new_servers[i]; + if (new_server->host.type == HOST_IP4 || new_server->host.type == HOST_IP6) { + + // find servers in alt servers + for (j = 0; j < NUMBER_SERVERS; j++) { + if ((new_server->host.type == dev->alt_servers[j].host.type) + && (new_server->host.port == dev->alt_servers[j].host.port) + && (0 == memcmp(new_server->host.addr, dev->alt_servers[j].host.addr, + (new_server->host.type == HOST_IP4 ? 4 : 16)))) { + + existing_server = &dev->alt_servers[j]; + } else if (dev->alt_servers[j].host.type == 0) { + free_server = &dev->alt_servers[j]; + } else if (dev->alt_servers[j].failures > 20) { + failed_server = &dev->alt_servers[j]; + } + } + + if (existing_server) { + if (new_server->failures == 1) { // remove is requested + print_host(&existing_server->host, "remove server"); + dnbd3_socket_disconnect(dev, existing_server, NULL); // TODO what to do when only one connection? + existing_server->host.type = 0; + } + // ADD, so just reset fail counter +// existing_server->failures = 0; makes no sense? + continue; + } else if (free_server) { + free_server->host = new_server->host; + } else if (failed_server) { + failed_server->host = new_server->host; + free_server = failed_server; + } else { + //no server found to replace + continue; + } + print_host(&free_server->host, "got new alt server"); + free_server->failures = 0; + free_server->protocol_version = 0; + free_server->rtts[0] = free_server->rtts[1] = free_server->rtts[2] = free_server->rtts[3] = RTT_UNREACHABLE; + } + } + dev->new_servers_num = 0; + mutex_unlock(&dev->device_lock); + } + + // measure rtt for all alt servers + for (i = 0; i < NUMBER_SERVERS; i++) { + + } +} +static int __dnbd3_socket_connect(dnbd3_server * server, dnbd3_sock *sock) +{ + struct timeval timeout; mutex_init(&sock->lock); mutex_lock(&sock->lock); - if (sock->pending) { - printk(KERN_DEBUG "dnbd3: socket still in request\n"); - while (sock->pending) - schedule(); - } + if (server->host.port == 0 || server->host.type == 0) { printk(KERN_ERR "dnbd3: host or port not set\n"); goto error; @@ -371,13 +423,6 @@ static int dnbd3_socket_connect(dnbd3_device *dev, dnbd3_sock *sock) timeout.tv_sec = SOCKET_TIMEOUT_CLIENT_DATA; timeout.tv_usec = 0; - req = kmalloc(sizeof(*req), GFP_ATOMIC ); - if (!req) { - printk(KERN_ERR "dnbd3: kmalloc failed\n"); - goto error; - } - - if (dnbd3_sock_create(server->host.type, SOCK_STREAM, IPPROTO_TCP, &sock->sock) < 0) { printk(KERN_ERR "dnbd3: could not create socket\n"); goto error; @@ -407,6 +452,49 @@ static int dnbd3_socket_connect(dnbd3_device *dev, dnbd3_sock *sock) goto error; } } + mutex_unlock(&sock->lock); + + return 0; +error: + if (sock->sock) { + sock_release(sock->sock); + sock->sock = NULL; + } + mutex_unlock(&sock->lock); + mutex_destroy(&sock->lock); + return -EIO; +} + +static int dnbd3_socket_connect(dnbd3_device *dev, dnbd3_server *server) +{ + int i; + int result = -EIO; + struct dnbd3_sock *sock = NULL; + struct request *req = NULL; + for (i = 0; i < NUMBER_CONNECTIONS; i++) { + if (!dev->socks[i].sock) { + sock = &dev->socks[i]; + break; + } + } + if (sock == NULL) { + printk(KERN_WARNING "dnbd3: could not connect to socket, to many connections\n"); + return -EIO; + } + sock->server = server; + + printk(KERN_DEBUG "dnbd3: socket connect device %i\n", dev->minor); + + __dnbd3_socket_connect(server, sock); + + mutex_lock(&sock->lock); + req = kmalloc(sizeof(*req), GFP_ATOMIC ); + if (!req) { + printk(KERN_ERR "dnbd3: kmalloc failed\n"); + goto error; + } + + dnbd3_connect(req); result = dnbd3_send_request(dev, sock, req); if (result) { @@ -440,8 +528,22 @@ error: return result; } -static int dnbd3_socket_disconnect(dnbd3_device *dev, dnbd3_sock *sock) + +static int dnbd3_socket_disconnect(dnbd3_device *dev, dnbd3_server *server, dnbd3_sock *sock) { + int i; + if (sock == NULL) { + for (i = 0; i < NUMBER_CONNECTIONS; i++) { + if (dev->socks[i].server == server) { + sock = &dev->socks[i]; + break; + } + } + if (!sock) { + printk(KERN_WARNING "dnbd3: could not find socket to disconnect\n"); + return -EIO; + } + } printk(KERN_DEBUG "dnbd3: socket disconnect device %i\n", dev->minor); mutex_lock(&sock->lock); @@ -460,6 +562,7 @@ static int dnbd3_socket_disconnect(dnbd3_device *dev, dnbd3_sock *sock) mutex_unlock(&sock->lock); mutex_destroy(&sock->lock); + sock->server = NULL; return 0; } @@ -470,7 +573,7 @@ int dnbd3_net_disconnect(struct dnbd3_device *dev) del_timer_sync(&dev->discovery_timer); for (i = 0; i < NUMBER_CONNECTIONS; i++) { if (dev->socks[i].sock) { - if (dnbd3_socket_disconnect(dev, &dev->socks[i])) { + if (dnbd3_socket_disconnect(dev, NULL, &dev->socks[i])) { result = -EIO; } } @@ -482,15 +585,18 @@ int dnbd3_net_disconnect(struct dnbd3_device *dev) int dnbd3_net_connect(struct dnbd3_device *dev) { // TODO decide which socket to connect int result; - dev->socks[0].server = &dev->initial_server; - if (dnbd3_socket_connect(dev, &dev->socks[0]) == 0) { - printServerList(dev); + dev->socks_active = 0; + if (dnbd3_socket_connect(dev, &dev->alt_servers[0]) == 0) { + print_server_list(dev); INIT_WORK(&dev->discovery, discovery); timer_setup(&dev->discovery_timer, dnbd3_discovery, 0); dev->discovery_timer.expires = DISCOVERY_TIMER; add_timer(&dev->discovery_timer); + // let it discover alt servers + queue_work(dnbd3_wq, &dev->discovery); + result = 0; } else { printk(KERN_ERR "dnbd3: failed to connect to initial server\n"); -- cgit v1.2.3-55-g7522