diff options
author | Johann Latocha | 2012-01-30 22:15:44 +0100 |
---|---|---|
committer | Johann Latocha | 2012-01-30 22:15:44 +0100 |
commit | 1dc88febdcb2a1d09dfca592bb47106512526b29 (patch) | |
tree | 8fc188c761ec13d6fa96f206ee3c00117a8204d2 /src/kernel | |
parent | [SERVER] Timeout for client sockets (diff) | |
download | dnbd3-1dc88febdcb2a1d09dfca592bb47106512526b29.tar.gz dnbd3-1dc88febdcb2a1d09dfca592bb47106512526b29.tar.xz dnbd3-1dc88febdcb2a1d09dfca592bb47106512526b29.zip |
[ALL] Reformat (line wrapping, indent)
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/blk.c | 209 | ||||
-rw-r--r-- | src/kernel/blk.h | 3 | ||||
-rw-r--r-- | src/kernel/core.c | 50 | ||||
-rw-r--r-- | src/kernel/dnbd3.h | 38 | ||||
-rw-r--r-- | src/kernel/net.c | 494 | ||||
-rw-r--r-- | src/kernel/utils.c | 16 |
6 files changed, 404 insertions, 406 deletions
diff --git a/src/kernel/blk.c b/src/kernel/blk.c index fe66e1d..7a61ba3 100644 --- a/src/kernel/blk.c +++ b/src/kernel/blk.c @@ -23,123 +23,122 @@ int dnbd3_blk_add_device(struct dnbd3_device *dev, int minor) { - struct gendisk *disk; - struct request_queue *blk_queue; - - init_waitqueue_head(&dev->process_queue_send); - init_waitqueue_head(&dev->process_queue_receive); - INIT_LIST_HEAD(&dev->request_queue_send); - INIT_LIST_HEAD(&dev->request_queue_receive); - - if (!(disk = alloc_disk(1))) - { - printk("ERROR: dnbd3 alloc_disk failed.\n"); - return -EIO; - } - - disk->major = major; - disk->first_minor = minor; - sprintf(disk->disk_name, "dnbd%d", minor); - set_capacity(disk, 0); - set_disk_ro(disk, 1); - disk->fops = &dnbd3_blk_ops; - - spin_lock_init(&dev->blk_lock); - if ((blk_queue = blk_init_queue(&dnbd3_blk_request, &dev->blk_lock)) == NULL) - { - printk("ERROR: dnbd3 blk_init_queue failed.\n"); - return -EIO; - } - - blk_queue_logical_block_size(blk_queue, DNBD3_BLOCK_SIZE); - disk->queue = blk_queue; - disk->private_data = dev; - 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; + struct gendisk *disk; + struct request_queue *blk_queue; + + init_waitqueue_head(&dev->process_queue_send); + init_waitqueue_head(&dev->process_queue_receive); + INIT_LIST_HEAD(&dev->request_queue_send); + INIT_LIST_HEAD(&dev->request_queue_receive); + + if (!(disk = alloc_disk(1))) + { + printk("ERROR: dnbd3 alloc_disk failed.\n"); + return -EIO; + } + + disk->major = major; + disk->first_minor = minor; + sprintf(disk->disk_name, "dnbd%d", minor); + set_capacity(disk, 0); + set_disk_ro(disk, 1); + disk->fops = &dnbd3_blk_ops; + + spin_lock_init(&dev->blk_lock); + if ((blk_queue = blk_init_queue(&dnbd3_blk_request, &dev->blk_lock)) == NULL) + { + printk("ERROR: dnbd3 blk_init_queue failed.\n"); + return -EIO; + } + + blk_queue_logical_block_size(blk_queue, DNBD3_BLOCK_SIZE); + disk->queue = blk_queue; + disk->private_data = dev; + 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; } int dnbd3_blk_del_device(struct dnbd3_device *dev) { - if (dev->sock) - { - sock_release(dev->sock); - 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); - return 0; + if (dev->sock) + { + sock_release(dev->sock); + 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); + return 0; } struct block_device_operations dnbd3_blk_ops = { .owner = THIS_MODULE, .ioctl = dnbd3_blk_ioctl, }; -int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, - unsigned long arg) +int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - struct dnbd3_device *lo = bdev->bd_disk->private_data; - - switch (cmd) - { - case IOCTL_SET_HOST: - strcpy(lo->host, (char *) arg); - break; - - case IOCTL_SET_PORT: - strcpy(lo->port, (char *) arg); - break; - case IOCTL_SET_IMAGE: - strcpy(lo->image_id, (char *) arg); - break; - case IOCTL_CONNECT: - if (lo->host && lo->port && lo->image_id) - dnbd3_net_connect(lo); - else - return -1; - break; - case IOCTL_DISCONNECT: - dnbd3_net_disconnect(lo); - break; - case BLKFLSBUF: - break; - - default: - return -1; - - } - return 0; + struct dnbd3_device *lo = bdev->bd_disk->private_data; + + switch (cmd) + { + case IOCTL_SET_HOST: + strcpy(lo->host, (char *) arg); + break; + + case IOCTL_SET_PORT: + strcpy(lo->port, (char *) arg); + break; + case IOCTL_SET_IMAGE: + strcpy(lo->image_id, (char *) arg); + break; + case IOCTL_CONNECT: + if (lo->host && lo->port && lo->image_id) + dnbd3_net_connect(lo); + else + return -1; + break; + case IOCTL_DISCONNECT: + dnbd3_net_disconnect(lo); + break; + case BLKFLSBUF: + break; + + default: + return -1; + + } + return 0; } void dnbd3_blk_request(struct request_queue *q) { - struct request *req; - struct dnbd3_device *lo; - - while ((req = blk_fetch_request(q)) != NULL) - { - lo = req->rq_disk->private_data; - - if (req->cmd_type != REQ_TYPE_FS) - { - __blk_end_request_all(req, 0); - continue; - } - - if (rq_data_dir(req) == READ) - { - list_add_tail(&req->queuelist, &lo->request_queue_send); - spin_unlock_irq(q->queue_lock); - wake_up(&lo->process_queue_send); - spin_lock_irq(q->queue_lock); - } - } + struct request *req; + struct dnbd3_device *lo; + + while ((req = blk_fetch_request(q)) != NULL) + { + lo = req->rq_disk->private_data; + + if (req->cmd_type != REQ_TYPE_FS) + { + __blk_end_request_all(req, 0); + continue; + } + + if (rq_data_dir(req) == READ) + { + list_add_tail(&req->queuelist, &lo->request_queue_send); + spin_unlock_irq(q->queue_lock); + wake_up(&lo->process_queue_send); + spin_lock_irq(q->queue_lock); + } + } } diff --git a/src/kernel/blk.h b/src/kernel/blk.h index 3092b22..039d991 100644 --- a/src/kernel/blk.h +++ b/src/kernel/blk.h @@ -25,8 +25,7 @@ extern struct block_device_operations dnbd3_blk_ops; -int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, - unsigned long arg); +int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); void dnbd3_blk_request(struct request_queue *q); diff --git a/src/kernel/core.c b/src/kernel/core.c index 3dc7ddf..6b50aaa 100644 --- a/src/kernel/core.c +++ b/src/kernel/core.c @@ -26,35 +26,35 @@ 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) - { - printk("ERROR: adding device failed.\n"); - return -EIO; - } - } - printk("INFO: dnbd3 init successful.\n"); - return 0; + 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) + { + printk("ERROR: adding device failed.\n"); + return -EIO; + } + } + printk("INFO: dnbd3 init successful.\n"); + return 0; } static void __exit dnbd3_exit(void) { - int i; - for (i = 0; i < MAX_NUMBER_DEVICES; i++) - { - dnbd3_blk_del_device(&dnbd3_device[i]); - } - unregister_blkdev(major, "dnbd3"); - printk("INFO: dnbd3 exit.\n"); + int i; + for (i = 0; i < MAX_NUMBER_DEVICES; i++) + { + dnbd3_blk_del_device(&dnbd3_device[i]); + } + unregister_blkdev(major, "dnbd3"); + printk("INFO: dnbd3 exit.\n"); } module_init( dnbd3_init); diff --git a/src/kernel/dnbd3.h b/src/kernel/dnbd3.h index 6f31c07..ec9dd6e 100644 --- a/src/kernel/dnbd3.h +++ b/src/kernel/dnbd3.h @@ -33,25 +33,25 @@ extern int major; struct dnbd3_device { - // block - struct gendisk *disk; - spinlock_t blk_lock; - - // network - char host[16]; - 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; - struct task_struct *thread_receive; - wait_queue_head_t process_queue_send; - wait_queue_head_t process_queue_receive; - struct list_head request_queue_send; - struct list_head request_queue_receive; + // block + struct gendisk *disk; + spinlock_t blk_lock; + + // network + char host[16]; + 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; + struct task_struct *thread_receive; + wait_queue_head_t process_queue_send; + wait_queue_head_t process_queue_receive; + struct list_head request_queue_send; + struct list_head request_queue_receive; }; diff --git a/src/kernel/net.c b/src/kernel/net.c index de47ff7..8f3227a 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -23,267 +23,267 @@ void dnbd3_net_connect(struct dnbd3_device *lo) { - struct sockaddr_in sin; - struct msghdr msg; - struct kvec iov; - struct dnbd3_request dnbd3_request; - struct dnbd3_reply dnbd3_reply; - - if (!lo->host || !lo->port || !lo->image_id) - { - printk("ERROR: Host or port not set."); - return; - } - - // TODO: check if allready connected - printk("INFO: Connecting device %s\n", lo->disk->disk_name); - - // initialize socket - if (sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &lo->sock) < 0) - { - printk("ERROR: dnbd3 couldn't create socket.\n"); - return; - } - lo->sock->sk->sk_allocation = GFP_NOIO; - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr(lo->host); - sin.sin_port = htons(simple_strtol(lo->port, NULL, 10)); - if (kernel_connect(lo->sock, (struct sockaddr *) &sin, sizeof(sin), 0) < 0) - { - printk("ERROR: dnbd3 couldn't connect to host %s:%s\n", lo->host, lo->port); - return; - } - - // prepare message and send request - dnbd3_request.cmd = CMD_GET_SIZE; - strcpy(dnbd3_request.image_id, lo->image_id); - 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 - - iov.iov_base = &dnbd3_request; - iov.iov_len = sizeof(dnbd3_request); - kernel_sendmsg(lo->sock, &msg, &iov, 1, sizeof(dnbd3_request)); - - // receive replay - iov.iov_base = &dnbd3_reply; - iov.iov_len = sizeof(dnbd3_reply); - kernel_recvmsg(lo->sock, &msg, &iov, 1, sizeof(dnbd3_reply), msg.msg_flags); - - // set filesize - if (dnbd3_reply.filesize <= 0) - { - printk("ERROR: File size returned by server is < 0.\n"); - return; - } - - printk("INFO: dnbd3 filesize: %llu\n", dnbd3_reply.filesize); - set_capacity(lo->disk, dnbd3_reply.filesize >> 9); /* 512 Byte blocks */ - - // start sending thread - lo->thread_send = kthread_create(dnbd3_net_send, lo, lo->disk->disk_name); - wake_up_process(lo->thread_send); - - // 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); + struct sockaddr_in sin; + struct msghdr msg; + struct kvec iov; + struct dnbd3_request dnbd3_request; + struct dnbd3_reply dnbd3_reply; + + if (!lo->host || !lo->port || !lo->image_id) + { + printk("ERROR: Host or port not set."); + return; + } + + // TODO: check if allready connected + printk("INFO: Connecting device %s\n", lo->disk->disk_name); + + // initialize socket + if (sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &lo->sock) < 0) + { + printk("ERROR: dnbd3 couldn't create socket.\n"); + return; + } + lo->sock->sk->sk_allocation = GFP_NOIO; + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(lo->host); + sin.sin_port = htons(simple_strtol(lo->port, NULL, 10)); + if (kernel_connect(lo->sock, (struct sockaddr *) &sin, sizeof(sin), 0) < 0) + { + printk("ERROR: dnbd3 couldn't connect to host %s:%s\n", lo->host, lo->port); + return; + } + + // prepare message and send request + dnbd3_request.cmd = CMD_GET_SIZE; + strcpy(dnbd3_request.image_id, lo->image_id); + 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 + + iov.iov_base = &dnbd3_request; + iov.iov_len = sizeof(dnbd3_request); + kernel_sendmsg(lo->sock, &msg, &iov, 1, sizeof(dnbd3_request)); + + // receive replay + iov.iov_base = &dnbd3_reply; + iov.iov_len = sizeof(dnbd3_reply); + kernel_recvmsg(lo->sock, &msg, &iov, 1, sizeof(dnbd3_reply), msg.msg_flags); + + // set filesize + if (dnbd3_reply.filesize <= 0) + { + printk("ERROR: File size returned by server is < 0.\n"); + return; + } + + printk("INFO: dnbd3 filesize: %llu\n", dnbd3_reply.filesize); + set_capacity(lo->disk, dnbd3_reply.filesize >> 9); /* 512 Byte blocks */ + + // start sending thread + lo->thread_send = kthread_create(dnbd3_net_send, lo, lo->disk->disk_name); + wake_up_process(lo->thread_send); + + // 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) { - struct request *blk_request, *tmp_request; - printk("INFO: Disconnecting device %s\n", lo->disk->disk_name); - - // kill sending and receiving threads - kthread_stop(lo->thread_send); - kthread_stop(lo->thread_receive); - - // clear sock - if (lo->sock) - { - 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)) - { - printk("WARN: Request queue was not empty on %s\n", lo->disk->disk_name); - spin_lock_irq(&lo->blk_lock); - list_for_each_entry_safe(blk_request, tmp_request, &lo->request_queue_receive, queuelist) - { - list_del_init(&blk_request->queuelist); - list_add_tail(&blk_request->queuelist, &lo->request_queue_send); - } - spin_unlock_irq(&lo->blk_lock); - } + struct request *blk_request, *tmp_request; + printk("INFO: Disconnecting device %s\n", lo->disk->disk_name); + + // kill sending and receiving threads + kthread_stop(lo->thread_send); + kthread_stop(lo->thread_receive); + + // clear sock + if (lo->sock) + { + 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)) + { + printk("WARN: Request queue was not empty on %s\n", lo->disk->disk_name); + spin_lock_irq(&lo->blk_lock); + list_for_each_entry_safe(blk_request, tmp_request, &lo->request_queue_receive, queuelist) + { + list_del_init(&blk_request->queuelist); + list_add_tail(&blk_request->queuelist, &lo->request_queue_send); + } + spin_unlock_irq(&lo->blk_lock); + } } int dnbd3_net_send(void *data) { - struct dnbd3_device *lo = data; - struct dnbd3_request dnbd3_request; - struct request *blk_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 - - set_user_nice(current, -20); - - while (!kthread_should_stop() || !list_empty(&lo->request_queue_send)) - { - wait_event_interruptible(lo->process_queue_send, - kthread_should_stop() || !list_empty(&lo->request_queue_send)); - - if (list_empty(&lo->request_queue_send)) - continue; - - // extract block request - spin_lock_irq(&lo->blk_lock); - blk_request = list_entry(lo->request_queue_send.next, struct request, queuelist); - list_del_init(&blk_request->queuelist); - spin_unlock_irq(&lo->blk_lock); - - 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); - - // send net request - if (kernel_sendmsg(lo->sock, &msg, &iov, 1, sizeof(dnbd3_request)) <= 0) - printk("ERROR: kernel_sendmsg\n"); - - spin_lock_irq(&lo->blk_lock); - list_add_tail(&blk_request->queuelist, &lo->request_queue_receive); - spin_unlock_irq(&lo->blk_lock); - wake_up(&lo->process_queue_receive); - } - return 0; + struct dnbd3_device *lo = data; + struct dnbd3_request dnbd3_request; + struct request *blk_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 + + set_user_nice(current, -20); + + while (!kthread_should_stop() || !list_empty(&lo->request_queue_send)) + { + wait_event_interruptible(lo->process_queue_send, + kthread_should_stop() || !list_empty(&lo->request_queue_send)); + + if (list_empty(&lo->request_queue_send)) + continue; + + // extract block request + spin_lock_irq(&lo->blk_lock); + blk_request = list_entry(lo->request_queue_send.next, struct request, queuelist); + list_del_init(&blk_request->queuelist); + spin_unlock_irq(&lo->blk_lock); + + 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); // bytes left to complete 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); + + // send net request + if (kernel_sendmsg(lo->sock, &msg, &iov, 1, sizeof(dnbd3_request)) <= 0) + printk("ERROR: kernel_sendmsg\n"); + + spin_lock_irq(&lo->blk_lock); + list_add_tail(&blk_request->queuelist, &lo->request_queue_receive); + spin_unlock_irq(&lo->blk_lock); + wake_up(&lo->process_queue_receive); + } + return 0; } int dnbd3_net_receive(void *data) { - struct dnbd3_device *lo = data; - struct dnbd3_reply dnbd3_reply; - struct request *blk_request; - struct msghdr msg; - struct kvec iov; - struct req_iterator iter; - struct bio_vec *bvec; - unsigned long flags; - sigset_t blocked, oldset; - struct request *tmp_request, *received_request; - void *kaddr; - unsigned int size; - - 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 - - set_user_nice(current, -20); - - while (!kthread_should_stop() || !list_empty(&lo->request_queue_receive)) - { - wait_event_interruptible(lo->process_queue_receive, kthread_should_stop() || !list_empty(&lo->request_queue_receive)); - - if (list_empty(&lo->request_queue_receive)) - continue; - - // receive net replay - iov.iov_base = &dnbd3_reply; - iov.iov_len = sizeof(dnbd3_reply); - kernel_recvmsg(lo->sock, &msg, &iov, 1, sizeof(dnbd3_reply), - msg.msg_flags); - - // search for replied request in queue - received_request = *(struct request **) dnbd3_reply.handle; - spin_lock_irq(&lo->blk_lock); - list_for_each_entry_safe(blk_request, tmp_request, &lo->request_queue_receive, queuelist) - { - if (blk_request != received_request) - continue; - - list_del_init(&blk_request->queuelist); - break; - } - spin_unlock_irq(&lo->blk_lock); - - 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); - - kaddr = kmap(bvec->bv_page) + bvec->bv_offset; - size = bvec->bv_len; - iov.iov_base = kaddr; - iov.iov_len = size; - kernel_recvmsg(lo->sock, &msg, &iov, 1, size, msg.msg_flags); - kunmap(bvec->bv_page); - - 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; - } - - } - return 0; + struct dnbd3_device *lo = data; + struct dnbd3_reply dnbd3_reply; + struct request *blk_request; + struct msghdr msg; + struct kvec iov; + struct req_iterator iter; + struct bio_vec *bvec; + unsigned long flags; + sigset_t blocked, oldset; + struct request *tmp_request, *received_request; + void *kaddr; + unsigned int size; + + 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 + + set_user_nice(current, -20); + + while (!kthread_should_stop() || !list_empty(&lo->request_queue_receive)) + { + wait_event_interruptible(lo->process_queue_receive, + kthread_should_stop() || !list_empty(&lo->request_queue_receive)); + + if (list_empty(&lo->request_queue_receive)) + continue; + + // receive net replay + iov.iov_base = &dnbd3_reply; + iov.iov_len = sizeof(dnbd3_reply); + kernel_recvmsg(lo->sock, &msg, &iov, 1, sizeof(dnbd3_reply), msg.msg_flags); + + // search for replied request in queue + received_request = *(struct request **) dnbd3_reply.handle; + spin_lock_irq(&lo->blk_lock); + list_for_each_entry_safe(blk_request, tmp_request, &lo->request_queue_receive, queuelist) + { + if (blk_request != received_request) + continue; + + list_del_init(&blk_request->queuelist); + break; + } + spin_unlock_irq(&lo->blk_lock); + + 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); + + kaddr = kmap(bvec->bv_page) + bvec->bv_offset; + size = bvec->bv_len; + iov.iov_base = kaddr; + iov.iov_len = size; + kernel_recvmsg(lo->sock, &msg, &iov, 1, size, msg.msg_flags); + kunmap(bvec->bv_page); + + 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; + } + + } + 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); + 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/utils.c b/src/kernel/utils.c index 423ceb9..85c0ce0 100644 --- a/src/kernel/utils.c +++ b/src/kernel/utils.c @@ -22,12 +22,12 @@ unsigned int inet_addr(char *str) { - int a, b, c, d; - char arr[4]; - sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d); - arr[0] = a; - arr[1] = b; - arr[2] = c; - arr[3] = d; - return *(unsigned int*) arr; + int a, b, c, d; + char arr[4]; + sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d); + arr[0] = a; + arr[1] = b; + arr[2] = c; + arr[3] = d; + return *(unsigned int*) arr; } |