]> git.proxmox.com Git - qemu.git/commitdiff
add support for protocol driver create_options
authorMORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Wed, 26 May 2010 02:35:36 +0000 (11:35 +0900)
committerKevin Wolf <kwolf@redhat.com>
Fri, 28 May 2010 11:14:25 +0000 (13:14 +0200)
This patch enables protocol drivers to use their create options which
are not supported by the format.  For example, protcol drivers can use
a backing_file option with raw format.

Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
block.c
block.h
qemu-img.c
qemu-option.c
qemu-option.h

diff --git a/block.c b/block.c
index 47be5ba1255c62c0320c0330c0c24f8702fdf9f5..24c63f6338945b3c168c9f9adc436e0cb5e7f0fb 100644 (file)
--- a/block.c
+++ b/block.c
@@ -56,7 +56,6 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
                         uint8_t *buf, int nb_sectors);
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
                          const uint8_t *buf, int nb_sectors);
-static BlockDriver *find_protocol(const char *filename);
 
 static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
     QTAILQ_HEAD_INITIALIZER(bdrv_states);
@@ -210,7 +209,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
 {
     BlockDriver *drv;
 
-    drv = find_protocol(filename);
+    drv = bdrv_find_protocol(filename);
     if (drv == NULL) {
         drv = bdrv_find_format("file");
     }
@@ -283,7 +282,7 @@ static BlockDriver *find_hdev_driver(const char *filename)
     return drv;
 }
 
-static BlockDriver *find_protocol(const char *filename)
+BlockDriver *bdrv_find_protocol(const char *filename)
 {
     BlockDriver *drv1;
     char protocol[128];
@@ -478,7 +477,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     BlockDriver *drv;
     int ret;
 
-    drv = find_protocol(filename);
+    drv = bdrv_find_protocol(filename);
     if (!drv) {
         return -ENOENT;
     }
diff --git a/block.h b/block.h
index 24efeb68b11799b01f04bef2aeb8848df3786e92..9034ebb92404eac623dd7db820f66714ba6b12ac 100644 (file)
--- a/block.h
+++ b/block.h
@@ -54,6 +54,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data);
 
 void bdrv_init(void);
 void bdrv_init_with_whitelist(void);
+BlockDriver *bdrv_find_protocol(const char *filename);
 BlockDriver *bdrv_find_format(const char *format_name);
 BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
 int bdrv_create(BlockDriver *drv, const char* filename,
index cb007b757dc68d1bd4cf03118917a9f743390593..ea091f00ca67ed042139c2739bc56ba7fd4c4afd 100644 (file)
@@ -252,8 +252,8 @@ static int img_create(int argc, char **argv)
     const char *base_fmt = NULL;
     const char *filename;
     const char *base_filename = NULL;
-    BlockDriver *drv;
-    QEMUOptionParameter *param = NULL;
+    BlockDriver *drv, *proto_drv;
+    QEMUOptionParameter *param = NULL, *create_options = NULL;
     char *options = NULL;
 
     flags = 0;
@@ -286,33 +286,42 @@ static int img_create(int argc, char **argv)
         }
     }
 
+    /* Get the filename */
+    if (optind >= argc)
+        help();
+    filename = argv[optind++];
+
     /* Find driver and parse its options */
     drv = bdrv_find_format(fmt);
     if (!drv)
         error("Unknown file format '%s'", fmt);
 
+    proto_drv = bdrv_find_protocol(filename);
+    if (!proto_drv)
+        error("Unknown protocol '%s'", filename);
+
+    create_options = append_option_parameters(create_options,
+                                              drv->create_options);
+    create_options = append_option_parameters(create_options,
+                                              proto_drv->create_options);
+
     if (options && !strcmp(options, "?")) {
-        print_option_help(drv->create_options);
+        print_option_help(create_options);
         return 0;
     }
 
     /* Create parameter list with default values */
-    param = parse_option_parameters("", drv->create_options, param);
+    param = parse_option_parameters("", create_options, param);
     set_option_parameter_int(param, BLOCK_OPT_SIZE, -1);
 
     /* Parse -o options */
     if (options) {
-        param = parse_option_parameters(options, drv->create_options, param);
+        param = parse_option_parameters(options, create_options, param);
         if (param == NULL) {
             error("Invalid options for file format '%s'.", fmt);
         }
     }
 
-    /* Get the filename */
-    if (optind >= argc)
-        help();
-    filename = argv[optind++];
-
     /* Add size to parameters */
     if (optind < argc) {
         set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
@@ -362,6 +371,7 @@ static int img_create(int argc, char **argv)
     puts("");
 
     ret = bdrv_create(drv, filename, param);
+    free_option_parameters(create_options);
     free_option_parameters(param);
 
     if (ret < 0) {
@@ -543,14 +553,14 @@ static int img_convert(int argc, char **argv)
 {
     int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
     const char *fmt, *out_fmt, *out_baseimg, *out_filename;
-    BlockDriver *drv;
+    BlockDriver *drv, *proto_drv;
     BlockDriverState **bs, *out_bs;
     int64_t total_sectors, nb_sectors, sector_num, bs_offset;
     uint64_t bs_sectors;
     uint8_t * buf;
     const uint8_t *buf1;
     BlockDriverInfo bdi;
-    QEMUOptionParameter *param = NULL;
+    QEMUOptionParameter *param = NULL, *create_options = NULL;
     char *options = NULL;
 
     fmt = NULL;
@@ -615,19 +625,27 @@ static int img_convert(int argc, char **argv)
     if (!drv)
         error("Unknown file format '%s'", out_fmt);
 
+    proto_drv = bdrv_find_protocol(out_filename);
+    if (!proto_drv)
+        error("Unknown protocol '%s'", out_filename);
+
+    create_options = append_option_parameters(create_options,
+                                              drv->create_options);
+    create_options = append_option_parameters(create_options,
+                                              proto_drv->create_options);
     if (options && !strcmp(options, "?")) {
-        print_option_help(drv->create_options);
+        print_option_help(create_options);
         free(bs);
         return 0;
     }
 
     if (options) {
-        param = parse_option_parameters(options, drv->create_options, param);
+        param = parse_option_parameters(options, create_options, param);
         if (param == NULL) {
             error("Invalid options for file format '%s'.", out_fmt);
         }
     } else {
-        param = parse_option_parameters("", drv->create_options, param);
+        param = parse_option_parameters("", create_options, param);
     }
 
     set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
@@ -649,6 +667,7 @@ static int img_convert(int argc, char **argv)
 
     /* Create the new image */
     ret = bdrv_create(drv, out_filename, param);
+    free_option_parameters(create_options);
     free_option_parameters(param);
 
     if (ret < 0) {
index 076dddfc026c02bc3eb40b826c9b0222f0d872a4..acd74f91247f5b8d21e008152e3ea8b7c9e9da44 100644 (file)
@@ -345,6 +345,51 @@ void free_option_parameters(QEMUOptionParameter *list)
     qemu_free(list);
 }
 
+/*
+ * Count valid options in list
+ */
+static size_t count_option_parameters(QEMUOptionParameter *list)
+{
+    size_t num_options = 0;
+
+    while (list && list->name) {
+        num_options++;
+        list++;
+    }
+
+    return num_options;
+}
+
+/*
+ * Append an option list (list) to an option list (dest).
+ *
+ * If dest is NULL, a new copy of list is created.
+ *
+ * Returns a pointer to the first element of dest (or the newly allocated copy)
+ */
+QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
+    QEMUOptionParameter *list)
+{
+    size_t num_options, num_dest_options;
+
+    num_options = count_option_parameters(dest);
+    num_dest_options = num_options;
+
+    num_options += count_option_parameters(list);
+
+    dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
+
+    while (list && list->name) {
+        if (get_option_parameter(dest, list->name) == NULL) {
+            dest[num_dest_options++] = *list;
+            dest[num_dest_options].name = NULL;
+        }
+        list++;
+    }
+
+    return dest;
+}
+
 /*
  * Parses a parameter string (param) into an option list (dest).
  *
@@ -365,7 +410,6 @@ void free_option_parameters(QEMUOptionParameter *list)
 QEMUOptionParameter *parse_option_parameters(const char *param,
     QEMUOptionParameter *list, QEMUOptionParameter *dest)
 {
-    QEMUOptionParameter *cur;
     QEMUOptionParameter *allocated = NULL;
     char name[256];
     char value[256];
@@ -379,12 +423,7 @@ QEMUOptionParameter *parse_option_parameters(const char *param,
 
     if (dest == NULL) {
         // Count valid options
-        num_options = 0;
-        cur = list;
-        while (cur->name) {
-            num_options++;
-            cur++;
-        }
+        num_options = count_option_parameters(list);
 
         // Create a copy of the option list to fill in values
         dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
index 58136f3032715e541e86a23f391124375a57fc02..4823219a183450c25b9337e809a03bf0e1360cf0 100644 (file)
@@ -70,6 +70,8 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
     const char *value);
 int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
     uint64_t value);
+QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
+    QEMUOptionParameter *list);
 QEMUOptionParameter *parse_option_parameters(const char *param,
     QEMUOptionParameter *list, QEMUOptionParameter *dest);
 void free_option_parameters(QEMUOptionParameter *list);