From 90123ef4fbe457642325362ca07fe5b75df3f0c9 Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Tue, 24 Jan 2012 20:42:30 +0100 Subject: Serving more than one image. --- src/client/client.c | 15 +++++++-- src/config.h | 29 +++++++++++++++++ src/kernel/blk.c | 4 ++- src/kernel/core.c | 5 +-- src/kernel/dnbd3.h | 1 + src/kernel/net.c | 9 +++++- src/server/hashtable.c | 70 +++++++++++++++++++++++++++++++++++++++++ src/server/hashtable.h | 30 ++++++++++++++++++ src/server/server.c | 84 +++++++++++++++++++++++++++++++++++++++++--------- src/types.h | 24 ++++++++++++++- src/version.h | 20 ++++++++++++ 11 files changed, 269 insertions(+), 22 deletions(-) create mode 100644 src/server/hashtable.c create mode 100644 src/server/hashtable.h (limited to 'src') diff --git a/src/client/client.c b/src/client/client.c index 68b7f5c..d60614b 100644 --- a/src/client/client.c +++ b/src/client/client.c @@ -31,10 +31,11 @@ void print_help(char* argv_0) { - printf("Usage: %s -H -p -d \n", argv_0); + printf("Usage: %s -H -p -i -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("-h or --help \t\t Show this help text and quit.\n"); printf("-v or --version \t Show version and quit.\n"); @@ -51,15 +52,17 @@ int main(int argc, char *argv[]) { char *host = NULL; char *port = NULL; + char *image_id = NULL; char *dev = NULL; int opt = 0; int longIndex = 0; - static const char *optString = "H:p:d:hv?"; + static const char *optString = "H:p:i:d: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' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, }; @@ -76,6 +79,9 @@ int main(int argc, char *argv[]) case 'p': port = optarg; break; + case 'i': + image_id = optarg; + break; case 'd': dev = optarg; break; @@ -91,7 +97,7 @@ int main(int argc, char *argv[]) opt = getopt_long(argc, argv, optString, longOpts, &longIndex); } - if (!host || !port || !dev) + if (!host || !port || !dev || !image_id) { printf("FATAL: Not enough information specified\n"); exit(EXIT_FAILURE); @@ -106,6 +112,9 @@ int main(int argc, char *argv[]) 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_CONNECT) < 0) printf("ERROR: ioctl not successful\n"); diff --git a/src/config.h b/src/config.h index 1d31f60..2df4dab 100644 --- a/src/config.h +++ b/src/config.h @@ -1,9 +1,38 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + #ifndef CONFIG_H_ #define CONFIG_H_ +// network #define PORT 5003 +// block device #define KERNEL_SECTOR_SIZE 512 #define DNBD3_BLOCK_SIZE 4096 +// configuration file +#define DEFAULT_CONFIG_FILE "/etc/dnbd3-server.conf" +#define MAX_NUMBER_IMAGES 1024 +#define MAX_FILE_NAME 4096 +#define MAX_FILE_ID 8 + + #endif /* CONFIG_H_ */ diff --git a/src/kernel/blk.c b/src/kernel/blk.c index bf7f4e8..8a31841 100644 --- a/src/kernel/blk.c +++ b/src/kernel/blk.c @@ -36,7 +36,9 @@ int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, case IOCTL_SET_PORT: _port = (char *) arg; break; - + case IOCTL_SET_IMAGE: + _image_id = (char *) arg; + break; case IOCTL_CONNECT: dnbd3_net_connect(); break; diff --git a/src/kernel/core.c b/src/kernel/core.c index 3b6ce54..3fe88f3 100644 --- a/src/kernel/core.c +++ b/src/kernel/core.c @@ -28,8 +28,9 @@ struct request_queue *dnbd3_queue; spinlock_t dnbd3_lock; // network -char* _host; -char* _port; +char* _host = NULL; +char* _port = NULL; +char* _image_id = NULL; struct socket *_sock; // process diff --git a/src/kernel/dnbd3.h b/src/kernel/dnbd3.h index 11eee48..71be4e8 100644 --- a/src/kernel/dnbd3.h +++ b/src/kernel/dnbd3.h @@ -36,6 +36,7 @@ extern spinlock_t dnbd3_lock; // network extern char* _host; extern char* _port; +extern char* _image_id; extern struct socket *_sock; // process diff --git a/src/kernel/net.c b/src/kernel/net.c index 1ec92ca..ac8e81d 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -31,7 +31,7 @@ void dnbd3_net_connect(void) struct task_struct *thread_send; struct task_struct *thread_receive; - if (!_host || !_port) + if (!_host || !_port || !_image_id) { printk("ERROR: Host or port not set."); return; @@ -55,6 +55,7 @@ void dnbd3_net_connect(void) // prepare message and send request dnbd3_request.cmd = CMD_GET_SIZE; + strcpy(dnbd3_request.image_id, _image_id); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; @@ -71,6 +72,12 @@ void dnbd3_net_connect(void) kernel_recvmsg(_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(disk, dnbd3_reply.filesize >> 9); /* 512 Byte blocks */ diff --git a/src/server/hashtable.c b/src/server/hashtable.c new file mode 100644 index 0000000..518454f --- /dev/null +++ b/src/server/hashtable.c @@ -0,0 +1,70 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include + +#include "../config.h" + +char key_buf[MAX_NUMBER_IMAGES * MAX_FILE_ID]; +char value_buf[MAX_NUMBER_IMAGES * MAX_FILE_NAME]; + +char *key_ptr = key_buf; +char *val_ptr = value_buf; + +void ht_create() +{ + (void) hcreate(MAX_NUMBER_IMAGES); +} + +int ht_insert(char* key, char* value) +{ + if (strlen(key) > MAX_FILE_ID) return -1; + if (strlen(value) > MAX_FILE_NAME) return -2; + + strcpy(key_ptr, key); + strcpy(val_ptr, value); + + ENTRY item; + item.key = key_ptr; + item.data = val_ptr; + + (void) hsearch(item, ENTER); + + key_ptr += strlen(key) + 1; + val_ptr += strlen(value) + 1; + + return 0; +} + +char* ht_search(char* key) +{ + ENTRY *result; + + ENTRY item; + item.key = key; + + if ((result = hsearch(item, FIND)) != NULL) + return result->data; + else + return NULL; +} + diff --git a/src/server/hashtable.h b/src/server/hashtable.h new file mode 100644 index 0000000..c05d459 --- /dev/null +++ b/src/server/hashtable.h @@ -0,0 +1,30 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef HASHTABLE_H_ +#define HASHTABLE_H_ + +void ht_create (); + +int ht_insert(char* key, char* value); + +char* ht_search(char* key); + +#endif /* HASHTABLE_H_ */ diff --git a/src/server/server.c b/src/server/server.c index 7f62a53..7185e2f 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -1,3 +1,23 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + #include #include #include @@ -19,17 +39,16 @@ #include "../types.h" #include "../version.h" -int file; -off_t filesize; +#include "hashtable.h" void print_help(char* argv_0) { printf("Usage: %s [OPTIONS]...\n", argv_0); - printf("Start the DNBD3 server.\n"); - printf("-f or --file \t\t File to export.\n"); - printf("-h or --help \t\t Show this help text and quit.\n"); - printf("-v or --version \t Show version and quit.\n"); + printf("Start the DNBD3 server\n"); + printf("-f or --file \t\t Configuration file\n \t\t\t (default /etc/dnbd3-server.conf)\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(0); } @@ -47,6 +66,8 @@ void handle_sigpipe(int signum) void *handle_query(void *client_socket) { + int image_file = -1; + off_t filesize = 0; int sock = (int) client_socket; struct dnbd3_request request; struct dnbd3_reply reply; @@ -58,23 +79,40 @@ void *handle_query(void *client_socket) switch (cmd) { case CMD_GET_SIZE: + image_file = open(ht_search(request.image_id), O_RDONLY); + if (image_file < 0) + { + printf("ERROR: Client requested an unknown image id.\n"); + filesize = 0; + } + else + { + struct stat st; + fstat(image_file, &st); + filesize = st.st_size; + } + reply.cmd = request.cmd; reply.filesize = filesize; send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); break; case CMD_GET_BLOCK: + if (image_file < 0) + break; + reply.cmd = request.cmd; memcpy(reply.handle, request.handle, sizeof(request.handle)); send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); - if (sendfile(sock, file, (off_t *) &request.offset, request.size) <0) + if (sendfile(sock, image_file, (off_t *) &request.offset, request.size) <0) printf("ERROR: sendfile returned -1\n"); break; default: printf("ERROR: Unknown command\n"); + break; } } @@ -85,6 +123,8 @@ void *handle_query(void *client_socket) int main(int argc, char* argv[]) { + char *config_file_name = DEFAULT_CONFIG_FILE; + int opt = 0; int longIndex = 0; static const char *optString = "f:hv?"; @@ -95,18 +135,13 @@ int main(int argc, char* argv[]) { "version", no_argument, NULL, 'v' } }; opt = getopt_long(argc, argv, optString, longOpts, &longIndex); - if (opt == -1) - print_help(argv[0]); while (opt != -1) { switch (opt) { case 'f': - file = open(optarg, O_RDONLY); - struct stat st; - fstat(file, &st); - filesize = st.st_size; + config_file_name = optarg; break; case 'h': print_help(argv[0]); @@ -120,6 +155,28 @@ int main(int argc, char* argv[]) opt = getopt_long(argc, argv, optString, longOpts, &longIndex); } + // parse config file + ht_create(); + FILE *config_file = fopen(config_file_name , "r"); + if (config_file == NULL) + { + printf("ERROR: Config file not found: %s\n", config_file_name); + exit(EXIT_FAILURE); + } + char line[MAX_FILE_NAME + 1 + MAX_FILE_ID]; + char* image_name = NULL; + char* image_id = NULL; + while (fgets (line , sizeof(line) , config_file) != NULL ) + { + sscanf (line, "%as %as", &image_name, &image_id); + if (ht_insert(image_id, image_name) < 0) + { + printf("ERROR: Image name or ID is too big\n"); + exit(EXIT_FAILURE); + } + } + + // setup network signal(SIGPIPE, handle_sigpipe); struct sockaddr_in server; @@ -154,7 +211,6 @@ int main(int argc, char* argv[]) exit(EXIT_FAILURE); } - printf("INFO: Filesize: %llu bytes\n", filesize); printf("INFO: Server is ready...\n"); while (1) diff --git a/src/types.h b/src/types.h index 3005f62..f3b2b97 100644 --- a/src/types.h +++ b/src/types.h @@ -1,3 +1,23 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + #ifndef TYPES_H_ #define TYPES_H_ @@ -7,7 +27,8 @@ #define DNBD3_MAGIC 'd' #define IOCTL_SET_HOST _IO(0xab, 1) #define IOCTL_SET_PORT _IO(0xab, 2) -#define IOCTL_CONNECT _IO(0xab, 3) +#define IOCTL_SET_IMAGE _IO(0xab, 3) +#define IOCTL_CONNECT _IO(0xab, 4) // network #define CMD_GET_BLOCK 1 @@ -18,6 +39,7 @@ typedef struct dnbd3_request { uint16_t cmd; uint64_t offset; uint64_t size; + char image_id[MAX_FILE_ID]; char handle[8]; } dnbd3_request_t; #pragma pack(0) diff --git a/src/version.h b/src/version.h index 86e034a..bbaaf41 100644 --- a/src/version.h +++ b/src/version.h @@ -1,3 +1,23 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + #ifndef VERSION_H_ #define VERSION_H_ -- cgit v1.2.3-55-g7522