* [Qemu-devel] [RFC][PATCH 0/3] Make qemu-img create options generic
@ 2009-05-14 14:12 Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 1/3] Create qemu-option.h Kevin Wolf
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Kevin Wolf @ 2009-05-14 14:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf
Currently, qemu-img and the bdrv_create() interface need to carry parameters
for every single option that is used by at least one file format. We already
have a few of such format specific options (encryption for qcow2, version 6
header for VMDK, backing file for some formats) and there are more to come
(like qcow cluster size).
This patch series changes this into a more generic approach: All block drivers
contain a data structure which describes all options this driver recognizes.
qemu-img can use this structure then instead of hard-coding every single
option. An -o option is introduced for these parameteres, the format is the
usual comma separated name=value style as in -drive.
This series is not yet meant to be applied. qemu-img convert still needs to be
converted to the new interface and it's not exactly tested extensively (let
alone the state after patch 1 or 2 applied without the rest). Maybe it also
could use some better identifiers, I'm open for suggestions.
Kevin Wolf (3):
Create qemu-option.h
Convert all block drivers
Convert qemu-img create
Makefile | 2 +-
block-cow.c | 24 ++++-
block-qcow.c | 28 +++++-
block-qcow2.c | 36 ++++++-
block-raw-posix.c | 37 +++++--
block-raw-win32.c | 20 +++-
block-vmdk.c | 28 +++++-
block-vpc.c | 21 +++-
block-vvfat.c | 4 +-
block.c | 44 ++++++--
block.h | 6 +-
block_int.h | 17 ++-
qemu-img.c | 133 +++++++++++++++++---------
qemu-option.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-option.h | 61 ++++++++++++
sysemu.h | 2 -
vl.c | 38 +-------
17 files changed, 642 insertions(+), 139 deletions(-)
create mode 100644 qemu-option.c
create mode 100644 qemu-option.h
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] [RFC][PATCH 1/3] Create qemu-option.h
2009-05-14 14:12 [Qemu-devel] [RFC][PATCH 0/3] Make qemu-img create options generic Kevin Wolf
@ 2009-05-14 14:12 ` Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 2/3] Convert all block drivers Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 3/3] Convert qemu-img create Kevin Wolf
2 siblings, 0 replies; 4+ messages in thread
From: Kevin Wolf @ 2009-05-14 14:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf
This patch creates a new header file and the corresponding implementation file
for parsing of parameter strings for options (like used in -drive). Part of
this is code moved from vl.c (so qemu-img can use it later).
The idea is to have a data structure describing all accepted parameters. When
parsing a parameter string, the structure is copied and filled with the
parameter values.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
Makefile | 2 +-
qemu-option.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-option.h | 61 +++++++++++++
sysemu.h | 2 -
vl.c | 38 +--------
5 files changed, 343 insertions(+), 40 deletions(-)
create mode 100644 qemu-option.c
create mode 100644 qemu-option.h
diff --git a/Makefile b/Makefile
index 8649938..7277de7 100644
--- a/Makefile
+++ b/Makefile
@@ -63,7 +63,7 @@ recurse-all: $(SUBDIR_RULES)
#######################################################################
# BLOCK_OBJS is code used by both qemu system emulation and qemu-img
-BLOCK_OBJS=cutils.o cache-utils.o qemu-malloc.o
+BLOCK_OBJS=cutils.o cache-utils.o qemu-malloc.o qemu-option.o
BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
BLOCK_OBJS+=block-qcow2.o block-parallels.o block-nbd.o
diff --git a/qemu-option.c b/qemu-option.c
new file mode 100644
index 0000000..bfc7545
--- /dev/null
+++ b/qemu-option.c
@@ -0,0 +1,280 @@
+/*
+ * Commandline option parsing functions
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "qemu-common.h"
+#include "qemu-option.h"
+
+const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
+{
+ char *q;
+
+ q = buf;
+ while (*p != '\0' && *p != delim) {
+ if (q && (q - buf) < buf_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ if (q)
+ *q = '\0';
+
+ return p;
+}
+
+const char *get_opt_value(char *buf, int buf_size, const char *p)
+{
+ char *q;
+
+ q = buf;
+ while (*p != '\0') {
+ if (*p == ',') {
+ if (*(p + 1) != ',')
+ break;
+ p++;
+ }
+ if (q && (q - buf) < buf_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ if (q)
+ *q = '\0';
+
+ return p;
+}
+
+QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
+ const char *name)
+{
+ while (list && list->name) {
+ if (!strcmp(list->name, name)) {
+ return list;
+ }
+ list++;
+ }
+
+ return NULL;
+}
+
+int set_option_parameter(QEMUOptionParameter *list, const char *name,
+ const char *value)
+{
+ // Find a matching parameter
+ list = get_option_parameter(list, name);
+ if (list == NULL) {
+ fprintf(stderr, "Unknown option '%s'\n", name);
+ return -1;
+ }
+
+ // Process parameter
+ switch (list->type) {
+ case OPT_FLAG:
+ if (value != NULL) {
+ if (!strcmp(value, "on")) {
+ list->value.n = 1;
+ } else if (!strcmp(value, "off")) {
+ list->value.n = 0;
+ } else {
+ fprintf(stderr, "Option '%s': Use 'on' or 'off'\n", name);
+ return -1;
+ }
+ } else {
+ list->value.n = 1;
+ }
+ break;
+
+ case OPT_STRING:
+ if (value != NULL) {
+ list->value.s = strdup(value);
+ } else {
+ fprintf(stderr, "Option '%s' needs a parameter\n", name);
+ return -1;
+ }
+ break;
+
+ case OPT_SIZE:
+ if (value != NULL) {
+ double sizef = strtod(value, (char**) &value);
+
+ switch (*value) {
+ case 'T':
+ sizef *= 1024;
+ case 'G':
+ sizef *= 1024;
+ case 'M':
+ sizef *= 1024;
+ case 'K':
+ case 'k':
+ sizef *= 1024;
+ case 'b':
+ case '\0':
+ list->value.n = (uint64_t) sizef;
+ break;
+ default:
+ fprintf(stderr, "Option '%s' needs size as parameter\n", name);
+ fprintf(stderr, "You may use k, M, G or T suffixes for "
+ "kilobytes, megabytes, gigabytes and terabytes.\n");
+ return -1;
+ }
+ } else {
+ fprintf(stderr, "Option '%s' needs a parameter\n", name);
+ return -1;
+ }
+ break;
+ default:
+ fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
+ uint64_t value)
+{
+ // Find a matching parameter
+ list = get_option_parameter(list, name);
+ if (list == NULL) {
+ fprintf(stderr, "Unknown option '%s'\n", name);
+ return -1;
+ }
+
+ // Process parameter
+ switch (list->type) {
+ case OPT_FLAG:
+ case OPT_NUMBER:
+ case OPT_SIZE:
+ list->value.n = value;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+void free_option_parameters(QEMUOptionParameter *list)
+{
+ QEMUOptionParameter *cur = list;
+
+ while (cur && cur->name) {
+ if (cur->type == OPT_STRING) {
+ free(cur->value.s);
+ }
+ cur++;
+ }
+
+ free(list);
+}
+
+QEMUOptionParameter *parse_option_parameters(const char *param,
+ QEMUOptionParameter *list, QEMUOptionParameter *dest)
+{
+ QEMUOptionParameter *cur;
+ QEMUOptionParameter *allocated = NULL;
+ char name[256];
+ char value[256];
+ char *param_delim, *value_delim;
+ char next_delim;
+ size_t num_options;
+
+ if (list == NULL) {
+ return NULL;
+ }
+
+ if (dest == NULL) {
+ // Count valid options
+ num_options = 0;
+ cur = list;
+ while (cur->name) {
+ num_options++;
+ cur++;
+ }
+
+ // Create a copy of the option list to fill in values
+ dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
+ allocated = dest;
+ memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
+ }
+
+ while (*param) {
+
+ // Find parameter name and value in the string
+ param_delim = strchr(param, ',');
+ value_delim = strchr(param, '=');
+
+ if (value_delim && (value_delim < param_delim || !param_delim)) {
+ next_delim = '=';
+ } else {
+ next_delim = ',';
+ value_delim = NULL;
+ }
+
+ param = get_opt_name(name, sizeof(name), param, next_delim);
+ if (value_delim) {
+ param = get_opt_value(value, sizeof(value), param + 1);
+ }
+ if (*param != '\0') {
+ param++;
+ }
+
+ // Set the parameter
+ if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
+ goto fail;
+ }
+ }
+
+ return dest;
+
+fail:
+ free_option_parameters(allocated);
+ return NULL;
+}
+
+void print_option_parameters(QEMUOptionParameter *list)
+{
+ while (list && list->name) {
+ switch (list->type) {
+ case OPT_STRING:
+ if (list->value.s != NULL) {
+ printf("%s='%s' ", list->name, list->value.s);
+ }
+ break;
+ case OPT_FLAG:
+ printf("%s=%s ", list->name, list->value.n ? "on" : "off");
+ break;
+ case OPT_SIZE:
+ case OPT_NUMBER:
+ printf("%s=%" PRId64 " ", list->name, list->value.n);
+ break;
+ default:
+ printf("%s=(unkown type) ", list->name);
+ break;
+ }
+ list++;
+ }
+}
diff --git a/qemu-option.h b/qemu-option.h
new file mode 100644
index 0000000..15d8cb8
--- /dev/null
+++ b/qemu-option.h
@@ -0,0 +1,61 @@
+/*
+ * Commandline option parsing functions
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_OPTIONS_H
+#define QEMU_OPTIONS_H
+
+enum QEMUOptionParType {
+ OPT_FLAG,
+ OPT_NUMBER,
+ OPT_SIZE,
+ OPT_STRING,
+};
+
+typedef struct QEMUOptionParameter {
+ const char *name;
+ enum QEMUOptionParType type;
+ union {
+ uint64_t n;
+ char* s;
+ } value;
+} QEMUOptionParameter;
+
+
+const char *get_opt_name(char *buf, int buf_size, const char *p, char delim);
+const char *get_opt_value(char *buf, int buf_size, const char *p);
+
+
+QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
+ const char *name);
+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 *parse_option_parameters(const char *param,
+ QEMUOptionParameter *list, QEMUOptionParameter *dest);
+void free_option_parameters(QEMUOptionParameter *list);
+void print_option_parameters(QEMUOptionParameter *list);
+
+#endif
diff --git a/sysemu.h b/sysemu.h
index 25a7c32..b054015 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -253,8 +253,6 @@ void do_usb_add(Monitor *mon, const char *devname);
void do_usb_del(Monitor *mon, const char *devname);
void usb_info(Monitor *mon);
-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim);
-const char *get_opt_value(char *buf, int buf_size, const char *p);
int get_param_value(char *buf, int buf_size,
const char *tag, const char *str);
int check_params(const char * const *params, const char *str);
diff --git a/vl.c b/vl.c
index 8e4fba6..1a042a8 100644
--- a/vl.c
+++ b/vl.c
@@ -156,6 +156,7 @@ int main(int argc, char **argv)
#include "migration.h"
#include "kvm.h"
#include "balloon.h"
+#include "qemu-option.h"
#include "disas.h"
@@ -1807,43 +1808,6 @@ static int socket_init(void)
}
#endif
-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
-{
- char *q;
-
- q = buf;
- while (*p != '\0' && *p != delim) {
- if (q && (q - buf) < buf_size - 1)
- *q++ = *p;
- p++;
- }
- if (q)
- *q = '\0';
-
- return p;
-}
-
-const char *get_opt_value(char *buf, int buf_size, const char *p)
-{
- char *q;
-
- q = buf;
- while (*p != '\0') {
- if (*p == ',') {
- if (*(p + 1) != ',')
- break;
- p++;
- }
- if (q && (q - buf) < buf_size - 1)
- *q++ = *p;
- p++;
- }
- if (q)
- *q = '\0';
-
- return p;
-}
-
int get_param_value(char *buf, int buf_size,
const char *tag, const char *str)
{
--
1.6.0.6
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [RFC][PATCH 2/3] Convert all block drivers
2009-05-14 14:12 [Qemu-devel] [RFC][PATCH 0/3] Make qemu-img create options generic Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 1/3] Create qemu-option.h Kevin Wolf
@ 2009-05-14 14:12 ` Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 3/3] Convert qemu-img create Kevin Wolf
2 siblings, 0 replies; 4+ messages in thread
From: Kevin Wolf @ 2009-05-14 14:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf
Now we can make use of the newly introduced option structures. Instead of
having bdrv_create carry more and more parameters (which are format specific in
most cases), just pass a option structure as defined by the driver itself.
bdrv_create2() contains an emulation of the old interface to simplify the
transition.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block-cow.c | 24 ++++++++++++++++++++----
block-qcow.c | 28 ++++++++++++++++++++++++++--
block-qcow2.c | 36 +++++++++++++++++++++++++++++++-----
block-raw-posix.c | 37 +++++++++++++++++++++++++++----------
block-raw-win32.c | 20 ++++++++++++++++----
block-vmdk.c | 28 ++++++++++++++++++++++++++--
block-vpc.c | 21 +++++++++++++++++----
block-vvfat.c | 4 ++--
block.c | 44 +++++++++++++++++++++++++++++++++-----------
block.h | 6 +++---
block_int.h | 17 +++++++++++------
qemu-img.c | 2 +-
12 files changed, 213 insertions(+), 54 deletions(-)
diff --git a/block-cow.c b/block-cow.c
index 17e3292..2bfd17b 100644
--- a/block-cow.c
+++ b/block-cow.c
@@ -201,15 +201,23 @@ static void cow_close(BlockDriverState *bs)
close(s->fd);
}
-static int cow_create(const char *filename, int64_t image_sectors,
- const char *image_filename, int flags)
+static int cow_create(const char *filename, QEMUOptionParameter *options)
{
int fd, cow_fd;
struct cow_header_v2 cow_header;
struct stat st;
+ int64_t image_sectors = 0;
+ const char *image_filename = NULL;
- if (flags)
- return -ENOTSUP;
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ image_sectors = options->value.n / 512;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+ image_filename = options->value.s;
+ }
+ options++;
+ }
cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
@@ -252,6 +260,12 @@ static void cow_flush(BlockDriverState *bs)
fsync(s->fd);
}
+static QEMUOptionParameter cow_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { BLOCK_OPT_BACKING_FILE, OPT_STRING },
+ { NULL }
+};
+
BlockDriver bdrv_cow = {
.format_name = "cow",
.instance_size = sizeof(BDRVCowState),
@@ -263,5 +277,7 @@ BlockDriver bdrv_cow = {
.bdrv_create = cow_create,
.bdrv_flush = cow_flush,
.bdrv_is_allocated = cow_is_allocated,
+
+ .create_options = cow_create_options,
};
#endif
diff --git a/block-qcow.c b/block-qcow.c
index fc6b809..5bfb2ee 100644
--- a/block-qcow.c
+++ b/block-qcow.c
@@ -766,12 +766,26 @@ static void qcow_close(BlockDriverState *bs)
bdrv_delete(s->hd);
}
-static int qcow_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int qcow_create(const char *filename, QEMUOptionParameter *options)
{
int fd, header_size, backing_filename_len, l1_size, i, shift;
QCowHeader header;
uint64_t tmp;
+ int64_t total_size = 0;
+ const char *backing_file = NULL;
+ int flags = 0;
+
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ total_size = options->value.n / 512;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+ backing_file = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
+ flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
+ }
+ options++;
+ }
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
if (fd < 0)
@@ -917,6 +931,14 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return 0;
}
+
+static QEMUOptionParameter qcow_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { BLOCK_OPT_BACKING_FILE, OPT_STRING },
+ { BLOCK_OPT_ENCRYPT, OPT_FLAG },
+ { NULL }
+};
+
BlockDriver bdrv_qcow = {
.format_name = "qcow",
.instance_size = sizeof(BDRVQcowState),
@@ -934,4 +956,6 @@ BlockDriver bdrv_qcow = {
.aiocb_size = sizeof(QCowAIOCB),
.bdrv_write_compressed = qcow_write_compressed,
.bdrv_get_info = qcow_get_info,
+
+ .create_options = qcow_create_options,
};
diff --git a/block-qcow2.c b/block-qcow2.c
index 9a49777..2c87701 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -1696,10 +1696,28 @@ static int qcow_create2(const char *filename, int64_t total_size,
return 0;
}
-static int qcow_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
-{
- return qcow_create2(filename, total_size, backing_file, NULL, flags);
+static int qcow_create(const char *filename, QEMUOptionParameter *options)
+{
+ const char *backing_file = NULL;
+ const char *backing_fmt = NULL;
+ uint64_t sectors = 0;
+ int flags = 0;
+
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ sectors = options->value.n / 512;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+ backing_file = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) {
+ backing_fmt = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
+ flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
+ }
+ options++;
+ }
+
+ return qcow_create2(filename, sectors, backing_file, backing_fmt, flags);
}
static int qcow_make_empty(BlockDriverState *bs)
@@ -2892,6 +2910,14 @@ static int qcow_get_buffer(BlockDriverState *bs, uint8_t *buf,
return ret;
}
+static QEMUOptionParameter qcow_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { BLOCK_OPT_BACKING_FILE, OPT_STRING },
+ { BLOCK_OPT_BACKING_FMT, OPT_STRING },
+ { BLOCK_OPT_ENCRYPT, OPT_FLAG },
+ { NULL }
+};
+
BlockDriver bdrv_qcow2 = {
.format_name = "qcow2",
.instance_size = sizeof(BDRVQcowState),
@@ -2919,6 +2945,6 @@ BlockDriver bdrv_qcow2 = {
.bdrv_put_buffer = qcow_put_buffer,
.bdrv_get_buffer = qcow_get_buffer,
- .bdrv_create2 = qcow_create2,
+ .create_options = qcow_create_options,
.bdrv_check = qcow_check,
};
diff --git a/block-raw-posix.c b/block-raw-posix.c
index 0663c06..a32ce37 100644
--- a/block-raw-posix.c
+++ b/block-raw-posix.c
@@ -823,13 +823,18 @@ again:
}
#endif
-static int raw_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int raw_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
+ int64_t total_size = 0;
- if (flags || backing_file)
- return -ENOTSUP;
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ total_size = options->value.n / 512;
+ }
+ options++;
+ }
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
@@ -846,6 +851,12 @@ static void raw_flush(BlockDriverState *bs)
fsync(s->fd);
}
+
+static QEMUOptionParameter raw_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { NULL }
+};
+
BlockDriver bdrv_raw = {
.format_name = "raw",
.instance_size = sizeof(BDRVRawState),
@@ -866,6 +877,8 @@ BlockDriver bdrv_raw = {
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
+
+ .create_options = raw_create_options,
};
/***********************************************/
@@ -1364,15 +1377,20 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
#endif /* !linux && !FreeBSD */
#if defined(__linux__) || defined(__FreeBSD__)
-static int hdev_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int hdev_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
int ret = 0;
struct stat stat_buf;
+ int64_t total_size = 0;
- if (flags || backing_file)
- return -ENOTSUP;
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, "size")) {
+ total_size = options->value.n / 512;
+ }
+ options++;
+ }
fd = open(filename, O_WRONLY | O_BINARY);
if (fd < 0)
@@ -1391,8 +1409,7 @@ static int hdev_create(const char *filename, int64_t total_size,
#else /* !(linux || freebsd) */
-static int hdev_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int hdev_create(const char *filename, QEMUOptionParameter *options)
{
return -ENOTSUP;
}
diff --git a/block-raw-win32.c b/block-raw-win32.c
index b5287d2..a05c687 100644
--- a/block-raw-win32.c
+++ b/block-raw-win32.c
@@ -210,13 +210,18 @@ static int64_t raw_getlength(BlockDriverState *bs)
return l.QuadPart;
}
-static int raw_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int raw_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
+ int64_t total_size = 0;
- if (flags || backing_file)
- return -ENOTSUP;
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ total_size = options->value.n / 512;
+ }
+ options++;
+ }
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
@@ -228,6 +233,11 @@ static int raw_create(const char *filename, int64_t total_size,
return 0;
}
+static QEMUOptionParameter raw_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { NULL }
+};
+
BlockDriver bdrv_raw = {
.format_name = "raw",
.instance_size = sizeof(BDRVRawState),
@@ -239,6 +249,8 @@ BlockDriver bdrv_raw = {
.bdrv_write = raw_write,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
+
+ .create_options = raw_create_options,
};
/***********************************************/
diff --git a/block-vmdk.c b/block-vmdk.c
index d47d483..bba6b9c 100644
--- a/block-vmdk.c
+++ b/block-vmdk.c
@@ -686,8 +686,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
return 0;
}
-static int vmdk_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int vmdk_create(const char *filename, QEMUOptionParameter *options)
{
int fd, i;
VMDK4Header header;
@@ -712,6 +711,21 @@ static int vmdk_create(const char *filename, int64_t total_size,
"ddb.adapterType = \"ide\"\n";
char desc[1024];
const char *real_filename, *temp_str;
+ int64_t total_size = 0;
+ const char *backing_file = NULL;
+ int flags = 0;
+
+ // Read out options
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ total_size = options->value.n / 512;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+ backing_file = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
+ flags |= options->value.n ? BLOCK_FLAG_COMPAT6: 0;
+ }
+ options++;
+ }
/* XXX: add support for backing file */
if (backing_file) {
@@ -811,6 +825,14 @@ static void vmdk_flush(BlockDriverState *bs)
bdrv_flush(s->hd);
}
+
+static QEMUOptionParameter vmdk_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { BLOCK_OPT_BACKING_FILE, OPT_STRING },
+ { BLOCK_OPT_COMPAT6, OPT_FLAG },
+ { NULL }
+};
+
BlockDriver bdrv_vmdk = {
.format_name = "vmdk",
.instance_size = sizeof(BDRVVmdkState),
@@ -822,4 +844,6 @@ BlockDriver bdrv_vmdk = {
.bdrv_create = vmdk_create,
.bdrv_flush = vmdk_flush,
.bdrv_is_allocated = vmdk_is_allocated,
+
+ .create_options = vmdk_create_options,
};
diff --git a/block-vpc.c b/block-vpc.c
index 71a171d..45b99f8 100644
--- a/block-vpc.c
+++ b/block-vpc.c
@@ -476,8 +476,7 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
return 0;
}
-static int vpc_create(const char *filename, int64_t total_sectors,
- const char *backing_file, int flags)
+static int vpc_create(const char *filename, QEMUOptionParameter *options)
{
uint8_t buf[1024];
struct vhd_footer* footer = (struct vhd_footer*) buf;
@@ -488,10 +487,17 @@ static int vpc_create(const char *filename, int64_t total_sectors,
uint8_t heads;
uint8_t secs_per_cyl;
size_t block_size, num_bat_entries;
+ int64_t total_sectors = 0;
- if (backing_file != NULL)
- return -ENOTSUP;
+ // Read out options
+ while (options && options->name) {
+ if (!strcmp(options->name, "size")) {
+ total_sectors = options->value.n / 512;
+ }
+ options++;
+ }
+ // Create the file
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
if (fd < 0)
return -EIO;
@@ -586,6 +592,11 @@ static void vpc_close(BlockDriverState *bs)
bdrv_delete(s->hd);
}
+static QEMUOptionParameter vpc_create_options[] = {
+ { "size", OPT_SIZE },
+ { NULL }
+};
+
BlockDriver bdrv_vpc = {
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
@@ -595,4 +606,6 @@ BlockDriver bdrv_vpc = {
.bdrv_write = vpc_write,
.bdrv_close = vpc_close,
.bdrv_create = vpc_create,
+
+ .create_options = vpc_create_options,
};
diff --git a/block-vvfat.c b/block-vvfat.c
index 7905931..5323e9a 100644
--- a/block-vvfat.c
+++ b/block-vvfat.c
@@ -2777,8 +2777,8 @@ static int enable_write_target(BDRVVVFATState *s)
s->qcow_filename = qemu_malloc(1024);
get_tmp_filename(s->qcow_filename, 1024);
- if (bdrv_create(&bdrv_qcow,
- s->qcow_filename, s->sector_count, "fat:", 0) < 0)
+ if (bdrv_create2(&bdrv_qcow,
+ s->qcow_filename, s->sector_count, "fat:", NULL, 0) < 0)
return -1;
s->qcow = bdrv_new("");
if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
diff --git a/block.c b/block.c
index acb8976..fe9c3ef 100644
--- a/block.c
+++ b/block.c
@@ -188,22 +188,44 @@ int bdrv_create2(BlockDriver *drv,
const char *backing_file, const char *backing_format,
int flags)
{
- if (drv->bdrv_create2)
- return drv->bdrv_create2(filename, size_in_sectors, backing_file,
- backing_format, flags);
- if (drv->bdrv_create)
- return drv->bdrv_create(filename, size_in_sectors, backing_file,
- flags);
- return -ENOTSUP;
+ QEMUOptionParameter *options;
+
+ options = parse_option_parameters("", drv->create_options, NULL);
+
+ // Process flags
+ if (flags & ~(BLOCK_FLAG_ENCRYPT | BLOCK_FLAG_COMPAT6)) {
+ return -ENOTSUP;
+ }
+
+ if (flags & BLOCK_FLAG_ENCRYPT) {
+ set_option_parameter_int(options, BLOCK_OPT_ENCRYPT, 1);
+ }
+ if (flags & BLOCK_FLAG_COMPAT6) {
+ set_option_parameter_int(options, BLOCK_OPT_COMPAT6, 1);
+ }
+
+ // Add size to options
+ set_option_parameter_int(options, BLOCK_OPT_SIZE, size_in_sectors * 512);
+
+ // Backing files
+ if ((backing_file != NULL && set_option_parameter(options,
+ BLOCK_OPT_BACKING_FILE, backing_file))
+ || (backing_format != NULL && set_option_parameter(options,
+ BLOCK_OPT_BACKING_FMT, backing_format)))
+ {
+ return -ENOTSUP;
+ }
+
+ return bdrv_create(drv, filename, options);
}
-int bdrv_create(BlockDriver *drv,
- const char *filename, int64_t size_in_sectors,
- const char *backing_file, int flags)
+int bdrv_create(BlockDriver *drv, const char* filename,
+ QEMUOptionParameter *options)
{
if (!drv->bdrv_create)
return -ENOTSUP;
- return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
+
+ return drv->bdrv_create(filename, options);
}
#ifdef _WIN32
diff --git a/block.h b/block.h
index 5aef076..dcb2941 100644
--- a/block.h
+++ b/block.h
@@ -3,6 +3,7 @@
#include "qemu-aio.h"
#include "qemu-common.h"
+#include "qemu-option.h"
/* block.c */
typedef struct BlockDriver BlockDriver;
@@ -59,9 +60,8 @@ void bdrv_info_stats(Monitor *mon);
void bdrv_init(void);
BlockDriver *bdrv_find_format(const char *format_name);
-int bdrv_create(BlockDriver *drv,
- const char *filename, int64_t size_in_sectors,
- const char *backing_file, int flags);
+int bdrv_create(BlockDriver *drv, const char* filename,
+ QEMUOptionParameter *options);
int bdrv_create2(BlockDriver *drv,
const char *filename, int64_t size_in_sectors,
const char *backing_file, const char *backing_format,
diff --git a/block_int.h b/block_int.h
index 9d11940..694daa9 100644
--- a/block_int.h
+++ b/block_int.h
@@ -25,11 +25,18 @@
#define BLOCK_INT_H
#include "block.h"
+#include "qemu-option.h"
#define BLOCK_FLAG_ENCRYPT 1
#define BLOCK_FLAG_COMPRESS 2
#define BLOCK_FLAG_COMPAT6 4
+#define BLOCK_OPT_SIZE "size"
+#define BLOCK_OPT_ENCRYPT "encrpytion"
+#define BLOCK_OPT_COMPAT6 "compat6"
+#define BLOCK_OPT_BACKING_FILE "backing_file"
+#define BLOCK_OPT_BACKING_FMT "backing_fmt"
+
typedef struct AIOPool {
void (*cancel)(BlockDriverAIOCB *acb);
int aiocb_size;
@@ -46,8 +53,7 @@ struct BlockDriver {
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
void (*bdrv_close)(BlockDriverState *bs);
- int (*bdrv_create)(const char *filename, int64_t total_sectors,
- const char *backing_file, int flags);
+ int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
void (*bdrv_flush)(BlockDriverState *bs);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
@@ -97,10 +103,9 @@ struct BlockDriver {
AIOPool aio_pool;
- /* new create with backing file format */
- int (*bdrv_create2)(const char *filename, int64_t total_sectors,
- const char *backing_file, const char *backing_format,
- int flags);
+ /* List of options for creating images, terminated by name == NULL */
+ QEMUOptionParameter *create_options;
+
/* Returns number of errors in image, -errno for internal errors */
int (*bdrv_check)(BlockDriverState* bs);
diff --git a/qemu-img.c b/qemu-img.c
index 29149a2..15f9cfd 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -552,7 +552,7 @@ static int img_convert(int argc, char **argv)
if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
error("Compression and encryption not supported at the same time");
- ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
+ ret = bdrv_create2(drv, out_filename, total_sectors, out_baseimg, NULL, flags);
if (ret < 0) {
if (ret == -ENOTSUP) {
error("Formatting not supported for file format '%s'", out_fmt);
--
1.6.0.6
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [RFC][PATCH 3/3] Convert qemu-img create
2009-05-14 14:12 [Qemu-devel] [RFC][PATCH 0/3] Make qemu-img create options generic Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 1/3] Create qemu-option.h Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 2/3] Convert all block drivers Kevin Wolf
@ 2009-05-14 14:12 ` Kevin Wolf
2 siblings, 0 replies; 4+ messages in thread
From: Kevin Wolf @ 2009-05-14 14:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf
This patch changes qemu-img to actually use the new bdrv_create interface. It
translates the old-style qemu-img options which have been bdrv_create2
parameters or flags so far to option structures. As the generic approach, it
introduces an -o option which accepts any parameter the driver knows.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
qemu-img.c | 131 +++++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 86 insertions(+), 45 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 15f9cfd..4d8aa43 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "qemu-common.h"
+#include "qemu-option.h"
#include "osdep.h"
#include "block_int.h"
#include <assert.h>
@@ -185,6 +186,7 @@ static int read_password(char *buf, int buf_size)
}
#endif
+
static BlockDriverState *bdrv_new_open(const char *filename,
const char *fmt)
{
@@ -222,14 +224,13 @@ static int img_create(int argc, char **argv)
const char *base_fmt = NULL;
const char *filename;
const char *base_filename = NULL;
- uint64_t size;
- double sizef;
- const char *p;
BlockDriver *drv;
+ QEMUOptionParameter *param = NULL;
+ char *options = NULL;
flags = 0;
for(;;) {
- c = getopt(argc, argv, "F:b:f:he6");
+ c = getopt(argc, argv, "F:b:f:he6o:");
if (c == -1)
break;
switch(c) {
@@ -251,59 +252,99 @@ static int img_create(int argc, char **argv)
case '6':
flags |= BLOCK_FLAG_COMPAT6;
break;
+ case 'o':
+ options = optarg;
+ break;
}
}
if (optind >= argc)
help();
filename = argv[optind++];
- size = 0;
- if (base_filename) {
- BlockDriverState *bs;
- BlockDriver *base_drv = NULL;
- if (base_fmt) {
- base_drv = bdrv_find_format(base_fmt);
- if (base_drv == NULL)
- error("Unknown basefile format '%s'", base_fmt);
- }
+ /* Find driver and parse its options */
+ drv = bdrv_find_format(fmt);
+ if (!drv)
+ error("Unknown file format '%s'", fmt);
- bs = bdrv_new_open(base_filename, base_fmt);
- bdrv_get_geometry(bs, &size);
- size *= 512;
- bdrv_delete(bs);
+ if (options) {
+ param = parse_option_parameters(options, drv->create_options, param);
+ if (param == NULL) {
+ error("Invalid options for file format '%s'.", fmt);
+ }
} else {
- if (optind >= argc)
- help();
- p = argv[optind];
- sizef = strtod(p, (char **)&p);
- if (*p == 'M') {
- size = (uint64_t)(sizef * 1024 * 1024);
- } else if (*p == 'G') {
- size = (uint64_t)(sizef * 1024 * 1024 * 1024);
- } else if (*p == 'k' || *p == 'K' || *p == '\0') {
- size = (uint64_t)(sizef * 1024);
- } else {
- help();
+ param = parse_option_parameters("", drv->create_options, param);
+ }
+
+ /* Add size to parameters */
+ if (optind < argc) {
+ set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
+ }
+
+ /* Add old-style options to parameters */
+ if (flags & BLOCK_FLAG_ENCRYPT) {
+ if (set_option_parameter(param, BLOCK_OPT_ENCRYPT, "on")) {
+ error("Encryption not supported for file format '%s'", fmt);
}
}
- drv = bdrv_find_format(fmt);
- if (!drv)
- error("Unknown file format '%s'", fmt);
- printf("Formatting '%s', fmt=%s",
- filename, fmt);
- if (flags & BLOCK_FLAG_ENCRYPT)
- printf(", encrypted");
- if (flags & BLOCK_FLAG_COMPAT6)
- printf(", compatibility level=6");
+ if (flags & BLOCK_FLAG_COMPAT6) {
+ if (set_option_parameter(param, BLOCK_OPT_COMPAT6, "on")) {
+ error("VMDK version 6 not supported for file format '%s'", fmt);
+ }
+ }
+
if (base_filename) {
- printf(", backing_file=%s",
- base_filename);
- if (base_fmt)
- printf(", backing_fmt=%s",
- base_fmt);
- }
- printf(", size=%" PRIu64 " kB\n", size / 1024);
- ret = bdrv_create2(drv, filename, size / 512, base_filename, base_fmt, flags);
+ if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE, base_filename)) {
+ error("Backing file not supported for file format '%s'", fmt);
+ }
+ }
+ if (base_fmt) {
+ if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+ error("Backing file format not supported for file format '%s'", fmt);
+ }
+ }
+
+ // The size for the image must always be specified, with one exception:
+ // If we are using a backing file, we can obtain the size from there
+ if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == 0) {
+
+ QEMUOptionParameter *backing_file =
+ get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
+ QEMUOptionParameter *backing_fmt =
+ get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
+
+ if (backing_file && backing_file->value.s) {
+ BlockDriverState *bs;
+ uint64_t size;
+ const char *fmt = NULL;
+ char buf[32];
+
+ if (backing_fmt && backing_fmt->value.s) {
+ if (bdrv_find_format(backing_fmt->value.s)) {
+ fmt = backing_fmt->value.s;
+ } else {
+ error("Unknown basefile format '%s'", base_fmt);
+ }
+ }
+
+ bs = bdrv_new_open(base_filename, base_fmt);
+ bdrv_get_geometry(bs, &size);
+ size *= 512;
+ bdrv_delete(bs);
+
+ snprintf(buf, sizeof(buf), "%" PRId64, size);
+ set_option_parameter(param, BLOCK_OPT_SIZE, buf);
+ } else {
+ error("Image creation needs a size parameter");
+ }
+ }
+
+ printf("Formatting '%s', fmt=%s ", filename, fmt);
+ print_option_parameters(param);
+ puts("");
+
+ ret = bdrv_create(drv, filename, param);
+ free_option_parameters(param);
+
if (ret < 0) {
if (ret == -ENOTSUP) {
error("Formatting or formatting option not supported for file format '%s'", fmt);
--
1.6.0.6
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-05-14 14:13 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-14 14:12 [Qemu-devel] [RFC][PATCH 0/3] Make qemu-img create options generic Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 1/3] Create qemu-option.h Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 2/3] Convert all block drivers Kevin Wolf
2009-05-14 14:12 ` [Qemu-devel] [RFC][PATCH 3/3] Convert qemu-img create Kevin Wolf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).