diff options
author | Johann Latocha | 2012-01-30 21:57:52 +0100 |
---|---|---|
committer | Johann Latocha | 2012-01-30 21:57:52 +0100 |
commit | 83c80e33b2ad1ecc37e5fb637c411fbb33371a81 (patch) | |
tree | 3c2cdb691e5febcb7340ada5d38465b3e6e56efe /src | |
parent | [SERVER] Some refactoring (diff) | |
download | dnbd3-83c80e33b2ad1ecc37e5fb637c411fbb33371a81.tar.gz dnbd3-83c80e33b2ad1ecc37e5fb637c411fbb33371a81.tar.xz dnbd3-83c80e33b2ad1ecc37e5fb637c411fbb33371a81.zip |
[SERVER] Timeout for client sockets
[KERNEL] Send keep alive
Diffstat (limited to 'src')
-rw-r--r-- | src/config.h | 2 | ||||
-rw-r--r-- | src/kernel/blk.c | 5 | ||||
-rw-r--r-- | src/kernel/core.c | 4 | ||||
-rw-r--r-- | src/kernel/dnbd3.h | 3 | ||||
-rw-r--r-- | src/kernel/net.c | 65 | ||||
-rw-r--r-- | src/kernel/net.h | 2 | ||||
-rw-r--r-- | src/server/server.c | 14 | ||||
-rw-r--r-- | src/types.h | 1 |
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 |