From 5536f1731c6c603f1b76e2c83ce18c4e610051d7 Mon Sep 17 00:00:00 2001 From: sr Date: Sat, 25 Aug 2012 20:05:04 +0200 Subject: [KERNEL] Only update alt-server list if received from initial server [*] Add CMD_KEEPALIVE protocol message type --- src/client/client.c | 8 ++++---- src/kernel/blk.c | 1 + src/kernel/dnbd3.h | 2 +- src/kernel/net.c | 58 +++++++++++++++++++++++++++++++++++++++++++---------- src/server/net.c | 12 ++++++++++- src/types.h | 1 + 6 files changed, 65 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/client.c b/src/client/client.c index c3318f4..57762cc 100644 --- a/src/client/client.c +++ b/src/client/client.c @@ -170,7 +170,7 @@ int main(int argc, char *argv[]) const int ret = ioctl(fd, IOCTL_CLOSE, &msg); if (ret < 0) { - printf("ERROR: ioctl not successful (close, errcode: %d)\n", ret); + printf("ERROR: ioctl not successful (close, %s (%d))\n", strerror(ret), ret); exit(EXIT_FAILURE); } @@ -187,7 +187,7 @@ int main(int argc, char *argv[]) const int ret = ioctl(fd, IOCTL_SWITCH, &msg); if (ret < 0) { - printf("ERROR: ioctl not successful (switch, errcode: %d)\n", ret); + printf("ERROR: ioctl not successful (switch, %s (%d))\n", strerror(ret), ret); exit(EXIT_FAILURE); } @@ -205,7 +205,7 @@ int main(int argc, char *argv[]) const int ret = ioctl(fd, IOCTL_OPEN, &msg); if (ret < 0) { - printf("ERROR: ioctl not successful (connect, errcode: %d)\n", ret); + printf("ERROR: ioctl not successful (connect, %s (%d))\n", strerror(ret), ret); exit(EXIT_FAILURE); } @@ -242,7 +242,7 @@ int main(int argc, char *argv[]) const int ret = ioctl(fd, IOCTL_OPEN, &msg); if (ret < 0) { - printf("ERROR: ioctl not successful (config file, errcode: %d)\n", ret); + printf("ERROR: ioctl not successful (config file, %s (%d))\n", strerror(ret), ret); exit(EXIT_FAILURE); } diff --git a/src/kernel/blk.c b/src/kernel/blk.c index f8ef4fd..70e8419 100644 --- a/src/kernel/blk.c +++ b/src/kernel/blk.c @@ -142,6 +142,7 @@ int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u memcpy(dev->cur_server.hostaddr, msg->addr, 16); dev->cur_server.port = msg->port; dev->cur_server.hostaddrtype = msg->addrtype; + memcpy(&dev->initial_server, &dev->cur_server, sizeof(dev->initial_server)); dev->imgname = imgname; dev->rid = msg->rid; blk_queue->backing_dev_info.ra_pages = (msg->read_ahead_kb * 1024) / PAGE_CACHE_SIZE; diff --git a/src/kernel/dnbd3.h b/src/kernel/dnbd3.h index dfed0f2..69f64b6 100644 --- a/src/kernel/dnbd3.h +++ b/src/kernel/dnbd3.h @@ -55,7 +55,7 @@ typedef struct // network struct socket *sock; - dnbd3_server_t cur_server; + dnbd3_server_t cur_server, initial_server; uint64_t cur_rtt; char *imgname; serialized_buffer_t payload_buffer; diff --git a/src/kernel/net.c b/src/kernel/net.c index 3623614..9920a2f 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -29,20 +29,33 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +static inline int is_same_server(const dnbd3_server_t * const a, const dnbd3_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))); +} + int dnbd3_net_connect(dnbd3_device_t *dev) { struct sockaddr_in sin; - struct request *req1 = kmalloc(sizeof(*req1), GFP_ATOMIC); + struct request *req1 = NULL; struct timeval timeout; + timeout.tv_sec = SOCKET_TIMEOUT_CLIENT_DATA; timeout.tv_usec = 0; // do some checks before connecting - if (!req1) + if (is_same_server(&dev->cur_server, &dev->initial_server)) { - printk("FATAL: Kmalloc(1) failed.\n"); - goto error; + printk("Connecting to initial server, so I need %d bytes.\n", (int)sizeof(*req1)); + req1 = kmalloc(sizeof(*req1), GFP_ATOMIC); + if (!req1) + { + printk("FATAL: Kmalloc(1) failed.\n"); + goto error; + } } if (dev->cur_server.port == 0 || dev->cur_server.hostaddrtype == 0 || dev->imgname == NULL) { @@ -182,10 +195,13 @@ int dnbd3_net_connect(dnbd3_device_t *dev) dev->alt_servers_num = 0; dev->update_available = 0; - // enqueue request to request_queue_send (ask alt servers) - req1->cmd_type = REQ_TYPE_SPECIAL; - req1->cmd_flags = CMD_GET_SERVERS; - list_add(&req1->queuelist, &dev->request_queue_send); + if (req1) + { + // enqueue request to request_queue_send (ask alt servers) + req1->cmd_type = REQ_TYPE_SPECIAL; + req1->cmd_flags = CMD_GET_SERVERS; + list_add(&req1->queuelist, &dev->request_queue_send); + } // create required threads dev->thread_send = kthread_create(dnbd3_net_send, dev, dev->disk->disk_name); @@ -278,7 +294,7 @@ void dnbd3_net_heartbeat(unsigned long arg) if (req) { req->cmd_type = REQ_TYPE_SPECIAL; - req->cmd_flags = CMD_GET_SERVERS; + req->cmd_flags = CMD_KEEPALIVE; list_add_tail(&req->queuelist, &dev->request_queue_send); wake_up(&dev->process_queue_send); } @@ -599,7 +615,7 @@ int dnbd3_net_discover(void *data) if (ready && best_server != current_server && dev->cur_rtt > best_rtt + RTT_THRESHOLD) { - printk("INFO: Server %d on %s is faster (%lluµs)\n", best_server, dev->disk->disk_name, best_rtt); + printk("INFO: Server %d on %s is faster (%lluµs vs. %lluµs)\n", best_server, dev->disk->disk_name, (unsigned long long)best_rtt, (unsigned long long)dev->cur_rtt); kfree(buf); dev->better_sock = best_sock; // Take shortcut by continuing to use open connection dev->thread_discover = NULL; @@ -824,6 +840,11 @@ int dnbd3_net_receive(void *data) continue; case CMD_GET_SERVERS: + if (!is_same_server(&dev->cur_server, &dev->initial_server)) + { + remaining = dnbd3_reply.size; + goto clear_remaining_payload; + } spin_lock_irq(&dev->blk_lock); dev->new_servers_num = 0; spin_unlock_irq(&dev->blk_lock); @@ -838,6 +859,15 @@ int dnbd3_net_receive(void *data) printk("ERROR: Recv CMD_GET_SERVERS payload.\n"); goto error; } + for (remaining = 0; remaining < count; ++remaining) + { + if (dev->new_servers[remaining].addrtype == AF_INET) + printk("New Server: %pI4 : %d\n", dev->new_servers[remaining].ipaddr, (int)ntohs(dev->new_servers[remaining].port)); + else if (dev->new_servers[remaining].addrtype == AF_INET6) + printk("New Server: %pI6 : %d\n", dev->new_servers[remaining].ipaddr, (int)ntohs(dev->new_servers[remaining].port)); + else + printk("New Server of unknown address type (%d)\n", (int)dev->new_servers[remaining].addrtype); + } spin_lock_irq(&dev->blk_lock); dev->new_servers_num = count; spin_unlock_irq(&dev->blk_lock); @@ -845,9 +875,10 @@ int dnbd3_net_receive(void *data) } // If there were more servers than accepted, remove the remaining data from the socket buffer remaining = dnbd3_reply.size - (count * sizeof(dnbd3_server_entry_t)); +clear_remaining_payload: while (remaining > 0) { - count = MIN(sizeof(dnbd3_reply), remaining); + count = MIN(sizeof(dnbd3_reply), remaining); // Abuse the reply struct as the receive buffer iov.iov_base = &dnbd3_reply; iov.iov_len = count; ret = kernel_recvmsg(dev->sock, &msg, &iov, 1, iov.iov_len, msg.msg_flags); @@ -860,6 +891,11 @@ int dnbd3_net_receive(void *data) } continue; + case CMD_KEEPALIVE: + if (dnbd3_reply.size != 0) + printk("Error: keep alive packet with payload.\n"); + continue; + default: printk("ERROR: Unknown command (Receive)\n"); continue; diff --git a/src/server/net.c b/src/server/net.c index a60b739..c145beb 100644 --- a/src/server/net.c +++ b/src/server/net.c @@ -45,7 +45,8 @@ static char recv_request_header(int sock, dnbd3_request_t *request) // Read request header from socket if ((ret = recv(sock, request, sizeof(*request), MSG_WAITALL)) != sizeof(*request)) { - printf("[DEBUG] Error receiving request: Could not read message header (%d)\n", ret); + 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) @@ -252,6 +253,9 @@ void *dnbd3_handle_query(void *dnbd3_client) reply.handle = request.handle; send_reply(client->sock, &reply, NULL); + if (request.size == 0) // Request for 0 bytes, done after sending header + break; + // caching is off if (image_cache == -1) { @@ -357,6 +361,12 @@ void *dnbd3_handle_query(void *dnbd3_client) 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; + default: memlogf("ERROR: Unknown command\n"); break; diff --git a/src/types.h b/src/types.h index 6ba7629..0227433 100644 --- a/src/types.h +++ b/src/types.h @@ -75,6 +75,7 @@ typedef struct #define CMD_GET_SIZE 2 #define CMD_GET_SERVERS 3 #define CMD_ERROR 4 +#define CMD_KEEPALIVE 5 #pragma pack(1) typedef struct -- cgit v1.2.3-55-g7522