From 23c91a086d70898303ca3f8a0fb70a161b79bb37 Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Mon, 30 Jan 2012 12:28:38 +0100 Subject: [KERNEL] Change server at runtime [SERVER] Build error/warning on x64 fixed --- CMakeLists.txt | 4 ++-- src/client/client.c | 57 +++++++++++++++++++++++++++++++++++++---------------- src/kernel/blk.c | 17 ++++++++++++---- src/kernel/dnbd3.h | 8 +++++--- src/kernel/net.c | 49 +++++++++++++++++++++++++++++++++++++-------- src/kernel/net.h | 2 ++ src/server/server.c | 5 ++--- src/types.h | 9 +++++---- 8 files changed, 110 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1874d0..78deb01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,8 +39,8 @@ TARGET_LINK_LIBRARIES(dnbd3-server ${CMAKE_THREAD_LIBS_INIT}) SET(MODULE_NAME dnbd3) SET(MODULE_FILE ${MODULE_NAME}.ko) -FILE(GLOB_RECURSE MODULE_SOURCE_FILES src/kernel/*.c) -FILE(GLOB_RECURSE MODULE_HEADER_FILES src/kernel/*.h src/*.h) +FILE(GLOB MODULE_SOURCE_FILES src/kernel/*.c) +FILE(GLOB MODULE_HEADER_FILES src/kernel/*.h src/*.h) SET(KERNEL_DIR "/lib/modules/${CMAKE_SYSTEM_VERSION}/build") diff --git a/src/client/client.c b/src/client/client.c index d60614b..54535a3 100644 --- a/src/client/client.c +++ b/src/client/client.c @@ -31,12 +31,13 @@ void print_help(char* argv_0) { - printf("Usage: %s -H -p -i -d \n", argv_0); + printf("Usage: %s -H -p -i -d || -c -d \n", argv_0); printf("Start the DNBD3 client.\n"); printf("-H or --host \t\t Host running dnbd3-server.\n"); printf("-p or --port \t\t Port used by server.\n"); printf("-i or --image \t\t Exported image ID.\n"); printf("-d or --device \t\t DNBD3 device name.\n"); + printf("-c or --changehost \t Change 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); @@ -50,20 +51,23 @@ void print_version() int main(int argc, char *argv[]) { + int fd; char *host = NULL; char *port = NULL; char *image_id = NULL; char *dev = NULL; + int change_host = 0; int opt = 0; int longIndex = 0; - static const char *optString = "H:p:i:d:hv?"; + static const char *optString = "H:p:i:d:D:c:hv?"; static const struct option longOpts[] = { { "host", required_argument, NULL, 'H' }, { "port", required_argument, NULL, 'p' }, { "image", required_argument, NULL, 'i' }, { "device", required_argument, NULL, 'd' }, + { "changehost", required_argument, NULL, 'c' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, }; @@ -85,6 +89,10 @@ int main(int argc, char *argv[]) case 'd': dev = optarg; break; + case 'c': + host = optarg; + change_host = 1; + break; case 'h': print_help(argv[0]); break; @@ -97,28 +105,43 @@ int main(int argc, char *argv[]) opt = getopt_long(argc, argv, optString, longOpts, &longIndex); } - if (!host || !port || !dev || !image_id) + if (change_host && host && dev && !port && !image_id) { - printf("FATAL: Not enough information specified\n"); - exit(EXIT_FAILURE); + fd = open(dev, O_RDONLY); + + if (ioctl(fd, IOCTL_DISCONNECT) < 0) + printf("ERROR: ioctl not successful\n"); + + if (ioctl(fd, IOCTL_SET_HOST, host) < 0) + printf("ERROR: ioctl not successful\n"); + + if (ioctl(fd, IOCTL_CONNECT) < 0) + printf("ERROR: ioctl not successful\n"); + + close(fd); + exit(EXIT_SUCCESS); } - int fd; - fd = open(dev, O_RDONLY); + if (host && port && dev && image_id) + { + fd = open(dev, O_RDONLY); - if (ioctl(fd, IOCTL_SET_HOST, host) < 0) - printf("ERROR: ioctl not successful\n"); + 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_PORT, port) < 0) + printf("ERROR: ioctl not successful\n"); - if (ioctl(fd, IOCTL_SET_IMAGE, image_id) < 0) - printf("ERROR: ioctl not successful\n"); + if (ioctl(fd, IOCTL_SET_IMAGE, image_id) < 0) + printf("ERROR: ioctl not successful\n"); - if (ioctl(fd, IOCTL_CONNECT) < 0) - printf("ERROR: ioctl not successful\n"); + if (ioctl(fd, IOCTL_CONNECT) < 0) + printf("ERROR: ioctl not successful\n"); - close(fd); + close(fd); + exit(EXIT_SUCCESS); + } - exit(EXIT_SUCCESS); + print_help(argv[0]); + exit(EXIT_FAILURE); } diff --git a/src/kernel/blk.c b/src/kernel/blk.c index 213ae23..c495205 100644 --- a/src/kernel/blk.c +++ b/src/kernel/blk.c @@ -64,7 +64,10 @@ int dnbd3_blk_add_device(struct dnbd3_device *dev, int minor) int dnbd3_blk_del_device(struct dnbd3_device *dev) { if (dev->sock) + { sock_release(dev->sock); + dev->sock = NULL; + } del_gendisk(dev->disk); put_disk(dev->disk); @@ -83,17 +86,23 @@ int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, switch (cmd) { case IOCTL_SET_HOST: - lo->host = (char *) arg; + strcpy(lo->host, (char *) arg); break; case IOCTL_SET_PORT: - lo->port = (char *) arg; + strcpy(lo->port, (char *) arg); break; case IOCTL_SET_IMAGE: - lo->image_id = (char *) arg; + strcpy(lo->image_id, (char *) arg); break; case IOCTL_CONNECT: - dnbd3_net_connect(lo); + 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; diff --git a/src/kernel/dnbd3.h b/src/kernel/dnbd3.h index 561c554..5f45699 100644 --- a/src/kernel/dnbd3.h +++ b/src/kernel/dnbd3.h @@ -39,12 +39,14 @@ struct dnbd3_device spinlock_t blk_lock; // network - char* host; - char* port; - char* image_id; + char host[16]; + char port[6]; + char image_id[MAX_FILE_NAME]; struct socket *sock; // 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; diff --git a/src/kernel/net.c b/src/kernel/net.c index 9a323e8..c3f9782 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -28,8 +28,6 @@ void dnbd3_net_connect(struct dnbd3_device *lo) struct kvec iov; struct dnbd3_request dnbd3_request; struct dnbd3_reply dnbd3_reply; - struct task_struct *thread_send; - struct task_struct *thread_receive; if (!lo->host || !lo->port || !lo->image_id) { @@ -37,6 +35,9 @@ void dnbd3_net_connect(struct dnbd3_device *lo) return; } + // FIXME: 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) { @@ -49,7 +50,7 @@ void dnbd3_net_connect(struct dnbd3_device *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 given host.\n"); + printk("ERROR: dnbd3 couldn't connect to host %s:%s\n", lo->host, lo->port); return; } @@ -82,12 +83,42 @@ void dnbd3_net_connect(struct dnbd3_device *lo) set_capacity(lo->disk, dnbd3_reply.filesize >> 9); /* 512 Byte blocks */ // start sending thread - thread_send = kthread_create(dnbd3_net_send, lo, lo->disk->disk_name); - wake_up_process(thread_send); + lo->thread_send = kthread_create(dnbd3_net_send, lo, lo->disk->disk_name); + wake_up_process(lo->thread_send); // start receiving thread - thread_receive = kthread_create(dnbd3_net_receive, lo, lo->disk->disk_name); - wake_up_process(thread_receive); + lo->thread_receive = kthread_create(dnbd3_net_receive, lo, lo->disk->disk_name); + wake_up_process(lo->thread_receive); +} + +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; + } + + // 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) @@ -167,6 +198,9 @@ int dnbd3_net_receive(void *data) { 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); @@ -206,6 +240,5 @@ int dnbd3_net_receive(void *data) __blk_end_request_all(blk_request, 0); spin_unlock_irqrestore(&lo->blk_lock, flags); } - return 0; } diff --git a/src/kernel/net.h b/src/kernel/net.h index 5ac8f6f..017a71e 100644 --- a/src/kernel/net.h +++ b/src/kernel/net.h @@ -25,6 +25,8 @@ void dnbd3_net_connect(struct dnbd3_device *lo); +void dnbd3_net_disconnect(struct dnbd3_device *lo); + int dnbd3_net_send(void *data); int dnbd3_net_receive(void *data); diff --git a/src/server/server.c b/src/server/server.c index 90ec77b..4dbeb7f 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -79,7 +79,6 @@ void handle_sighup(int signum) pthread_spin_lock(&spinlock); reload_config(config_file_name); pthread_spin_unlock(&spinlock); - // TODO: stop handle_query or use mutex before image_file = open(ht_search(request.image_id), O_RDONLY); } void handle_sigterm(int signum) @@ -94,7 +93,7 @@ void *handle_query(void *client_socket) { int image_file = -1; off_t filesize = 0; - int sock = (int) client_socket; + int sock = (int)(uintptr_t) client_socket; struct dnbd3_request request; struct dnbd3_reply reply; uint16_t cmd; @@ -258,7 +257,7 @@ int main(int argc, char* argv[]) // FIXME: catch SIGKILL/SIGTERM and close all socket before exit pthread_t thread; - pthread_create(&(thread), NULL, handle_query, (void *) fd); + pthread_create(&(thread), NULL, handle_query, (void *)(uintptr_t) fd); pthread_detach(thread); } diff --git a/src/types.h b/src/types.h index f4ff98e..3e03d97 100644 --- a/src/types.h +++ b/src/types.h @@ -25,10 +25,11 @@ // ioctl #define DNBD3_MAGIC 'd' -#define IOCTL_SET_HOST _IO(0xab, 1) -#define IOCTL_SET_PORT _IO(0xab, 2) -#define IOCTL_SET_IMAGE _IO(0xab, 3) -#define IOCTL_CONNECT _IO(0xab, 4) +#define IOCTL_SET_HOST _IO(0xab, 1) +#define IOCTL_SET_PORT _IO(0xab, 2) +#define IOCTL_SET_IMAGE _IO(0xab, 3) +#define IOCTL_CONNECT _IO(0xab, 4) +#define IOCTL_DISCONNECT _IO(0xab, 5) // network #define CMD_GET_BLOCK 1 -- cgit v1.2.3-55-g7522