From 6b40869a06d6fb3331630409e0949b75caeb9923 Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Fri, 3 Feb 2012 20:15:25 +0100 Subject: [KERNEL] Device can now be closed --- src/kernel/blk.c | 38 +++++++++++++++++++++++--------------- src/kernel/net.c | 20 ++++++++++++++++---- 2 files changed, 39 insertions(+), 19 deletions(-) (limited to 'src/kernel') diff --git a/src/kernel/blk.c b/src/kernel/blk.c index c4bbeb1..46e20d8 100644 --- a/src/kernel/blk.c +++ b/src/kernel/blk.c @@ -33,6 +33,7 @@ int dnbd3_blk_add_device(dnbd3_device_t *dev, int minor) dev->vid = 0; dev->rid = 0; + dev->sock = NULL; if (!(disk = alloc_disk(1))) { @@ -89,34 +90,41 @@ struct block_device_operations dnbd3_blk_ops = int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { dnbd3_device_t *lo = bdev->bd_disk->private_data; + int minor = lo->disk->first_minor; + + dnbd3_ioctl_t *msg = kmalloc(sizeof(dnbd3_ioctl_t), GFP_KERNEL); + copy_from_user((char *)msg, (char *)arg, sizeof(*msg)); 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_VID: - lo->vid = arg; - break; - case IOCTL_SET_RID: - lo->rid = arg; - break; - case IOCTL_CONNECT: + case IOCTL_OPEN: + strcpy(lo->host, msg->host); + strcpy(lo->port, msg->port); + lo->vid = msg->vid; + lo->rid = msg->rid; dnbd3_net_connect(lo); break; - case IOCTL_DISCONNECT: + + case IOCTL_CLOSE: dnbd3_net_disconnect(lo); + dnbd3_blk_del_device(lo); + dnbd3_blk_add_device(lo, minor); break; + + case IOCTL_SWITCH: + dnbd3_net_disconnect(lo); + strcpy(lo->host, msg->host); + dnbd3_net_connect(lo); + break; + case BLKFLSBUF: break; default: return -1; - } + + kfree(msg); return 0; } diff --git a/src/kernel/net.c b/src/kernel/net.c index a83b4b6..53a12af 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -35,13 +35,19 @@ void dnbd3_net_connect(dnbd3_device_t *lo) return; } - // TODO: check if already connected + if (lo->sock) + { + printk("ERROR: Device %s already connected to %s.\n", lo->disk->disk_name, lo->host); + return; + } + printk("INFO: Connecting device %s to %s\n", lo->disk->disk_name, lo->host); // initialize socket if (sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &lo->sock) < 0) { - printk("ERROR: dnbd3 couldn't create socket.\n"); + printk("ERROR: Couldn't create socket.\n"); + lo->sock = NULL; return; } lo->sock->sk->sk_allocation = GFP_NOIO; @@ -50,7 +56,8 @@ void dnbd3_net_connect(dnbd3_device_t *lo) 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); + printk("ERROR: Couldn't connect to host %s:%s\n", lo->host, lo->port); + lo->sock = NULL; return; } @@ -78,10 +85,13 @@ void dnbd3_net_connect(dnbd3_device_t *lo) if (dnbd3_reply.filesize <= 0) { printk("ERROR: File size returned by server is < 0.\n"); + sock_release(lo->sock); + lo->sock = NULL; return; } + set_capacity(lo->disk, dnbd3_reply.filesize >> 9); /* 512 Byte blocks */ - printk("INFO: dnbd3 filesize: %llu\n", dnbd3_reply.filesize); + printk("INFO: Filesize %s: %llu\n", lo->disk->disk_name, dnbd3_reply.filesize); // start sending thread lo->thread_send = kthread_create(dnbd3_net_send, lo, lo->disk->disk_name); @@ -109,6 +119,8 @@ void dnbd3_net_disconnect(dnbd3_device_t *lo) { kthread_stop(lo->thread_send); kthread_stop(lo->thread_receive); + lo->thread_send = NULL; + lo->thread_receive = NULL; } // clear sock -- cgit v1.2.3-55-g7522