summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.h2
-rw-r--r--src/kernel/blk.c5
-rw-r--r--src/kernel/core.c4
-rw-r--r--src/kernel/dnbd3.h3
-rw-r--r--src/kernel/net.c65
-rw-r--r--src/kernel/net.h2
-rw-r--r--src/server/server.c14
-rw-r--r--src/types.h1
8 files changed, 82 insertions, 14 deletions
diff --git a/src/config.h b/src/config.h
index 1aabf47..8cb088e 100644
--- a/src/config.h
+++ b/src/config.h
@@ -23,6 +23,8 @@
// network
#define PORT 5003
+#define SERVER_SOCKET_TIMEOUT 30
+#define HB_INTERVAL 20*HZ
// block device
#define KERNEL_SECTOR_SIZE 512
diff --git a/src/kernel/blk.c b/src/kernel/blk.c
index c495205..fe66e1d 100644
--- a/src/kernel/blk.c
+++ b/src/kernel/blk.c
@@ -57,6 +57,8 @@ int dnbd3_blk_add_device(struct dnbd3_device *dev, int minor)
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue);
dev->disk = disk;
+ dev->hb_request.cmd_type = REQ_TYPE_SPECIAL;
+
add_disk(disk); // must be last
return 0;
}
@@ -69,6 +71,9 @@ int dnbd3_blk_del_device(struct dnbd3_device *dev)
dev->sock = NULL;
}
+ if (&dev->hb_timer)
+ del_timer(&dev->hb_timer);
+
del_gendisk(dev->disk);
put_disk(dev->disk);
blk_cleanup_queue(dev->disk->queue);
diff --git a/src/kernel/core.c b/src/kernel/core.c
index 1483704..3dc7ddf 100644
--- a/src/kernel/core.c
+++ b/src/kernel/core.c
@@ -27,13 +27,13 @@ struct dnbd3_device dnbd3_device[MAX_NUMBER_DEVICES];
static int __init dnbd3_init(void)
{
int i;
-
// initialize block device
if ((major = register_blkdev(0, "dnbd3")) == 0)
{
printk("ERROR: dnbd3 register_blkdev failed.\n");
return -EIO;
}
+ // add MAX_NUMBER_DEVICES devices
for (i = 0; i < MAX_NUMBER_DEVICES; i++)
{
if (dnbd3_blk_add_device(&dnbd3_device[i], i) != 0)
@@ -42,7 +42,6 @@ static int __init dnbd3_init(void)
return -EIO;
}
}
-
printk("INFO: dnbd3 init successful.\n");
return 0;
}
@@ -54,7 +53,6 @@ static void __exit dnbd3_exit(void)
{
dnbd3_blk_del_device(&dnbd3_device[i]);
}
-
unregister_blkdev(major, "dnbd3");
printk("INFO: dnbd3 exit.\n");
}
diff --git a/src/kernel/dnbd3.h b/src/kernel/dnbd3.h
index 5f45699..6f31c07 100644
--- a/src/kernel/dnbd3.h
+++ b/src/kernel/dnbd3.h
@@ -33,7 +33,6 @@ extern int major;
struct dnbd3_device
{
-
// block
struct gendisk *disk;
spinlock_t blk_lock;
@@ -43,6 +42,8 @@ struct dnbd3_device
char port[6];
char image_id[MAX_FILE_NAME];
struct socket *sock;
+ struct timer_list hb_timer;
+ struct request hb_request;
// process
struct task_struct *thread_send;
diff --git a/src/kernel/net.c b/src/kernel/net.c
index c3f9782..de47ff7 100644
--- a/src/kernel/net.c
+++ b/src/kernel/net.c
@@ -35,7 +35,7 @@ void dnbd3_net_connect(struct dnbd3_device *lo)
return;
}
- // FIXME: check if allready connected
+ // TODO: check if allready connected
printk("INFO: Connecting device %s\n", lo->disk->disk_name);
// initialize socket
@@ -89,6 +89,13 @@ void dnbd3_net_connect(struct dnbd3_device *lo)
// start receiving thread
lo->thread_receive = kthread_create(dnbd3_net_receive, lo, lo->disk->disk_name);
wake_up_process(lo->thread_receive);
+
+ // Add heartbeat timer
+ init_timer(&lo->hb_timer);
+ lo->hb_timer.data = (unsigned long)lo;
+ lo->hb_timer.function = dnbd3_net_heartbeat;
+ lo->hb_timer.expires = jiffies + HB_INTERVAL;
+ add_timer(&lo->hb_timer);
}
void dnbd3_net_disconnect(struct dnbd3_device *lo)
@@ -106,6 +113,9 @@ void dnbd3_net_disconnect(struct dnbd3_device *lo)
sock_release(lo->sock);
lo->sock = NULL;
}
+ // clear heartbeat timer
+ if (&lo->hb_timer)
+ del_timer(&lo->hb_timer);
// move already send requests to request_queue_send
if (!list_empty(&lo->request_queue_receive))
@@ -151,10 +161,23 @@ int dnbd3_net_send(void *data)
list_del_init(&blk_request->queuelist);
spin_unlock_irq(&lo->blk_lock);
- // prepare net request
- dnbd3_request.cmd = CMD_GET_BLOCK;
- dnbd3_request.offset = blk_rq_pos(blk_request) << 9; // *512
- dnbd3_request.size = blk_rq_bytes(blk_request); // blk_rq_bytes() Returns bytes left to complete in the entire request
+ switch (blk_request->cmd_type)
+ {
+ case REQ_TYPE_SPECIAL:
+ dnbd3_request.cmd = CMD_PING;
+ 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); // blk_rq_bytes() Returns bytes left to complete in the entire request
+ break;
+
+ default:
+ printk("ERROR: Unknown command\n");
+ break;
+ }
+
memcpy(dnbd3_request.handle, &blk_request, sizeof(blk_request));
iov.iov_base = &dnbd3_request;
iov.iov_len = sizeof(dnbd3_request);
@@ -220,8 +243,15 @@ int dnbd3_net_receive(void *data)
}
spin_unlock_irq(&lo->blk_lock);
- // receive data and answer to block layer
- rq_for_each_segment(bvec, blk_request, iter)
+ switch (dnbd3_reply.cmd)
+ {
+ case CMD_PING:
+ // TODO: use for rtt?
+ 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);
@@ -235,10 +265,25 @@ int dnbd3_net_receive(void *data)
sigprocmask(SIG_SETMASK, &oldset, NULL);
}
+ spin_lock_irqsave(&lo->blk_lock, flags);
+ __blk_end_request_all(blk_request, 0);
+ spin_unlock_irqrestore(&lo->blk_lock, flags);
+ break;
+
+ default:
+ printk("ERROR: Unknown command\n");
+ break;
+ }
- spin_lock_irqsave(&lo->blk_lock, flags);
- __blk_end_request_all(blk_request, 0);
- spin_unlock_irqrestore(&lo->blk_lock, flags);
}
return 0;
}
+
+void dnbd3_net_heartbeat(unsigned long arg)
+{
+ struct dnbd3_device *lo = (struct dnbd3_device *) arg;
+ list_add(&lo->hb_request.queuelist, &lo->request_queue_send);
+ wake_up(&lo->process_queue_send);
+ lo->hb_timer.expires = jiffies + HB_INTERVAL;
+ add_timer(&lo->hb_timer);
+}
diff --git a/src/kernel/net.h b/src/kernel/net.h
index 017a71e..66bc195 100644
--- a/src/kernel/net.h
+++ b/src/kernel/net.h
@@ -31,4 +31,6 @@ int dnbd3_net_send(void *data);
int dnbd3_net_receive(void *data);
+void dnbd3_net_heartbeat(unsigned long arg);
+
#endif /* NET_H_ */
diff --git a/src/server/server.c b/src/server/server.c
index 33e93f1..ffeb0af 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -108,6 +108,12 @@ void *handle_query(void *client_socket)
cmd = request.cmd;
switch (cmd)
{
+ case CMD_PING:
+ reply.cmd = request.cmd;
+ memcpy(reply.handle, request.handle, sizeof(request.handle));
+ send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0);
+ break;
+
case CMD_GET_SIZE:
pthread_spin_lock(&spinlock); // because of reloading config
image_file = open(dnbd3_ht_search(request.image_id), O_RDONLY);
@@ -249,6 +255,11 @@ int main(int argc, char* argv[])
dnbd3_write_pid_file(getpid());
printf("INFO: Server is ready...\n");
+ struct timeval timeout;
+ timeout.tv_sec = SERVER_SOCKET_TIMEOUT;
+ timeout.tv_usec = 0;
+
+
while (1)
{
len = sizeof(client);
@@ -260,6 +271,9 @@ int main(int argc, char* argv[])
}
printf("INFO: Client: %s connected\n", inet_ntoa(client.sin_addr));
+ setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
+ setsockopt (fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
+
// FIXME: catch SIGKILL/SIGTERM and close all socket before exit
pthread_t thread;
pthread_create(&(thread), NULL, handle_query, (void *)(uintptr_t) fd);
diff --git a/src/types.h b/src/types.h
index 3e03d97..2d34943 100644
--- a/src/types.h
+++ b/src/types.h
@@ -34,6 +34,7 @@
// network
#define CMD_GET_BLOCK 1
#define CMD_GET_SIZE 2
+#define CMD_PING 3
#pragma pack(1)
typedef struct dnbd3_request