summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/client/client.c113
-rw-r--r--src/kernel/blk.c38
-rw-r--r--src/kernel/net.c20
-rw-r--r--src/types.h19
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 <host> -p <port> -v <vid> -r <rid> -d <device> || -f file\n", argv_0);
+ printf(
+ "Usage: %s -h <host> -p <port> -v <vid> -r <rid> -d <device> || -f <file> || -c <device>\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