From: Chunqiang Tang <ctang@us.ibm.com>
To: qemu-devel@nongnu.org
Cc: Chunqiang Tang <ctang@us.ibm.com>
Subject: [Qemu-devel] [PATCH 05/26] FVD: add the 'qemu-img update' command
Date: Fri, 25 Feb 2011 17:37:45 -0500 [thread overview]
Message-ID: <1298673486-3573-5-git-send-email-ctang@us.ibm.com> (raw)
In-Reply-To: <1298673486-3573-1-git-send-email-ctang@us.ibm.com>
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 <ctang@us.ibm.com>
---
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
+@item update [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}]
+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
next prev parent reply other threads:[~2011-02-25 23:26 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-25 22:37 [Qemu-devel] [PATCH 01/26] FVD: add simulated block driver 'blksim' Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 02/26] FVD: extend qemu-io to do fully automated testing Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 03/26] FVD: add fully automated test-qcow2.sh Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 04/26] FVD: add fully automated test-vdi.sh Chunqiang Tang
2011-02-25 22:37 ` Chunqiang Tang [this message]
2011-02-25 22:37 ` [Qemu-devel] [PATCH 06/26] FVD: skeleton of Fast Virtual Disk Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 07/26] FVD: extend FVD header fvd.h to be more complete Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 08/26] FVD: add debugging utilities Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 09/26] FVD: add impl of interface bdrv_create() Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 10/26] FVD: add impl of interface bdrv_file_open() Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 11/26] FVD: add impl of interface bdrv_aio_writev() Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 12/26] FVD: add impl of interface bdrv_aio_readv() Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 13/26] FVD: add impl of storing data in compact image Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 14/26] FVD: add impl of loading data from " Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 15/26] FVD: add basic journal functionality Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 16/26] FVD: add impl for buffered journal updates Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 17/26] FVD: add impl of bdrv_flush() and bdrv_aio_flush() Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 18/26] FVD: add support for base image prefetching Chunqiang Tang
2011-02-25 22:37 ` [Qemu-devel] [PATCH 19/26] FVD: add support for aio_cancel Chunqiang Tang
2011-02-25 22:38 ` [Qemu-devel] [PATCH 20/26] FVD: add impl of interface bdrv_get_info() Chunqiang Tang
2011-02-25 22:38 ` [Qemu-devel] [PATCH 21/26] FVD: add impl of interface bdrv_close() Chunqiang Tang
2011-02-25 22:38 ` [Qemu-devel] [PATCH 22/26] FVD: add impl of interface bdrv_update() Chunqiang Tang
2011-02-25 22:38 ` [Qemu-devel] [PATCH 23/26] FVD: add impl of interface bdrv_is_allocated() Chunqiang Tang
2011-02-25 22:38 ` [Qemu-devel] [PATCH 24/26] FVD: add impl of interface bdrv_has_zero_init() Chunqiang Tang
2011-02-25 22:38 ` [Qemu-devel] [PATCH 25/26] FVD: add impl of interface bdrv_probe() Chunqiang Tang
2011-02-25 22:38 ` [Qemu-devel] [PATCH 26/26] FVD: add fully automated test-fvd.sh Chunqiang Tang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1298673486-3573-5-git-send-email-ctang@us.ibm.com \
--to=ctang@us.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).