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/client/client.c | 113 ++++++++++++++++++++++++++++------------------------ src/kernel/blk.c | 38 +++++++++++------- src/kernel/net.c | 20 ++++++++-- src/types.h | 19 +++++---- 4 files changed, 112 insertions(+), 78 deletions(-) diff --git a/src/client/client.c b/src/client/client.c index 564d6b0..723e650 100644 --- a/src/client/client.c +++ b/src/client/client.c @@ -34,7 +34,9 @@ char *_config_file_name = DEFAULT_CLIENT_CONFIG_FILE; void dnbd3_print_help(char* argv_0) { - printf("Usage: %s -h -p -v -r -d || -f file\n", argv_0); + printf( + "Usage: %s -h -p -v -r -d || -f || -c \n", + argv_0); printf("Start the DNBD3 client.\n"); printf("-f or --file \t\t Configuration file (default /etc/dnbd3-client.conf)\n"); printf("-h or --host \t\t Host running dnbd3-server.\n"); @@ -42,7 +44,8 @@ void dnbd3_print_help(char* argv_0) printf("-v or --vid \t\t Volume-ID of exported image.\n"); printf("-r or --rid \t\t Release-ID of exported image.\n"); printf("-d or --device \t\t DNBD3 device name.\n"); - printf("-c or --changehost \t Change dnbd3-server on device (DEBUG).\n"); + printf("-c or --close \t\t Disconnect and close device.\n"); + printf("-s or --switch \t Switch dnbd3-server on device (DEBUG).\n"); printf("-H or --help \t\t Show this help text and quit.\n"); printf("-V or --version \t Show version and quit.\n"); exit(EXIT_SUCCESS); @@ -54,43 +57,23 @@ void dnbd3_print_version() exit(EXIT_SUCCESS); } -void dnbd3_connect(char *host, char *port, int vid, int rid, char *dev) -{ - int fd = open(dev, O_WRONLY); - - printf("Connecting %s to %s:%s vid:%i rid:%i\n", dev, host, port, vid, rid); - - if (ioctl(fd, IOCTL_SET_HOST, host) < 0) - printf("ERROR: ioctl not successful\n"); - - if (ioctl(fd, IOCTL_SET_PORT, port) < 0) - printf("ERROR: ioctl not successful\n"); - - if (ioctl(fd, IOCTL_SET_VID, vid) < 0) - printf("ERROR: ioctl not successful\n"); - - if (ioctl(fd, IOCTL_SET_RID, rid) < 0) - printf("ERROR: ioctl not successful\n"); - - if (ioctl(fd, IOCTL_CONNECT) < 0) - printf("ERROR: ioctl not successful\n"); - - close(fd); -} - int main(int argc, char *argv[]) { int fd; - char *host = NULL; - char *port = NULL; - int vid = 0; - int rid = 0; char *dev = NULL; - int change_host = 0; + + int close_dev = 0; + int switch_host = 0; + + dnbd3_ioctl_t msg; + msg.host = NULL; + msg.port = NULL; + msg.vid = 0; + msg.rid = 0; int opt = 0; int longIndex = 0; - static const char *optString = "f:h:p:v:r:d:c:HV?"; + static const char *optString = "f:h:p:v:r:d:c:s:HV?"; static const struct option longOpts[] = { { "file", required_argument, NULL, 'f' }, @@ -99,7 +82,8 @@ int main(int argc, char *argv[]) { "vid", required_argument, NULL, 'v' }, { "rid", required_argument, NULL, 'r' }, { "device", required_argument, NULL, 'd' }, - { "changehost", required_argument, NULL, 'c' }, + { "close", required_argument, NULL, 'c' }, + { "switch", required_argument, NULL, 's' }, { "help", no_argument, NULL, 'H' }, { "version", no_argument, NULL, 'V' }, }; @@ -113,23 +97,27 @@ int main(int argc, char *argv[]) _config_file_name = optarg; break; case 'h': - host = optarg; + msg.host = optarg; break; case 'p': - port = optarg; + msg.port = optarg; break; case 'v': - vid = atoi(optarg); + msg.vid = atoi(optarg); break; case 'r': - rid = atoi(optarg); + msg.rid = atoi(optarg); break; case 'd': dev = optarg; break; case 'c': - host = optarg; - change_host = 1; + dev = optarg; + close_dev = 1; + break; + case 's': + msg.host = optarg; + switch_host = 1; break; case 'H': dnbd3_print_help(argv[0]); @@ -143,18 +131,26 @@ int main(int argc, char *argv[]) opt = getopt_long(argc, argv, optString, longOpts, &longIndex); } - // change host - if (change_host && host && dev && !port && (vid == 0) && (rid == 0)) + // close device + if (close_dev && !msg.host && dev && !msg.port && (msg.vid == 0) && (msg.rid == 0)) { fd = open(dev, O_WRONLY); + printf("INFO: Closing device %s\n", dev); - if (ioctl(fd, IOCTL_DISCONNECT) < 0) + if (ioctl(fd, IOCTL_CLOSE, &msg) < 0) printf("ERROR: ioctl not successful\n"); - if (ioctl(fd, IOCTL_SET_HOST, host) < 0) - printf("ERROR: ioctl not successful\n"); + close(fd); + exit(EXIT_SUCCESS); + } - if (ioctl(fd, IOCTL_CONNECT) < 0) + // switch host + if (switch_host && msg.host && dev && !msg.port && (msg.vid == 0) && (msg.rid == 0)) + { + fd = open(dev, O_WRONLY); + printf("INFO: Switching device %s to %s\n", dev, msg.host); + + if (ioctl(fd, IOCTL_SWITCH, &msg) < 0) printf("ERROR: ioctl not successful\n"); close(fd); @@ -162,9 +158,15 @@ int main(int argc, char *argv[]) } // connect - if (host && port && dev && (vid != 0) && (rid != 0)) + if (msg.host && msg.port && dev && (msg.vid != 0) && (msg.rid != 0)) { - dnbd3_connect(host, port, vid, rid, dev); + fd = open(dev, O_WRONLY); + printf("INFO: Connecting %s to %s:%s vid:%i rid:%i\n", dev, msg.host, msg.port, msg.vid, msg.rid); + + if (ioctl(fd, IOCTL_OPEN, &msg) < 0) + printf("ERROR: ioctl not successful\n"); + + close(fd); exit(EXIT_SUCCESS); } @@ -182,12 +184,19 @@ int main(int argc, char *argv[]) for (i = 0; i < j; i++) { - host = g_key_file_get_string(gkf, groups[i], "server", NULL); - port = g_key_file_get_string(gkf, groups[i], "port", NULL); - vid = g_key_file_get_integer(gkf, groups[i], "vid", NULL); - rid = g_key_file_get_integer(gkf, groups[i], "rid", NULL); + msg.host = g_key_file_get_string(gkf, groups[i], "server", NULL); + msg.port = g_key_file_get_string(gkf, groups[i], "port", NULL); + msg.vid = g_key_file_get_integer(gkf, groups[i], "vid", NULL); + msg.rid = g_key_file_get_integer(gkf, groups[i], "rid", NULL); dev = g_key_file_get_string(gkf, groups[i], "device", NULL); - dnbd3_connect(host, port, vid, rid, dev); + + fd = open(dev, O_WRONLY); + printf("INFO: Connecting %s to %s:%s vid:%i rid:%i\n", dev, msg.host, msg.port, msg.vid, msg.rid); + + if (ioctl(fd, IOCTL_OPEN, &msg) < 0) + printf("ERROR: ioctl not successful\n"); + + close(fd); } g_strfreev(groups); 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 diff --git a/src/types.h b/src/types.h index 7f5c392..bb2d082 100644 --- a/src/types.h +++ b/src/types.h @@ -24,13 +24,18 @@ #include "config.h" // ioctl -#define DNBD3_MAGIC 'd' -#define IOCTL_SET_HOST _IO(0xab, 1) -#define IOCTL_SET_PORT _IO(0xab, 2) -#define IOCTL_SET_VID _IO(0xab, 3) -#define IOCTL_SET_RID _IO(0xab, 4) -#define IOCTL_CONNECT _IO(0xab, 5) -#define IOCTL_DISCONNECT _IO(0xab, 6) +#define DNBD3_MAGIC 'd' +#define IOCTL_OPEN _IO(0xab, 1) +#define IOCTL_CLOSE _IO(0xab, 2) +#define IOCTL_SWITCH _IO(0xab, 3) + +typedef struct +{ + char *host; + char *port; + int vid; + int rid; +} dnbd3_ioctl_t; // network #define CMD_GET_BLOCK 1 -- cgit v1.2.3-55-g7522