From 79bb581eb0373c717d1ce95e817fd7411b07ff92 Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Fri, 10 Feb 2012 23:47:32 +0100 Subject: [SERVER] Config reload fixed --- src/kernel/net.c | 210 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 110 insertions(+), 100 deletions(-) (limited to 'src/kernel/net.c') diff --git a/src/kernel/net.c b/src/kernel/net.c index 7afac7d..5bd8871 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -19,23 +19,25 @@ */ #include "net.h" +#include "blk.h" #include "utils.h" void dnbd3_net_connect(dnbd3_device_t *dev) { struct sockaddr_in sin; - struct msghdr msg; - struct kvec iov; - dnbd3_request_t dnbd3_request; - dnbd3_reply_t dnbd3_reply; - uint64_t filesize; + struct request *req = kmalloc(sizeof(struct request), GFP_ATOMIC); + // do some checks before connecting + if (!req) + { + printk("ERROR: Kmalloc failed.\n"); + return; + } if (!dev->host || !dev->port || (dev->vid == 0)) { printk("ERROR: Host, port or vid not set.\n"); return; } - if (dev->sock) { printk("ERROR: Device %s already connected to %s.\n", dev->disk->disk_name, dev->host); @@ -62,40 +64,6 @@ void dnbd3_net_connect(dnbd3_device_t *dev) return; } - // prepare message - dnbd3_request.cmd = CMD_GET_SIZE; - dnbd3_request.vid = dev->vid; - dnbd3_request.rid = dev->rid; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_WAITALL | MSG_NOSIGNAL; // No SIGPIPE - - // send message - iov.iov_base = &dnbd3_request; - iov.iov_len = sizeof(dnbd3_request); - kernel_sendmsg(dev->sock, &msg, &iov, 1, sizeof(dnbd3_request)); - - // receive replay - iov.iov_base = &dnbd3_reply; - iov.iov_len = sizeof(dnbd3_reply); - kernel_recvmsg(dev->sock, &msg, &iov, 1, sizeof(dnbd3_reply), msg.msg_flags); - if (dnbd3_reply.size <= 0) - { - printk("ERROR: File size returned by server is < 0.\n"); - sock_release(dev->sock); - dev->sock = NULL; - return; - } - - // receive and set filesize - iov.iov_base = &filesize; - iov.iov_len = sizeof(uint64_t); - kernel_recvmsg(dev->sock, &msg, &iov, 1, dnbd3_reply.size, msg.msg_flags); - set_capacity(dev->disk, filesize >> 9); /* 512 Byte blocks */ - printk("INFO: Filesize %s: %llu\n", dev->disk->disk_name, filesize); - // start sending thread dev->thread_send = kthread_create(dnbd3_net_send, dev, dev->disk->disk_name); wake_up_process(dev->thread_send); @@ -104,12 +72,18 @@ void dnbd3_net_connect(dnbd3_device_t *dev) dev->thread_receive = kthread_create(dnbd3_net_receive, dev, dev->disk->disk_name); wake_up_process(dev->thread_receive); - // Add heartbeat timer + // add heartbeat timer init_timer(&dev->hb_timer); dev->hb_timer.data = (unsigned long) dev; dev->hb_timer.function = dnbd3_net_heartbeat; dev->hb_timer.expires = jiffies + HB_INTERVAL; add_timer(&dev->hb_timer); + + // enqueue request to request_queue_send (ask file size) + req->cmd_type = REQ_TYPE_SPECIAL; + req->cmd_flags = REQ_GET_FILESIZE; + list_add(&req->queuelist, &dev->request_queue_send); + wake_up(&dev->process_queue_send); } void dnbd3_net_disconnect(dnbd3_device_t *dev) @@ -124,7 +98,7 @@ void dnbd3_net_disconnect(dnbd3_device_t *dev) kthread_stop(dev->thread_receive); } - // clear sock + // clear socket if (dev->sock) { sock_release(dev->sock); @@ -151,17 +125,13 @@ void dnbd3_net_disconnect(dnbd3_device_t *dev) int dnbd3_net_send(void *data) { dnbd3_device_t *dev = data; - dnbd3_request_t dnbd3_request; struct request *blk_request; + + dnbd3_request_t dnbd3_request; struct msghdr msg; struct kvec iov; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_WAITALL | MSG_NOSIGNAL; // No SIGPIPE - + init_msghdr(msg); set_user_nice(current, -20); while (!kthread_should_stop() || !list_empty(&dev->request_queue_send)) @@ -178,31 +148,42 @@ int dnbd3_net_send(void *data) list_del_init(&blk_request->queuelist); spin_unlock_irq(&dev->blk_lock); + // what to do? switch (blk_request->cmd_type) { - case REQ_TYPE_SPECIAL: - dnbd3_request.cmd = CMD_GET_SERVERS; - break; - case REQ_TYPE_FS: dnbd3_request.cmd = CMD_GET_BLOCK; dnbd3_request.offset = blk_rq_pos(blk_request) << 9; // *512 dnbd3_request.size = blk_rq_bytes(blk_request); // bytes left to complete entire request break; - default: - printk("ERROR: Unknown command\n"); + case REQ_TYPE_SPECIAL: + switch (blk_request->cmd_flags) + { + case REQ_GET_FILESIZE: + dnbd3_request.cmd = CMD_GET_SIZE; + dnbd3_request.vid = dev->vid; + dnbd3_request.rid = dev->rid; + break; + case REQ_GET_SERVERS: + dnbd3_request.cmd = CMD_GET_SERVERS; + break; + } break; + + default: + printk("ERROR: Unknown command (Send)\n"); + continue; } + // send net request memcpy(dnbd3_request.handle, &blk_request, sizeof(blk_request)); iov.iov_base = &dnbd3_request; iov.iov_len = sizeof(dnbd3_request); - - // send net request if (kernel_sendmsg(dev->sock, &msg, &iov, 1, sizeof(dnbd3_request)) <= 0) printk("ERROR: kernel_sendmsg\n"); + // enqueue request to request_queue_receive spin_lock_irq(&dev->blk_lock); list_add_tail(&blk_request->queuelist, &dev->request_queue_receive); spin_unlock_irq(&dev->blk_lock); @@ -214,27 +195,21 @@ int dnbd3_net_send(void *data) int dnbd3_net_receive(void *data) { dnbd3_device_t *dev = data; + struct request *blk_request, *tmp_request, *received_request; + dnbd3_reply_t dnbd3_reply; - struct request *blk_request; struct msghdr msg; struct kvec iov; struct req_iterator iter; struct bio_vec *bvec; + void *kaddr; unsigned long flags; sigset_t blocked, oldset; - struct request *tmp_request, *received_request; - void *kaddr; - unsigned int size; - int i = 0; - //char a[15]; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_WAITALL | MSG_NOSIGNAL; // No SIGPIPE + unsigned int size, i; + uint64_t filesize; + init_msghdr(msg); set_user_nice(current, -20); while (!kthread_should_stop() || !list_empty(&dev->request_queue_receive)) @@ -256,15 +231,67 @@ int dnbd3_net_receive(void *data) list_for_each_entry_safe(blk_request, tmp_request, &dev->request_queue_receive, queuelist) { if (blk_request != received_request) - continue; + continue; list_del_init(&blk_request->queuelist); break; } spin_unlock_irq(&dev->blk_lock); + // check if server send error + switch (dnbd3_reply.error) + { + case ERROR_SIZE: + printk("ERROR: Requested image does't exist\n"); + kthread_stop(dev->thread_send); + del_timer(&dev->hb_timer); + sock_release(dev->sock); + kfree(blk_request); + dev->sock = NULL; + return -1; + + case ERROR_RELOAD: + blk_request->cmd_type = REQ_TYPE_SPECIAL; + blk_request->cmd_flags = REQ_GET_FILESIZE; + list_add(&blk_request->queuelist, &dev->request_queue_send); + wake_up(&dev->process_queue_send); + continue; + + } + + // what to do? switch (dnbd3_reply.cmd) { + case CMD_GET_BLOCK: + // receive data and answer to block layer + rq_for_each_segment(bvec, blk_request, iter) + { + siginitsetinv(&blocked, sigmask(SIGKILL)); + sigprocmask(SIG_SETMASK, &blocked, &oldset); + + kaddr = kmap(bvec->bv_page) + bvec->bv_offset; + size = bvec->bv_len; + iov.iov_base = kaddr; + iov.iov_len = size; + kernel_recvmsg(dev->sock, &msg, &iov, 1, size, msg.msg_flags); + kunmap(bvec->bv_page); + + sigprocmask(SIG_SETMASK, &oldset, NULL); + } + spin_lock_irqsave(&dev->blk_lock, flags); + __blk_end_request_all(blk_request, 0); + spin_unlock_irqrestore(&dev->blk_lock, flags); + continue; + + case CMD_GET_SIZE: + iov.iov_base = &filesize; + iov.iov_len = sizeof(uint64_t); + kernel_recvmsg(dev->sock, &msg, &iov, 1, dnbd3_reply.size, msg.msg_flags); + set_capacity(dev->disk, filesize >> 9); /* 512 Byte blocks */ + printk("INFO: Filesize %s: %llu\n", dev->disk->disk_name, filesize); + kfree(blk_request); + continue; + case CMD_GET_SERVERS: dev->num_servers = dnbd3_reply.size / sizeof(struct in_addr); size = sizeof(struct in_addr); @@ -273,38 +300,15 @@ int dnbd3_net_receive(void *data) iov.iov_base = &dev->servers[i]; iov.iov_len = size; kernel_recvmsg(dev->sock, &msg, &iov, 1, size, msg.msg_flags); - -// inet_ntoa(dev->servers[i], a); -// printk("INFO: Server[%i] %s\n", i, a); } - break; - - case CMD_GET_BLOCK: - // receive data and answer to block layer - rq_for_each_segment(bvec, blk_request, iter) - { - siginitsetinv(&blocked, sigmask(SIGKILL)); - sigprocmask(SIG_SETMASK, &blocked, &oldset); - - kaddr = kmap(bvec->bv_page) + bvec->bv_offset; - size = bvec->bv_len; - iov.iov_base = kaddr; - iov.iov_len = size; - kernel_recvmsg(dev->sock, &msg, &iov, 1, size, msg.msg_flags); - kunmap(bvec->bv_page); - - sigprocmask(SIG_SETMASK, &oldset, NULL); - } - spin_lock_irqsave(&dev->blk_lock, flags); - __blk_end_request_all(blk_request, 0); - spin_unlock_irqrestore(&dev->blk_lock, flags); - break; + kfree(blk_request); + continue; default: - printk("ERROR: Unknown command\n"); - break; - } + printk("ERROR: Unknown command (Receive)\n"); + continue; + } } return 0; } @@ -312,8 +316,14 @@ int dnbd3_net_receive(void *data) void dnbd3_net_heartbeat(unsigned long arg) { dnbd3_device_t *dev = (dnbd3_device_t *) arg; - list_add(&dev->hb_request.queuelist, &dev->request_queue_send); - wake_up(&dev->process_queue_send); + struct request *req = kmalloc(sizeof(struct request), GFP_ATOMIC); + if (req) + { + req->cmd_type = REQ_TYPE_SPECIAL; + req->cmd_flags = REQ_GET_SERVERS; + list_add(&req->queuelist, &dev->request_queue_send); + wake_up(&dev->process_queue_send); + } dev->hb_timer.expires = jiffies + HB_INTERVAL; add_timer(&dev->hb_timer); } -- cgit v1.2.3-55-g7522