summaryrefslogtreecommitdiffstats
path: root/src/kernel/net.c
diff options
context:
space:
mode:
authorJohann Latocha2012-02-10 23:47:32 +0100
committerJohann Latocha2012-02-10 23:47:32 +0100
commit79bb581eb0373c717d1ce95e817fd7411b07ff92 (patch)
tree79309d8030bec24bd80c7b534dc026f1ebf488c8 /src/kernel/net.c
parent[CLIENT] Get host by name (diff)
downloaddnbd3-79bb581eb0373c717d1ce95e817fd7411b07ff92.tar.gz
dnbd3-79bb581eb0373c717d1ce95e817fd7411b07ff92.tar.xz
dnbd3-79bb581eb0373c717d1ce95e817fd7411b07ff92.zip
[SERVER] Config reload fixed
Diffstat (limited to 'src/kernel/net.c')
-rw-r--r--src/kernel/net.c210
1 files changed, 110 insertions, 100 deletions
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);
}