[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 05/26] FVD: add the 'qemu-img update' command
From: |
Chunqiang Tang |
Subject: |
[Qemu-devel] [PATCH 05/26] FVD: add the 'qemu-img update' command |
Date: |
Fri, 25 Feb 2011 17:37:45 -0500 |
This patch is part of the Fast Virtual Disk (FVD) proposal.
See http://wiki.qemu.org/Features/FVD.
This patch adds the 'update' command to qemu-img. It is a general interface
that allows various image format specific manipulations. For example,
'qemu-img rebase' and 'qemu-img resize' can be considered as two special cases
of update.
Signed-off-by: Chunqiang Tang <address@hidden>
---
block_int.h | 3 +
qemu-img-cmds.hx | 6 +++
qemu-img.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++-------
qemu-option.c | 79 ++++++++++++++++++++++++++++++++++
qemu-option.h | 4 ++
5 files changed, 201 insertions(+), 16 deletions(-)
diff --git a/block_int.h b/block_int.h
index 545ad11..8f6b6d0 100644
--- a/block_int.h
+++ b/block_int.h
@@ -98,6 +98,7 @@ struct BlockDriver {
int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,
const char *snapshot_name);
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
+ int (*bdrv_update)(BlockDriverState *bs, QEMUOptionParameter *options);
int (*bdrv_save_vmstate)(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size);
@@ -122,6 +123,8 @@ struct BlockDriver {
/* List of options for creating images, terminated by name == NULL */
QEMUOptionParameter *create_options;
+ /* List of options for updating images, terminated by name == NULL */
+ QEMUOptionParameter *update_options;
/*
* Returns 0 for completed check, -errno for internal errors.
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 6c7176f..a7ed395 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -39,6 +39,12 @@ STEXI
@item info [-f @var{fmt}] @var{filename}
ETEXI
+DEF("update", img_update,
+ "update [-f fmt] [-o options] filename")
+STEXI
address@hidden update [-f @var{fmt}] [-o @var{options}] @var{filename}
address@hidden
+ETEXI
+
DEF("snapshot", img_snapshot,
"snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename")
STEXI
diff --git a/qemu-img.c b/qemu-img.c
index 7e3cc4c..215e7b9 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -179,10 +179,11 @@ static int read_password(char *buf, int buf_size)
}
#endif
-static int print_block_option_help(const char *filename, const char *fmt)
+static int print_block_option_help(const char *filename, const char *fmt,
+ bool create_options)
{
BlockDriver *drv, *proto_drv;
- QEMUOptionParameter *create_options = NULL;
+ QEMUOptionParameter *options = NULL;
/* Find driver and parse its options */
drv = bdrv_find_format(fmt);
@@ -197,12 +198,15 @@ static int print_block_option_help(const char *filename,
const char *fmt)
return 1;
}
- create_options = append_option_parameters(create_options,
- drv->create_options);
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
- print_option_help(create_options);
- free_option_parameters(create_options);
+ if (create_options) {
+ options = append_option_parameters(options, drv->create_options);
+ options = append_option_parameters(options, proto_drv->create_options);
+ } else {
+ options = append_option_parameters(options, drv->update_options);
+ options = append_option_parameters(options, proto_drv->update_options);
+ }
+ print_option_help(options);
+ free_option_parameters(options);
return 0;
}
@@ -337,7 +341,7 @@ static int img_create(int argc, char **argv)
}
if (options && !strcmp(options, "?")) {
- ret = print_block_option_help(filename, fmt);
+ ret = print_block_option_help(filename, fmt, true /*create*/);
goto out;
}
@@ -631,7 +635,7 @@ static int img_convert(int argc, char **argv)
out_filename = argv[argc - 1];
if (options && !strcmp(options, "?")) {
- ret = print_block_option_help(out_filename, out_fmt);
+ ret = print_block_option_help(out_filename, out_fmt, true /*create*/);
goto out;
}
@@ -869,7 +873,7 @@ static int img_convert(int argc, char **argv)
assume that sectors which are unallocated in the input image
are present in both the output's and input's base images (no
need to copy them). */
- if (out_baseimg) {
+ if (out_baseimg || bs[bs_i]->backing_file[0]==0) {
if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
n, &n1)) {
sector_num += n1;
@@ -1040,11 +1044,6 @@ static int img_info(int argc, char **argv)
if (bdrv_is_encrypted(bs)) {
printf("encrypted: yes\n");
}
- if (bdrv_get_info(bs, &bdi) >= 0) {
- if (bdi.cluster_size != 0) {
- printf("cluster_size: %d\n", bdi.cluster_size);
- }
- }
bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
if (backing_filename[0] != '\0') {
path_combine(backing_filename2, sizeof(backing_filename2),
@@ -1053,11 +1052,105 @@ static int img_info(int argc, char **argv)
backing_filename,
backing_filename2);
}
+ if (bdrv_get_info(bs, &bdi) >= 0) {
+ if (bdi.cluster_size != 0)
+ printf("cluster_size: %d\n", bdi.cluster_size);
+ }
dump_snapshots(bs);
bdrv_delete(bs);
return 0;
}
+static int img_update(int argc, char **argv)
+{
+ int c, ret = 0;
+ const char *filename, *fmt = NULL;
+ BlockDriverState *bs;
+ char *options = NULL;
+ QEMUOptionParameter *param = NULL, *option_template = NULL;
+ BlockDriver *drv, *proto_drv;
+ char fmt_name[128];
+
+ for(;;) {
+ c = getopt(argc, argv, "f:o:h");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ case 'o':
+ options = optarg;
+ break;
+ }
+ }
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+ if (!options) {
+ error_report("No options were given\n");
+ return -EINVAL;
+ }
+
+ bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING
+ | BDRV_O_RDWR);
+ if (!bs) {
+ ret = -EIO;
+ goto out;
+ }
+
+ bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
+
+ if (!strcmp(options, "?")) {
+ return print_block_option_help(filename, fmt_name, false /*update*/);
+ }
+
+ if (!bs->drv->bdrv_update) {
+ error_report("the 'update' command is not supported for the '%s' "
+ "image format.", fmt_name);
+ goto out;
+ }
+
+ /* Find driver and parse its options */
+ drv = bdrv_find_format(fmt_name);
+ if (!drv) {
+ error_report("Unknown file format '%s'", fmt_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ proto_drv = bdrv_find_protocol(filename);
+ if (!proto_drv) {
+ error_report("Unknown protocol '%s'", filename);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ option_template = append_option_parameters(option_template,
+ drv->update_options);
+ option_template = append_option_parameters(option_template,
+ proto_drv->update_options);
+
+ if (!(param = parse_specified_parameters(options, option_template))) {
+ error_report("Invalid options for file format '%s'.", fmt_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = bs->drv->bdrv_update(bs, param);
+
+out:
+ free_option_parameters(option_template);
+ free_option_parameters(param);
+ if(bs) {
+ bdrv_delete(bs);
+ }
+ return ret;
+}
+
#define SNAPSHOT_LIST 1
#define SNAPSHOT_CREATE 2
#define SNAPSHOT_APPLY 3
diff --git a/qemu-option.c b/qemu-option.c
index 65db542..28b19b5 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -289,6 +289,10 @@ int set_option_parameter(QEMUOptionParameter *list, const
char *name,
return -1;
break;
+ case OPT_NUMBER:
+ list->value.n = atoi (value);
+ break;
+
default:
fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
return -1;
@@ -391,6 +395,22 @@ QEMUOptionParameter
*append_option_parameters(QEMUOptionParameter *dest,
return dest;
}
+QEMUOptionParameter *append_one_option_parameter(QEMUOptionParameter *dest,
+ QEMUOptionParameter *param)
+{
+ QEMUOptionParameter *target;
+ if ((target = get_option_parameter(dest, param->name))) {
+ *target = *param;
+ } else {
+ size_t n = count_option_parameters(dest);
+ dest = qemu_realloc(dest, (n + 2) * sizeof(QEMUOptionParameter));
+ dest[n] = *param;
+ dest[n + 1].name = NULL;
+ }
+
+ return dest;
+}
+
/*
* Parses a parameter string (param) into an option list (dest).
*
@@ -461,6 +481,65 @@ fail:
}
/*
+ * Parses a parameter string (param) into an option list (dest).
+ *
+ * list is the template option list. If list is NULL, this function fails.
+ * Only options explicitly specified in param are returned in dest.
+ */
+QEMUOptionParameter *parse_specified_parameters(const char *param,
+ QEMUOptionParameter *list)
+{
+ QEMUOptionParameter *dest = NULL;
+ char name[256];
+ char value[256];
+ char *param_delim, *value_delim;
+ char next_delim;
+ QEMUOptionParameter *opt;
+
+ if (list == NULL) {
+ return NULL;
+ }
+
+ 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 in the template. */
+ if (set_option_parameter(list, name, value_delim ? value : NULL)) {
+ goto fail;
+ }
+
+ /* Copy from template to dest. */
+ opt = get_option_parameter(list, name);
+ dest = append_one_option_parameter(dest, opt);
+ }
+
+ return dest;
+
+fail:
+ if (dest) {
+ free_option_parameters(dest);
+ }
+ return NULL;
+}
+
+/*
* Prints all options of a list that have a value to stdout
*/
void print_option_parameters(QEMUOptionParameter *list)
diff --git a/qemu-option.h b/qemu-option.h
index b515813..81ca734 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -72,8 +72,12 @@ int set_option_parameter_int(QEMUOptionParameter *list,
const char *name,
uint64_t value);
QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
QEMUOptionParameter *list);
+QEMUOptionParameter *append_one_option_parameter(QEMUOptionParameter *dest,
+ QEMUOptionParameter *param);
QEMUOptionParameter *parse_option_parameters(const char *param,
QEMUOptionParameter *list, QEMUOptionParameter *dest);
+QEMUOptionParameter *parse_specified_parameters(const char *param,
+ QEMUOptionParameter *list);
void free_option_parameters(QEMUOptionParameter *list);
void print_option_parameters(QEMUOptionParameter *list);
void print_option_help(QEMUOptionParameter *list);
--
1.7.0.4
- [Qemu-devel] [PATCH 19/26] FVD: add support for aio_cancel, (continued)
- [Qemu-devel] [PATCH 19/26] FVD: add support for aio_cancel, Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 25/26] FVD: add impl of interface bdrv_probe(), Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 15/26] FVD: add basic journal functionality, Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 18/26] FVD: add support for base image prefetching, Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 03/26] FVD: add fully automated test-qcow2.sh, Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 02/26] FVD: extend qemu-io to do fully automated testing, Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 07/26] FVD: extend FVD header fvd.h to be more complete, Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 12/26] FVD: add impl of interface bdrv_aio_readv(), Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 11/26] FVD: add impl of interface bdrv_aio_writev(), Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 06/26] FVD: skeleton of Fast Virtual Disk, Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 05/26] FVD: add the 'qemu-img update' command,
Chunqiang Tang <=
- [Qemu-devel] [PATCH 04/26] FVD: add fully automated test-vdi.sh, Chunqiang Tang, 2011/02/25
- [Qemu-devel] [PATCH 09/26] FVD: add impl of interface bdrv_create(), Chunqiang Tang, 2011/02/25