Block pull request
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTntNuAAoJEJykq7OBq3PIjqYH/3R7hbHyYltew/3q761kF2F3 xc/52bDji4AA89mYFvBtQfWvD8m+ndCYDjtXhN5C17VJUrPkNKfSZ1/BQBn0vvGk DlHd2PUvEe+9mZRVdXQRFuNRmngtIBaLuCNCDyCOsqVjxZSHGH3KBapApyKRj6Dr +I33F5v+3lcs66JDOfJeY1BmHkK2ng4FehQEWHqPIl0oiXhEWF6f5DbQ9z13a2TI 1YC9CrcsI0XjzcE/glqRo6udp/bGXPO9h1q2e2RLs7GUmSULR/TJsIE3X56MdZpE Xz/gHpGeirrbrBkJeV2j45OAuZ/7w6JucFNL7zRG3OhiTy+BkDBBHq9qKbLFc20= =7gES -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging Block pull request # gpg: Signature made Mon 16 Jun 2014 12:22:22 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/block-pull-request: (39 commits) QemuOpts: cleanup tmp 'allocated' member from QemuOptsList cleanup QEMUOptionParameter vpc.c: replace QEMUOptionParameter with QemuOpts vmdk.c: replace QEMUOptionParameter with QemuOpts vhdx.c: replace QEMUOptionParameter with QemuOpts vdi.c: replace QEMUOptionParameter with QemuOpts ssh.c: replace QEMUOptionParameter with QemuOpts sheepdog.c: replace QEMUOptionParameter with QemuOpts rbd.c: replace QEMUOptionParameter with QemuOpts raw_bsd.c: replace QEMUOptionParameter with QemuOpts raw-win32.c: replace QEMUOptionParameter with QemuOpts raw-posix.c: replace QEMUOptionParameter with QemuOpts qed.c: replace QEMUOptionParameter with QemuOpts qcow2.c: replace QEMUOptionParameter with QemuOpts QemuOpts: export qemu_opt_find qcow.c: replace QEMUOptionParameter with QemuOpts nfs.c: replace QEMUOptionParameter with QemuOpts iscsi.c: replace QEMUOptionParameter with QemuOpts gluster.c: replace QEMUOptionParameter with QemuOpts cow.c: replace QEMUOptionParameter with QemuOpts ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
84219c5a21
99
block.c
99
block.c
@ -424,7 +424,7 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
|
||||
typedef struct CreateCo {
|
||||
BlockDriver *drv;
|
||||
char *filename;
|
||||
QEMUOptionParameter *options;
|
||||
QemuOpts *opts;
|
||||
int ret;
|
||||
Error *err;
|
||||
} CreateCo;
|
||||
@ -437,7 +437,7 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
|
||||
CreateCo *cco = opaque;
|
||||
assert(cco->drv);
|
||||
|
||||
ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err);
|
||||
ret = cco->drv->bdrv_create(cco->filename, cco->opts, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(&cco->err, local_err);
|
||||
}
|
||||
@ -445,7 +445,7 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
|
||||
}
|
||||
|
||||
int bdrv_create(BlockDriver *drv, const char* filename,
|
||||
QEMUOptionParameter *options, Error **errp)
|
||||
QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -453,7 +453,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
|
||||
CreateCo cco = {
|
||||
.drv = drv,
|
||||
.filename = g_strdup(filename),
|
||||
.options = options,
|
||||
.opts = opts,
|
||||
.ret = NOT_DONE,
|
||||
.err = NULL,
|
||||
};
|
||||
@ -489,8 +489,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
BlockDriver *drv;
|
||||
Error *local_err = NULL;
|
||||
@ -502,7 +501,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = bdrv_create(drv, filename, options, &local_err);
|
||||
ret = bdrv_create(drv, filename, opts, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
@ -1247,7 +1246,7 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
|
||||
char *tmp_filename = g_malloc0(PATH_MAX + 1);
|
||||
int64_t total_size;
|
||||
BlockDriver *bdrv_qcow2;
|
||||
QEMUOptionParameter *create_options;
|
||||
QemuOpts *opts = NULL;
|
||||
QDict *snapshot_options;
|
||||
BlockDriverState *bs_snapshot;
|
||||
Error *local_err;
|
||||
@ -1272,13 +1271,11 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
|
||||
}
|
||||
|
||||
bdrv_qcow2 = bdrv_find_format("qcow2");
|
||||
create_options = parse_option_parameters("", bdrv_qcow2->create_options,
|
||||
NULL);
|
||||
|
||||
set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
|
||||
|
||||
ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
|
||||
free_option_parameters(create_options);
|
||||
opts = qemu_opts_create(bdrv_qcow2->create_opts, NULL, 0,
|
||||
&error_abort);
|
||||
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size);
|
||||
ret = bdrv_create(bdrv_qcow2, tmp_filename, opts, &local_err);
|
||||
qemu_opts_del(opts);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not create temporary overlay "
|
||||
"'%s': %s", tmp_filename,
|
||||
@ -5519,8 +5516,10 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
char *options, uint64_t img_size, int flags,
|
||||
Error **errp, bool quiet)
|
||||
{
|
||||
QEMUOptionParameter *param = NULL, *create_options = NULL;
|
||||
QEMUOptionParameter *backing_fmt, *backing_file, *size;
|
||||
QemuOptsList *create_opts = NULL;
|
||||
QemuOpts *opts = NULL;
|
||||
const char *backing_fmt, *backing_file;
|
||||
int64_t size;
|
||||
BlockDriver *drv, *proto_drv;
|
||||
BlockDriver *backing_drv = NULL;
|
||||
Error *local_err = NULL;
|
||||
@ -5539,28 +5538,23 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
return;
|
||||
}
|
||||
|
||||
create_options = append_option_parameters(create_options,
|
||||
drv->create_options);
|
||||
create_options = append_option_parameters(create_options,
|
||||
proto_drv->create_options);
|
||||
create_opts = qemu_opts_append(create_opts, drv->create_opts);
|
||||
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
|
||||
|
||||
/* Create parameter list with default values */
|
||||
param = parse_option_parameters("", create_options, param);
|
||||
|
||||
set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
|
||||
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
|
||||
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size);
|
||||
|
||||
/* Parse -o options */
|
||||
if (options) {
|
||||
param = parse_option_parameters(options, create_options, param);
|
||||
if (param == NULL) {
|
||||
error_setg(errp, "Invalid options for file format '%s'.", fmt);
|
||||
if (qemu_opts_do_parse(opts, options, NULL) != 0) {
|
||||
error_setg(errp, "Invalid options for file format '%s'", fmt);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (base_filename) {
|
||||
if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE,
|
||||
base_filename)) {
|
||||
if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
|
||||
error_setg(errp, "Backing file not supported for file format '%s'",
|
||||
fmt);
|
||||
goto out;
|
||||
@ -5568,37 +5562,37 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
}
|
||||
|
||||
if (base_fmt) {
|
||||
if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
|
||||
if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
|
||||
error_setg(errp, "Backing file format not supported for file "
|
||||
"format '%s'", fmt);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
|
||||
if (backing_file && backing_file->value.s) {
|
||||
if (!strcmp(filename, backing_file->value.s)) {
|
||||
backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
|
||||
if (backing_file) {
|
||||
if (!strcmp(filename, backing_file)) {
|
||||
error_setg(errp, "Error: Trying to create an image with the "
|
||||
"same filename as the backing file");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
|
||||
if (backing_fmt && backing_fmt->value.s) {
|
||||
backing_drv = bdrv_find_format(backing_fmt->value.s);
|
||||
backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
|
||||
if (backing_fmt) {
|
||||
backing_drv = bdrv_find_format(backing_fmt);
|
||||
if (!backing_drv) {
|
||||
error_setg(errp, "Unknown backing file format '%s'",
|
||||
backing_fmt->value.s);
|
||||
backing_fmt);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
size = get_option_parameter(param, BLOCK_OPT_SIZE);
|
||||
if (size && size->value.n == -1) {
|
||||
if (backing_file && backing_file->value.s) {
|
||||
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
|
||||
if (size == -1) {
|
||||
if (backing_file) {
|
||||
BlockDriverState *bs;
|
||||
uint64_t size;
|
||||
char buf[32];
|
||||
@ -5609,11 +5603,11 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
|
||||
|
||||
bs = NULL;
|
||||
ret = bdrv_open(&bs, backing_file->value.s, NULL, NULL, back_flags,
|
||||
ret = bdrv_open(&bs, backing_file, NULL, NULL, back_flags,
|
||||
backing_drv, &local_err);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not open '%s': %s",
|
||||
backing_file->value.s,
|
||||
backing_file,
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
local_err = NULL;
|
||||
@ -5623,7 +5617,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
size *= 512;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%" PRId64, size);
|
||||
set_option_parameter(param, BLOCK_OPT_SIZE, buf);
|
||||
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size);
|
||||
|
||||
bdrv_unref(bs);
|
||||
} else {
|
||||
@ -5634,16 +5628,18 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
|
||||
if (!quiet) {
|
||||
printf("Formatting '%s', fmt=%s ", filename, fmt);
|
||||
print_option_parameters(param);
|
||||
qemu_opts_print(opts);
|
||||
puts("");
|
||||
}
|
||||
ret = bdrv_create(drv, filename, param, &local_err);
|
||||
|
||||
ret = bdrv_create(drv, filename, opts, &local_err);
|
||||
|
||||
if (ret == -EFBIG) {
|
||||
/* This is generally a better message than whatever the driver would
|
||||
* deliver (especially because of the cluster_size_hint), since that
|
||||
* is most probably not much different from "image too large". */
|
||||
const char *cluster_size_hint = "";
|
||||
if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) {
|
||||
if (qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE, 0)) {
|
||||
cluster_size_hint = " (try using a larger cluster size)";
|
||||
}
|
||||
error_setg(errp, "The image size is too large for file format '%s'"
|
||||
@ -5653,9 +5649,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
}
|
||||
|
||||
out:
|
||||
free_option_parameters(create_options);
|
||||
free_option_parameters(param);
|
||||
|
||||
qemu_opts_del(opts);
|
||||
qemu_opts_free(create_opts);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
@ -5731,12 +5726,12 @@ void bdrv_add_before_write_notifier(BlockDriverState *bs,
|
||||
notifier_with_return_list_add(&bs->before_write_notifiers, notifier);
|
||||
}
|
||||
|
||||
int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options)
|
||||
int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts)
|
||||
{
|
||||
if (bs->drv->bdrv_amend_options == NULL) {
|
||||
if (!bs->drv->bdrv_amend_options) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return bs->drv->bdrv_amend_options(bs, options);
|
||||
return bs->drv->bdrv_amend_options(bs, opts);
|
||||
}
|
||||
|
||||
/* This function will be called by the bdrv_recurse_is_first_non_filter method
|
||||
|
52
block/cow.c
52
block/cow.c
@ -324,31 +324,24 @@ static void cow_close(BlockDriverState *bs)
|
||||
{
|
||||
}
|
||||
|
||||
static int cow_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int cow_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
struct cow_header_v2 cow_header;
|
||||
struct stat st;
|
||||
int64_t image_sectors = 0;
|
||||
const char *image_filename = NULL;
|
||||
char *image_filename = NULL;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
BlockDriverState *cow_bs;
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
image_sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
|
||||
image_filename = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
|
||||
|
||||
ret = bdrv_create_file(filename, options, &local_err);
|
||||
ret = bdrv_create_file(filename, opts, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
return ret;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cow_bs = NULL;
|
||||
@ -356,7 +349,7 @@ static int cow_create(const char *filename, QEMUOptionParameter *options,
|
||||
BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
return ret;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(&cow_header, 0, sizeof(cow_header));
|
||||
@ -389,22 +382,27 @@ static int cow_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
|
||||
exit:
|
||||
g_free(image_filename);
|
||||
bdrv_unref(cow_bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter cow_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList cow_create_opts = {
|
||||
.name = "cow-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(cow_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_cow = {
|
||||
@ -421,7 +419,7 @@ static BlockDriver bdrv_cow = {
|
||||
.bdrv_write = cow_co_write,
|
||||
.bdrv_co_get_block_status = cow_co_get_block_status,
|
||||
|
||||
.create_options = cow_create_options,
|
||||
.create_opts = &cow_create_opts,
|
||||
};
|
||||
|
||||
static void bdrv_cow_init(void)
|
||||
|
@ -440,10 +440,8 @@ static void curl_detach_aio_context(BlockDriverState *bs)
|
||||
curl_easy_cleanup(s->states[i].curl);
|
||||
s->states[i].curl = NULL;
|
||||
}
|
||||
if (s->states[i].orig_buf) {
|
||||
g_free(s->states[i].orig_buf);
|
||||
s->states[i].orig_buf = NULL;
|
||||
}
|
||||
g_free(s->states[i].orig_buf);
|
||||
s->states[i].orig_buf = NULL;
|
||||
}
|
||||
if (s->multi) {
|
||||
curl_multi_cleanup(s->multi);
|
||||
@ -638,8 +636,7 @@ static void curl_readv_bh_cb(void *p)
|
||||
acb->end = (acb->nb_sectors * SECTOR_SIZE);
|
||||
|
||||
state->buf_off = 0;
|
||||
if (state->orig_buf)
|
||||
g_free(state->orig_buf);
|
||||
g_free(state->orig_buf);
|
||||
state->buf_start = start;
|
||||
state->buf_len = acb->end + s->readahead_size;
|
||||
end = MIN(start + state->buf_len, s->len) - 1;
|
||||
|
@ -478,13 +478,14 @@ static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
|
||||
#endif
|
||||
|
||||
static int qemu_gluster_create(const char *filename,
|
||||
QEMUOptionParameter *options, Error **errp)
|
||||
QemuOpts *opts, Error **errp)
|
||||
{
|
||||
struct glfs *glfs;
|
||||
struct glfs_fd *fd;
|
||||
int ret = 0;
|
||||
int prealloc = 0;
|
||||
int64_t total_size = 0;
|
||||
char *tmp = NULL;
|
||||
GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
|
||||
|
||||
glfs = qemu_gluster_init(gconf, filename, errp);
|
||||
@ -493,24 +494,21 @@ static int qemu_gluster_create(const char *filename,
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
total_size = options->value.n / BDRV_SECTOR_SIZE;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
|
||||
if (!options->value.s || !strcmp(options->value.s, "off")) {
|
||||
prealloc = 0;
|
||||
} else if (!strcmp(options->value.s, "full") &&
|
||||
gluster_supports_zerofill()) {
|
||||
prealloc = 1;
|
||||
} else {
|
||||
error_setg(errp, "Invalid preallocation mode: '%s'"
|
||||
" or GlusterFS doesn't support zerofill API",
|
||||
options->value.s);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
options++;
|
||||
total_size =
|
||||
qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
|
||||
|
||||
tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
if (!tmp || !strcmp(tmp, "off")) {
|
||||
prealloc = 0;
|
||||
} else if (!strcmp(tmp, "full") &&
|
||||
gluster_supports_zerofill()) {
|
||||
prealloc = 1;
|
||||
} else {
|
||||
error_setg(errp, "Invalid preallocation mode: '%s'"
|
||||
" or GlusterFS doesn't support zerofill API",
|
||||
tmp);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = glfs_creat(glfs, gconf->image,
|
||||
@ -532,6 +530,7 @@ static int qemu_gluster_create(const char *filename,
|
||||
}
|
||||
}
|
||||
out:
|
||||
g_free(tmp);
|
||||
qemu_gluster_gconf_free(gconf);
|
||||
if (glfs) {
|
||||
glfs_fini(glfs);
|
||||
@ -698,18 +697,22 @@ static int qemu_gluster_has_zero_init(BlockDriverState *bs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter qemu_gluster_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off, full)"
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList qemu_gluster_create_opts = {
|
||||
.name = "qemu-gluster-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_gluster_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off, full)"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_gluster = {
|
||||
@ -736,7 +739,7 @@ static BlockDriver bdrv_gluster = {
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
.bdrv_co_write_zeroes = qemu_gluster_co_write_zeroes,
|
||||
#endif
|
||||
.create_options = qemu_gluster_create_options,
|
||||
.create_opts = &qemu_gluster_create_opts,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_gluster_tcp = {
|
||||
@ -763,7 +766,7 @@ static BlockDriver bdrv_gluster_tcp = {
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
.bdrv_co_write_zeroes = qemu_gluster_co_write_zeroes,
|
||||
#endif
|
||||
.create_options = qemu_gluster_create_options,
|
||||
.create_opts = &qemu_gluster_create_opts,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_gluster_unix = {
|
||||
@ -790,7 +793,7 @@ static BlockDriver bdrv_gluster_unix = {
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
.bdrv_co_write_zeroes = qemu_gluster_co_write_zeroes,
|
||||
#endif
|
||||
.create_options = qemu_gluster_create_options,
|
||||
.create_opts = &qemu_gluster_create_opts,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_gluster_rdma = {
|
||||
@ -817,7 +820,7 @@ static BlockDriver bdrv_gluster_rdma = {
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
.bdrv_co_write_zeroes = qemu_gluster_co_write_zeroes,
|
||||
#endif
|
||||
.create_options = qemu_gluster_create_options,
|
||||
.create_opts = &qemu_gluster_create_opts,
|
||||
};
|
||||
|
||||
static void bdrv_gluster_init(void)
|
||||
|
@ -1434,9 +1434,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
out:
|
||||
qemu_opts_del(opts);
|
||||
if (initiator_name != NULL) {
|
||||
g_free(initiator_name);
|
||||
}
|
||||
g_free(initiator_name);
|
||||
if (iscsi_url != NULL) {
|
||||
iscsi_destroy_url(iscsi_url);
|
||||
}
|
||||
@ -1532,8 +1530,7 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iscsi_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
int64_t total_size = 0;
|
||||
@ -1544,13 +1541,8 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
|
||||
bs = bdrv_new("", &error_abort);
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, "size")) {
|
||||
total_size = options->value.n / BDRV_SECTOR_SIZE;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
|
||||
total_size =
|
||||
qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
|
||||
bs->opaque = g_malloc0(sizeof(struct IscsiLun));
|
||||
iscsilun = bs->opaque;
|
||||
|
||||
@ -1592,13 +1584,17 @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter iscsi_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList iscsi_create_opts = {
|
||||
.name = "iscsi-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(iscsi_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_iscsi = {
|
||||
@ -1610,7 +1606,7 @@ static BlockDriver bdrv_iscsi = {
|
||||
.bdrv_file_open = iscsi_open,
|
||||
.bdrv_close = iscsi_close,
|
||||
.bdrv_create = iscsi_create,
|
||||
.create_options = iscsi_create_options,
|
||||
.create_opts = &iscsi_create_opts,
|
||||
.bdrv_reopen_prepare = iscsi_reopen_prepare,
|
||||
|
||||
.bdrv_getlength = iscsi_getlength,
|
||||
|
14
block/nfs.c
14
block/nfs.c
@ -95,6 +95,7 @@ static void nfs_co_init_task(NFSClient *client, NFSRPC *task)
|
||||
static void nfs_co_generic_bh_cb(void *opaque)
|
||||
{
|
||||
NFSRPC *task = opaque;
|
||||
task->complete = 1;
|
||||
qemu_bh_delete(task->bh);
|
||||
qemu_coroutine_enter(task->co, NULL);
|
||||
}
|
||||
@ -104,7 +105,6 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
|
||||
void *private_data)
|
||||
{
|
||||
NFSRPC *task = private_data;
|
||||
task->complete = 1;
|
||||
task->ret = ret;
|
||||
if (task->ret > 0 && task->iov) {
|
||||
if (task->ret <= task->iov->size) {
|
||||
@ -123,6 +123,8 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
|
||||
task->bh = aio_bh_new(task->client->aio_context,
|
||||
nfs_co_generic_bh_cb, task);
|
||||
qemu_bh_schedule(task->bh);
|
||||
} else {
|
||||
task->complete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,8 +391,7 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfs_file_create(const char *url, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
int64_t total_size = 0;
|
||||
@ -399,12 +400,7 @@ static int nfs_file_create(const char *url, QEMUOptionParameter *options,
|
||||
client->aio_context = qemu_get_aio_context();
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, "size")) {
|
||||
total_size = options->value.n;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
|
||||
ret = nfs_client_open(client, url, O_CREAT, errp);
|
||||
if (ret < 0) {
|
||||
|
72
block/qcow.c
72
block/qcow.c
@ -693,35 +693,29 @@ static void qcow_close(BlockDriverState *bs)
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static int qcow_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int header_size, backing_filename_len, l1_size, shift, i;
|
||||
QCowHeader header;
|
||||
uint8_t *tmp;
|
||||
int64_t total_size = 0;
|
||||
const char *backing_file = NULL;
|
||||
char *backing_file = NULL;
|
||||
int flags = 0;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
BlockDriverState *qcow_bs;
|
||||
|
||||
/* 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++;
|
||||
total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
|
||||
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
|
||||
if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
|
||||
flags |= BLOCK_FLAG_ENCRYPT;
|
||||
}
|
||||
|
||||
ret = bdrv_create_file(filename, options, &local_err);
|
||||
ret = bdrv_create_file(filename, opts, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
return ret;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
qcow_bs = NULL;
|
||||
@ -729,7 +723,7 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options,
|
||||
BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
return ret;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = bdrv_truncate(qcow_bs, 0);
|
||||
@ -800,6 +794,8 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options,
|
||||
ret = 0;
|
||||
exit:
|
||||
bdrv_unref(qcow_bs);
|
||||
cleanup:
|
||||
g_free(backing_file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -912,24 +908,28 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static QEMUOptionParameter qcow_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_ENCRYPT,
|
||||
.type = OPT_FLAG,
|
||||
.help = "Encrypt the image"
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList qcow_create_opts = {
|
||||
.name = "qcow-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qcow_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_ENCRYPT,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Encrypt the image",
|
||||
.def_value_str = "off"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_qcow = {
|
||||
@ -938,8 +938,8 @@ static BlockDriver bdrv_qcow = {
|
||||
.bdrv_probe = qcow_probe,
|
||||
.bdrv_open = qcow_open,
|
||||
.bdrv_close = qcow_close,
|
||||
.bdrv_reopen_prepare = qcow_reopen_prepare,
|
||||
.bdrv_create = qcow_create,
|
||||
.bdrv_reopen_prepare = qcow_reopen_prepare,
|
||||
.bdrv_create = qcow_create,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
|
||||
.bdrv_co_readv = qcow_co_readv,
|
||||
@ -951,7 +951,7 @@ static BlockDriver bdrv_qcow = {
|
||||
.bdrv_write_compressed = qcow_write_compressed,
|
||||
.bdrv_get_info = qcow_get_info,
|
||||
|
||||
.create_options = qcow_create_options,
|
||||
.create_opts = &qcow_create_opts,
|
||||
};
|
||||
|
||||
static void bdrv_qcow_init(void)
|
||||
|
259
block/qcow2.c
259
block/qcow2.c
@ -31,6 +31,7 @@
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/option_int.h"
|
||||
|
||||
/*
|
||||
Differences with QCOW:
|
||||
@ -1594,7 +1595,7 @@ static int preallocate(BlockDriverState *bs)
|
||||
static int qcow2_create2(const char *filename, int64_t total_size,
|
||||
const char *backing_file, const char *backing_format,
|
||||
int flags, size_t cluster_size, int prealloc,
|
||||
QEMUOptionParameter *options, int version,
|
||||
QemuOpts *opts, int version,
|
||||
Error **errp)
|
||||
{
|
||||
/* Calculate cluster_bits */
|
||||
@ -1626,7 +1627,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_create_file(filename, options, &local_err);
|
||||
ret = bdrv_create_file(filename, opts, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
return ret;
|
||||
@ -1762,11 +1763,11 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcow2_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
const char *backing_file = NULL;
|
||||
const char *backing_fmt = NULL;
|
||||
char *backing_file = NULL;
|
||||
char *backing_fmt = NULL;
|
||||
char *buf = NULL;
|
||||
uint64_t sectors = 0;
|
||||
int flags = 0;
|
||||
size_t cluster_size = DEFAULT_CLUSTER_SIZE;
|
||||
@ -1776,64 +1777,66 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options,
|
||||
int ret;
|
||||
|
||||
/* 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;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
|
||||
if (options->value.n) {
|
||||
cluster_size = options->value.n;
|
||||
}
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
|
||||
if (!options->value.s || !strcmp(options->value.s, "off")) {
|
||||
prealloc = 0;
|
||||
} else if (!strcmp(options->value.s, "metadata")) {
|
||||
prealloc = 1;
|
||||
} else {
|
||||
error_setg(errp, "Invalid preallocation mode: '%s'",
|
||||
options->value.s);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_COMPAT_LEVEL)) {
|
||||
if (!options->value.s) {
|
||||
/* keep the default */
|
||||
} else if (!strcmp(options->value.s, "0.10")) {
|
||||
version = 2;
|
||||
} else if (!strcmp(options->value.s, "1.1")) {
|
||||
version = 3;
|
||||
} else {
|
||||
error_setg(errp, "Invalid compatibility level: '%s'",
|
||||
options->value.s);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
|
||||
flags |= options->value.n ? BLOCK_FLAG_LAZY_REFCOUNTS : 0;
|
||||
}
|
||||
options++;
|
||||
sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
|
||||
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
|
||||
backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);
|
||||
if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
|
||||
flags |= BLOCK_FLAG_ENCRYPT;
|
||||
}
|
||||
cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
|
||||
DEFAULT_CLUSTER_SIZE);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
if (!buf || !strcmp(buf, "off")) {
|
||||
prealloc = 0;
|
||||
} else if (!strcmp(buf, "metadata")) {
|
||||
prealloc = 1;
|
||||
} else {
|
||||
error_setg(errp, "Invalid preallocation mode: '%s'", buf);
|
||||
ret = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
g_free(buf);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_COMPAT_LEVEL);
|
||||
if (!buf) {
|
||||
/* keep the default */
|
||||
} else if (!strcmp(buf, "0.10")) {
|
||||
version = 2;
|
||||
} else if (!strcmp(buf, "1.1")) {
|
||||
version = 3;
|
||||
} else {
|
||||
error_setg(errp, "Invalid compatibility level: '%s'", buf);
|
||||
ret = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (qemu_opt_get_bool_del(opts, BLOCK_OPT_LAZY_REFCOUNTS, false)) {
|
||||
flags |= BLOCK_FLAG_LAZY_REFCOUNTS;
|
||||
}
|
||||
|
||||
if (backing_file && prealloc) {
|
||||
error_setg(errp, "Backing file and preallocation cannot be used at "
|
||||
"the same time");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) {
|
||||
error_setg(errp, "Lazy refcounts only supported with compatibility "
|
||||
"level 1.1 and above (use compat=1.1 or greater)");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = qcow2_create2(filename, sectors, backing_file, backing_fmt, flags,
|
||||
cluster_size, prealloc, options, version, &local_err);
|
||||
cluster_size, prealloc, opts, version, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
finish:
|
||||
g_free(backing_file);
|
||||
g_free(backing_fmt);
|
||||
g_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2198,64 +2201,72 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcow2_amend_options(BlockDriverState *bs,
|
||||
QEMUOptionParameter *options)
|
||||
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int old_version = s->qcow_version, new_version = old_version;
|
||||
uint64_t new_size = 0;
|
||||
const char *backing_file = NULL, *backing_format = NULL;
|
||||
bool lazy_refcounts = s->use_lazy_refcounts;
|
||||
const char *compat = NULL;
|
||||
uint64_t cluster_size = s->cluster_size;
|
||||
bool encrypt;
|
||||
int ret;
|
||||
int i;
|
||||
QemuOptDesc *desc = opts->list->desc;
|
||||
|
||||
for (i = 0; options[i].name; i++)
|
||||
{
|
||||
if (!options[i].assigned) {
|
||||
while (desc && desc->name) {
|
||||
if (!qemu_opt_find(opts, desc->name)) {
|
||||
/* only change explicitly defined options */
|
||||
desc++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(options[i].name, "compat")) {
|
||||
if (!options[i].value.s) {
|
||||
if (!strcmp(desc->name, "compat")) {
|
||||
compat = qemu_opt_get(opts, "compat");
|
||||
if (!compat) {
|
||||
/* preserve default */
|
||||
} else if (!strcmp(options[i].value.s, "0.10")) {
|
||||
} else if (!strcmp(compat, "0.10")) {
|
||||
new_version = 2;
|
||||
} else if (!strcmp(options[i].value.s, "1.1")) {
|
||||
} else if (!strcmp(compat, "1.1")) {
|
||||
new_version = 3;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown compatibility level %s.\n",
|
||||
options[i].value.s);
|
||||
fprintf(stderr, "Unknown compatibility level %s.\n", compat);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (!strcmp(options[i].name, "preallocation")) {
|
||||
} else if (!strcmp(desc->name, "preallocation")) {
|
||||
fprintf(stderr, "Cannot change preallocation mode.\n");
|
||||
return -ENOTSUP;
|
||||
} else if (!strcmp(options[i].name, "size")) {
|
||||
new_size = options[i].value.n;
|
||||
} else if (!strcmp(options[i].name, "backing_file")) {
|
||||
backing_file = options[i].value.s;
|
||||
} else if (!strcmp(options[i].name, "backing_fmt")) {
|
||||
backing_format = options[i].value.s;
|
||||
} else if (!strcmp(options[i].name, "encryption")) {
|
||||
if ((options[i].value.n != !!s->crypt_method)) {
|
||||
} else if (!strcmp(desc->name, "size")) {
|
||||
new_size = qemu_opt_get_size(opts, "size", 0);
|
||||
} else if (!strcmp(desc->name, "backing_file")) {
|
||||
backing_file = qemu_opt_get(opts, "backing_file");
|
||||
} else if (!strcmp(desc->name, "backing_fmt")) {
|
||||
backing_format = qemu_opt_get(opts, "backing_fmt");
|
||||
} else if (!strcmp(desc->name, "encryption")) {
|
||||
encrypt = qemu_opt_get_bool(opts, "encryption", s->crypt_method);
|
||||
if (encrypt != !!s->crypt_method) {
|
||||
fprintf(stderr, "Changing the encryption flag is not "
|
||||
"supported.\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
} else if (!strcmp(options[i].name, "cluster_size")) {
|
||||
if (options[i].value.n != s->cluster_size) {
|
||||
} else if (!strcmp(desc->name, "cluster_size")) {
|
||||
cluster_size = qemu_opt_get_size(opts, "cluster_size",
|
||||
cluster_size);
|
||||
if (cluster_size != s->cluster_size) {
|
||||
fprintf(stderr, "Changing the cluster size is not "
|
||||
"supported.\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
} else if (!strcmp(options[i].name, "lazy_refcounts")) {
|
||||
lazy_refcounts = options[i].value.n;
|
||||
} else if (!strcmp(desc->name, "lazy_refcounts")) {
|
||||
lazy_refcounts = qemu_opt_get_bool(opts, "lazy_refcounts",
|
||||
lazy_refcounts);
|
||||
} else {
|
||||
/* if this assertion fails, this probably means a new option was
|
||||
* added without having it covered here */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
desc++;
|
||||
}
|
||||
|
||||
if (new_version != old_version) {
|
||||
@ -2324,49 +2335,55 @@ static int qcow2_amend_options(BlockDriverState *bs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter qcow2_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_COMPAT_LEVEL,
|
||||
.type = OPT_STRING,
|
||||
.help = "Compatibility level (0.10 or 1.1)"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FMT,
|
||||
.type = OPT_STRING,
|
||||
.help = "Image format of the base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_ENCRYPT,
|
||||
.type = OPT_FLAG,
|
||||
.help = "Encrypt the image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "qcow2 cluster size",
|
||||
.value = { .n = DEFAULT_CLUSTER_SIZE },
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off, metadata)"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_LAZY_REFCOUNTS,
|
||||
.type = OPT_FLAG,
|
||||
.help = "Postpone refcount updates",
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList qcow2_create_opts = {
|
||||
.name = "qcow2-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qcow2_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_COMPAT_LEVEL,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Compatibility level (0.10 or 1.1)"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FMT,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Image format of the base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_ENCRYPT,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Encrypt the image",
|
||||
.def_value_str = "off"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "qcow2 cluster size",
|
||||
.def_value_str = stringify(DEFAULT_CLUSTER_SIZE)
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off, metadata)"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_LAZY_REFCOUNTS,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Postpone refcount updates",
|
||||
.def_value_str = "off"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_qcow2 = {
|
||||
@ -2394,8 +2411,8 @@ static BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_snapshot_goto = qcow2_snapshot_goto,
|
||||
.bdrv_snapshot_delete = qcow2_snapshot_delete,
|
||||
.bdrv_snapshot_list = qcow2_snapshot_list,
|
||||
.bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp,
|
||||
.bdrv_get_info = qcow2_get_info,
|
||||
.bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp,
|
||||
.bdrv_get_info = qcow2_get_info,
|
||||
.bdrv_get_specific_info = qcow2_get_specific_info,
|
||||
|
||||
.bdrv_save_vmstate = qcow2_save_vmstate,
|
||||
@ -2406,9 +2423,9 @@ static BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_refresh_limits = qcow2_refresh_limits,
|
||||
.bdrv_invalidate_cache = qcow2_invalidate_cache,
|
||||
|
||||
.create_options = qcow2_create_options,
|
||||
.bdrv_check = qcow2_check,
|
||||
.bdrv_amend_options = qcow2_amend_options,
|
||||
.create_opts = &qcow2_create_opts,
|
||||
.bdrv_check = qcow2_check,
|
||||
.bdrv_amend_options = qcow2_amend_options,
|
||||
};
|
||||
|
||||
static void bdrv_qcow2_init(void)
|
||||
|
110
block/qed.c
110
block/qed.c
@ -641,55 +641,53 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int bdrv_qed_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
uint64_t image_size = 0;
|
||||
uint32_t cluster_size = QED_DEFAULT_CLUSTER_SIZE;
|
||||
uint32_t table_size = QED_DEFAULT_TABLE_SIZE;
|
||||
const char *backing_file = NULL;
|
||||
const char *backing_fmt = NULL;
|
||||
char *backing_file = NULL;
|
||||
char *backing_fmt = NULL;
|
||||
int ret;
|
||||
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
image_size = options->value.n;
|
||||
} 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_CLUSTER_SIZE)) {
|
||||
if (options->value.n) {
|
||||
cluster_size = options->value.n;
|
||||
}
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_TABLE_SIZE)) {
|
||||
if (options->value.n) {
|
||||
table_size = options->value.n;
|
||||
}
|
||||
}
|
||||
options++;
|
||||
}
|
||||
image_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
|
||||
backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);
|
||||
cluster_size = qemu_opt_get_size_del(opts,
|
||||
BLOCK_OPT_CLUSTER_SIZE,
|
||||
QED_DEFAULT_CLUSTER_SIZE);
|
||||
table_size = qemu_opt_get_size_del(opts, BLOCK_OPT_TABLE_SIZE,
|
||||
QED_DEFAULT_TABLE_SIZE);
|
||||
|
||||
if (!qed_is_cluster_size_valid(cluster_size)) {
|
||||
error_setg(errp, "QED cluster size must be within range [%u, %u] "
|
||||
"and power of 2",
|
||||
QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
if (!qed_is_table_size_valid(table_size)) {
|
||||
error_setg(errp, "QED table size must be within range [%u, %u] "
|
||||
"and power of 2",
|
||||
QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) {
|
||||
error_setg(errp, "QED image size must be a non-zero multiple of "
|
||||
"cluster size and less than %" PRIu64 " bytes",
|
||||
qed_max_image_size(cluster_size, table_size));
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
return qed_create(filename, cluster_size, image_size, table_size,
|
||||
backing_file, backing_fmt, errp);
|
||||
ret = qed_create(filename, cluster_size, image_size, table_size,
|
||||
backing_file, backing_fmt, errp);
|
||||
|
||||
finish:
|
||||
g_free(backing_file);
|
||||
g_free(backing_fmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@ -1616,36 +1614,44 @@ static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result,
|
||||
return qed_check(s, result, !!fix);
|
||||
}
|
||||
|
||||
static QEMUOptionParameter qed_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size (in bytes)"
|
||||
}, {
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
}, {
|
||||
.name = BLOCK_OPT_BACKING_FMT,
|
||||
.type = OPT_STRING,
|
||||
.help = "Image format of the base image"
|
||||
}, {
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Cluster size (in bytes)",
|
||||
.value = { .n = QED_DEFAULT_CLUSTER_SIZE },
|
||||
}, {
|
||||
.name = BLOCK_OPT_TABLE_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "L1/L2 table size (in clusters)"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
static QemuOptsList qed_create_opts = {
|
||||
.name = "qed-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qed_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FMT,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Image format of the base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Cluster size (in bytes)",
|
||||
.def_value_str = stringify(QED_DEFAULT_CLUSTER_SIZE)
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_TABLE_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "L1/L2 table size (in clusters)"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_qed = {
|
||||
.format_name = "qed",
|
||||
.instance_size = sizeof(BDRVQEDState),
|
||||
.create_options = qed_create_options,
|
||||
.create_opts = &qed_create_opts,
|
||||
|
||||
.bdrv_probe = bdrv_qed_probe,
|
||||
.bdrv_rebind = bdrv_qed_rebind,
|
||||
|
@ -43,7 +43,7 @@
|
||||
*
|
||||
* All fields are little-endian on disk.
|
||||
*/
|
||||
|
||||
#define QED_DEFAULT_CLUSTER_SIZE 65536
|
||||
enum {
|
||||
QED_MAGIC = 'Q' | 'E' << 8 | 'D' << 16 | '\0' << 24,
|
||||
|
||||
@ -69,7 +69,6 @@ enum {
|
||||
*/
|
||||
QED_MIN_CLUSTER_SIZE = 4 * 1024, /* in bytes */
|
||||
QED_MAX_CLUSTER_SIZE = 64 * 1024 * 1024,
|
||||
QED_DEFAULT_CLUSTER_SIZE = 64 * 1024,
|
||||
|
||||
/* Allocated clusters are tracked using a 2-level pagetable. Table size is
|
||||
* a multiple of clusters so large maximum image sizes can be supported
|
||||
|
@ -1273,8 +1273,7 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
return (int64_t)st.st_blocks * 512;
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
int result = 0;
|
||||
@ -1283,12 +1282,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
|
||||
strstart(filename, "file:", &filename);
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
total_size = options->value.n / BDRV_SECTOR_SIZE;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
total_size =
|
||||
qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
|
||||
|
||||
fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
|
||||
0644);
|
||||
@ -1473,13 +1468,17 @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter raw_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList raw_create_opts = {
|
||||
.name = "raw-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_file = {
|
||||
@ -1514,7 +1513,7 @@ static BlockDriver bdrv_file = {
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
.create_options = raw_create_options,
|
||||
.create_opts = &raw_create_opts,
|
||||
};
|
||||
|
||||
/***********************************************/
|
||||
@ -1835,7 +1834,7 @@ static coroutine_fn int hdev_co_write_zeroes(BlockDriverState *bs,
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int hdev_create(const char *filename, QEMUOptionParameter *options,
|
||||
static int hdev_create(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int fd;
|
||||
@ -1856,12 +1855,8 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options,
|
||||
(void)has_prefix;
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, "size")) {
|
||||
total_size = options->value.n / BDRV_SECTOR_SIZE;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
total_size =
|
||||
qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
|
||||
|
||||
fd = qemu_open(filename, O_WRONLY | O_BINARY);
|
||||
if (fd < 0) {
|
||||
@ -1898,8 +1893,8 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_options = raw_create_options,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_opts = &raw_create_opts,
|
||||
.bdrv_co_write_zeroes = hdev_co_write_zeroes,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
@ -2045,8 +2040,8 @@ static BlockDriver bdrv_host_floppy = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_options = raw_create_options,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_opts = &raw_create_opts,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
@ -2173,8 +2168,8 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_options = raw_create_options,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_opts = &raw_create_opts,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
@ -2308,7 +2303,7 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_options = raw_create_options,
|
||||
.create_opts = &raw_create_opts,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
|
@ -503,8 +503,7 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
int64_t total_size = 0;
|
||||
@ -512,12 +511,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
|
||||
strstart(filename, "file:", &filename);
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
total_size = options->value.n / 512;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
total_size =
|
||||
qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
|
||||
|
||||
fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
|
||||
0644);
|
||||
@ -531,13 +526,18 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter raw_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ NULL }
|
||||
|
||||
static QemuOptsList raw_create_opts = {
|
||||
.name = "raw-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_file = {
|
||||
@ -546,9 +546,9 @@ static BlockDriver bdrv_file = {
|
||||
.instance_size = sizeof(BDRVRawState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_parse_filename = raw_parse_filename,
|
||||
.bdrv_file_open = raw_open,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_create = raw_create,
|
||||
.bdrv_file_open = raw_open,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_create = raw_create,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
@ -560,7 +560,7 @@ static BlockDriver bdrv_file = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.create_options = raw_create_options,
|
||||
.create_opts = &raw_create_opts,
|
||||
};
|
||||
|
||||
/***********************************************/
|
||||
|
@ -29,13 +29,17 @@
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/option.h"
|
||||
|
||||
static QEMUOptionParameter raw_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ 0 }
|
||||
static QemuOptsList raw_create_opts = {
|
||||
.name = "raw-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static int raw_reopen_prepare(BDRVReopenState *reopen_state,
|
||||
@ -139,13 +143,12 @@ static int raw_has_zero_init(BlockDriverState *bs)
|
||||
return bdrv_has_zero_init(bs->file);
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_create_file(filename, options, &local_err);
|
||||
ret = bdrv_create_file(filename, opts, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
@ -194,7 +197,7 @@ static BlockDriver bdrv_raw = {
|
||||
.bdrv_lock_medium = &raw_lock_medium,
|
||||
.bdrv_ioctl = &raw_ioctl,
|
||||
.bdrv_aio_ioctl = &raw_aio_ioctl,
|
||||
.create_options = &raw_create_options[0],
|
||||
.create_opts = &raw_create_opts,
|
||||
.bdrv_has_zero_init = &raw_has_zero_init
|
||||
};
|
||||
|
||||
|
61
block/rbd.c
61
block/rbd.c
@ -289,8 +289,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf, Error **errp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int64_t bytes = 0;
|
||||
@ -315,24 +314,18 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
bytes = options->value.n;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
|
||||
if (options->value.n) {
|
||||
objsize = options->value.n;
|
||||
if ((objsize - 1) & objsize) { /* not a power of 2? */
|
||||
error_setg(errp, "obj size needs to be power of 2");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (objsize < 4096) {
|
||||
error_setg(errp, "obj size too small");
|
||||
return -EINVAL;
|
||||
}
|
||||
obj_order = ffs(objsize) - 1;
|
||||
}
|
||||
bytes = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0);
|
||||
if (objsize) {
|
||||
if ((objsize - 1) & objsize) { /* not a power of 2? */
|
||||
error_setg(errp, "obj size needs to be power of 2");
|
||||
return -EINVAL;
|
||||
}
|
||||
options++;
|
||||
if (objsize < 4096) {
|
||||
error_setg(errp, "obj size too small");
|
||||
return -EINVAL;
|
||||
}
|
||||
obj_order = ffs(objsize) - 1;
|
||||
}
|
||||
|
||||
clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
|
||||
@ -911,18 +904,22 @@ static BlockDriverAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs,
|
||||
}
|
||||
#endif
|
||||
|
||||
static QEMUOptionParameter qemu_rbd_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "RBD object size"
|
||||
},
|
||||
{NULL}
|
||||
static QemuOptsList qemu_rbd_create_opts = {
|
||||
.name = "rbd-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_rbd_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "RBD object size"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_rbd = {
|
||||
@ -934,7 +931,7 @@ static BlockDriver bdrv_rbd = {
|
||||
.bdrv_create = qemu_rbd_create,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_get_info = qemu_rbd_getinfo,
|
||||
.create_options = qemu_rbd_create_options,
|
||||
.create_opts = &qemu_rbd_create_opts,
|
||||
.bdrv_getlength = qemu_rbd_getlength,
|
||||
.bdrv_truncate = qemu_rbd_truncate,
|
||||
.protocol_name = "rbd",
|
||||
|
105
block/sheepdog.c
105
block/sheepdog.c
@ -1670,12 +1670,13 @@ static int parse_redundancy(BDRVSheepdogState *s, const char *opt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
static int sd_create(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t vid = 0;
|
||||
char *backing_file = NULL;
|
||||
char *buf = NULL;
|
||||
BDRVSheepdogState *s;
|
||||
char tag[SD_MAX_VDI_TAG_LEN];
|
||||
uint32_t snapid;
|
||||
@ -1694,33 +1695,27 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
s->inode.vdi_size = options->value.n;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
|
||||
backing_file = options->value.s;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
|
||||
if (!options->value.s || !strcmp(options->value.s, "off")) {
|
||||
prealloc = false;
|
||||
} else if (!strcmp(options->value.s, "full")) {
|
||||
prealloc = true;
|
||||
} else {
|
||||
error_setg(errp, "Invalid preallocation mode: '%s'",
|
||||
options->value.s);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_REDUNDANCY)) {
|
||||
if (options->value.s) {
|
||||
ret = parse_redundancy(s, options->value.s);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Invalid redundancy mode: '%s'",
|
||||
options->value.s);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
s->inode.vdi_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
if (!buf || !strcmp(buf, "off")) {
|
||||
prealloc = false;
|
||||
} else if (!strcmp(buf, "full")) {
|
||||
prealloc = true;
|
||||
} else {
|
||||
error_setg(errp, "Invalid preallocation mode: '%s'", buf);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_free(buf);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
|
||||
if (buf) {
|
||||
ret = parse_redundancy(s, buf);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Invalid redundancy mode: '%s'", buf);
|
||||
goto out;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
|
||||
if (s->inode.vdi_size > SD_MAX_VDI_SIZE) {
|
||||
@ -1770,6 +1765,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
ret = sd_prealloc(filename, errp);
|
||||
}
|
||||
out:
|
||||
g_free(backing_file);
|
||||
g_free(buf);
|
||||
g_free(s);
|
||||
return ret;
|
||||
}
|
||||
@ -2571,28 +2568,32 @@ static int64_t sd_get_allocated_file_size(BlockDriverState *bs)
|
||||
return size;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter sd_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off, full)"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_REDUNDANCY,
|
||||
.type = OPT_STRING,
|
||||
.help = "Redundancy of the image"
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList sd_create_opts = {
|
||||
.name = "sheepdog-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(sd_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off, full)"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_REDUNDANCY,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Redundancy of the image"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_sheepdog = {
|
||||
@ -2625,7 +2626,7 @@ static BlockDriver bdrv_sheepdog = {
|
||||
.bdrv_detach_aio_context = sd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = sd_attach_aio_context,
|
||||
|
||||
.create_options = sd_create_options,
|
||||
.create_opts = &sd_create_opts,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_sheepdog_tcp = {
|
||||
@ -2658,7 +2659,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
|
||||
.bdrv_detach_aio_context = sd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = sd_attach_aio_context,
|
||||
|
||||
.create_options = sd_create_options,
|
||||
.create_opts = &sd_create_opts,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_sheepdog_unix = {
|
||||
@ -2691,7 +2692,7 @@ static BlockDriver bdrv_sheepdog_unix = {
|
||||
.bdrv_detach_aio_context = sd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = sd_attach_aio_context,
|
||||
|
||||
.create_options = sd_create_options,
|
||||
.create_opts = &sd_create_opts,
|
||||
};
|
||||
|
||||
static void bdrv_sheepdog_init(void)
|
||||
|
30
block/ssh.c
30
block/ssh.c
@ -675,17 +675,20 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter ssh_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList ssh_create_opts = {
|
||||
.name = "ssh-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(ssh_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static int ssh_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int ssh_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int r, ret;
|
||||
int64_t total_size = 0;
|
||||
@ -697,12 +700,7 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options,
|
||||
ssh_state_init(&s);
|
||||
|
||||
/* Get desired file size. */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
total_size = options->value.n;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
DPRINTF("total_size=%" PRIi64, total_size);
|
||||
|
||||
uri_options = qdict_new();
|
||||
@ -1084,7 +1082,7 @@ static BlockDriver bdrv_ssh = {
|
||||
.bdrv_co_writev = ssh_co_writev,
|
||||
.bdrv_getlength = ssh_getlength,
|
||||
.bdrv_co_flush_to_disk = ssh_co_flush,
|
||||
.create_options = ssh_create_options,
|
||||
.create_opts = &ssh_create_opts,
|
||||
};
|
||||
|
||||
static void bdrv_ssh_init(void)
|
||||
|
71
block/vdi.c
71
block/vdi.c
@ -672,8 +672,7 @@ static int vdi_co_write(BlockDriverState *bs,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
int result = 0;
|
||||
@ -688,25 +687,18 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
||||
logout("\n");
|
||||
|
||||
/* Read out options. */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
bytes = options->value.n;
|
||||
bytes = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
#if defined(CONFIG_VDI_BLOCK_SIZE)
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
|
||||
if (options->value.n) {
|
||||
/* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */
|
||||
block_size = options->value.n;
|
||||
}
|
||||
/* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */
|
||||
block_size = qemu_opt_get_size_del(opts,
|
||||
BLOCK_OPT_CLUSTER_SIZE,
|
||||
DEFAULT_CLUSTER_SIZE);
|
||||
#endif
|
||||
#if defined(CONFIG_VDI_STATIC_IMAGE)
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_STATIC)) {
|
||||
if (options->value.n) {
|
||||
image_type = VDI_TYPE_STATIC;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
options++;
|
||||
if (qemu_opt_get_bool_del(opts, BLOCK_OPT_STATIC, false)) {
|
||||
image_type = VDI_TYPE_STATIC;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bytes > VDI_DISK_SIZE_MAX) {
|
||||
result = -ENOTSUP;
|
||||
@ -801,29 +793,34 @@ static void vdi_close(BlockDriverState *bs)
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static QEMUOptionParameter vdi_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
static QemuOptsList vdi_create_opts = {
|
||||
.name = "vdi-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(vdi_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
#if defined(CONFIG_VDI_BLOCK_SIZE)
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "VDI cluster (block) size",
|
||||
.value = { .n = DEFAULT_CLUSTER_SIZE },
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "VDI cluster (block) size",
|
||||
.def_value_str = stringify(DEFAULT_CLUSTER_SIZE)
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_VDI_STATIC_IMAGE)
|
||||
{
|
||||
.name = BLOCK_OPT_STATIC,
|
||||
.type = OPT_FLAG,
|
||||
.help = "VDI static (pre-allocated) image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_STATIC,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "VDI static (pre-allocated) image",
|
||||
.def_value_str = "off"
|
||||
},
|
||||
#endif
|
||||
/* TODO: An additional option to set UUID values might be useful. */
|
||||
{ NULL }
|
||||
/* TODO: An additional option to set UUID values might be useful. */
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_vdi = {
|
||||
@ -845,7 +842,7 @@ static BlockDriver bdrv_vdi = {
|
||||
|
||||
.bdrv_get_info = vdi_get_info,
|
||||
|
||||
.create_options = vdi_create_options,
|
||||
.create_opts = &vdi_create_opts,
|
||||
.bdrv_check = vdi_check,
|
||||
};
|
||||
|
||||
|
97
block/vhdx.c
97
block/vhdx.c
@ -1723,8 +1723,7 @@ exit:
|
||||
* .---- ~ ----------- ~ ------------ ~ ---------------- ~ -----------.
|
||||
* 1MB
|
||||
*/
|
||||
static int vhdx_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
uint64_t image_size = (uint64_t) 2 * GiB;
|
||||
@ -1737,24 +1736,15 @@ static int vhdx_create(const char *filename, QEMUOptionParameter *options,
|
||||
gunichar2 *creator = NULL;
|
||||
glong creator_items;
|
||||
BlockDriverState *bs;
|
||||
const char *type = NULL;
|
||||
char *type = NULL;
|
||||
VHDXImageType image_type;
|
||||
Error *local_err = NULL;
|
||||
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
image_size = options->value.n;
|
||||
} else if (!strcmp(options->name, VHDX_BLOCK_OPT_LOG_SIZE)) {
|
||||
log_size = options->value.n;
|
||||
} else if (!strcmp(options->name, VHDX_BLOCK_OPT_BLOCK_SIZE)) {
|
||||
block_size = options->value.n;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
|
||||
type = options->value.s;
|
||||
} else if (!strcmp(options->name, VHDX_BLOCK_OPT_ZERO)) {
|
||||
use_zero_blocks = options->value.n != 0;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
image_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
log_size = qemu_opt_get_size_del(opts, VHDX_BLOCK_OPT_LOG_SIZE, 0);
|
||||
block_size = qemu_opt_get_size_del(opts, VHDX_BLOCK_OPT_BLOCK_SIZE, 0);
|
||||
type = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
|
||||
use_zero_blocks = qemu_opt_get_bool_del(opts, VHDX_BLOCK_OPT_ZERO, false);
|
||||
|
||||
if (image_size > VHDX_MAX_IMAGE_SIZE) {
|
||||
error_setg_errno(errp, EINVAL, "Image size too large; max of 64TB");
|
||||
@ -1763,7 +1753,7 @@ static int vhdx_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
|
||||
if (type == NULL) {
|
||||
type = "dynamic";
|
||||
type = g_strdup("dynamic");
|
||||
}
|
||||
|
||||
if (!strcmp(type, "dynamic")) {
|
||||
@ -1803,7 +1793,7 @@ static int vhdx_create(const char *filename, QEMUOptionParameter *options,
|
||||
block_size = block_size > VHDX_BLOCK_SIZE_MAX ? VHDX_BLOCK_SIZE_MAX :
|
||||
block_size;
|
||||
|
||||
ret = bdrv_create_file(filename, options, &local_err);
|
||||
ret = bdrv_create_file(filename, opts, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
goto exit;
|
||||
@ -1863,6 +1853,7 @@ static int vhdx_create(const char *filename, QEMUOptionParameter *options,
|
||||
delete_and_exit:
|
||||
bdrv_unref(bs);
|
||||
exit:
|
||||
g_free(type);
|
||||
g_free(creator);
|
||||
return ret;
|
||||
}
|
||||
@ -1885,37 +1876,41 @@ static int vhdx_check(BlockDriverState *bs, BdrvCheckResult *result,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter vhdx_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size; max of 64TB."
|
||||
},
|
||||
{
|
||||
.name = VHDX_BLOCK_OPT_LOG_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.value.n = 1 * MiB,
|
||||
.help = "Log size; min 1MB."
|
||||
},
|
||||
{
|
||||
.name = VHDX_BLOCK_OPT_BLOCK_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.value.n = 0,
|
||||
.help = "Block Size; min 1MB, max 256MB. " \
|
||||
"0 means auto-calculate based on image size."
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_SUBFMT,
|
||||
.type = OPT_STRING,
|
||||
.help = "VHDX format type, can be either 'dynamic' or 'fixed'. "\
|
||||
"Default is 'dynamic'."
|
||||
},
|
||||
{
|
||||
.name = VHDX_BLOCK_OPT_ZERO,
|
||||
.type = OPT_FLAG,
|
||||
.help = "Force use of payload blocks of type 'ZERO'. Non-standard."
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList vhdx_create_opts = {
|
||||
.name = "vhdx-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(vhdx_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size; max of 64TB."
|
||||
},
|
||||
{
|
||||
.name = VHDX_BLOCK_OPT_LOG_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.def_value_str = stringify(DEFAULT_LOG_SIZE),
|
||||
.help = "Log size; min 1MB."
|
||||
},
|
||||
{
|
||||
.name = VHDX_BLOCK_OPT_BLOCK_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.def_value_str = stringify(0),
|
||||
.help = "Block Size; min 1MB, max 256MB. " \
|
||||
"0 means auto-calculate based on image size."
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_SUBFMT,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "VHDX format type, can be either 'dynamic' or 'fixed'. "\
|
||||
"Default is 'dynamic'."
|
||||
},
|
||||
{
|
||||
.name = VHDX_BLOCK_OPT_ZERO,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Force use of payload blocks of type 'ZERO'. Non-standard."
|
||||
},
|
||||
{ NULL }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_vhdx = {
|
||||
@ -1931,7 +1926,7 @@ static BlockDriver bdrv_vhdx = {
|
||||
.bdrv_get_info = vhdx_get_info,
|
||||
.bdrv_check = vhdx_check,
|
||||
|
||||
.create_options = vhdx_create_options,
|
||||
.create_opts = &vhdx_create_opts,
|
||||
};
|
||||
|
||||
static void bdrv_vhdx_init(void)
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define GiB (MiB * 1024)
|
||||
#define TiB ((uint64_t) GiB * 1024)
|
||||
|
||||
#define DEFAULT_LOG_SIZE 1048576 /* 1MiB */
|
||||
/* Structures and fields present in the VHDX file */
|
||||
|
||||
/* The header section has the following blocks,
|
||||
|
121
block/vmdk.c
121
block/vmdk.c
@ -1695,17 +1695,16 @@ static int filename_decompose(const char *filename, char *path, char *prefix,
|
||||
return VMDK_OK;
|
||||
}
|
||||
|
||||
static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int idx = 0;
|
||||
BlockDriverState *new_bs = NULL;
|
||||
Error *local_err = NULL;
|
||||
char *desc = NULL;
|
||||
int64_t total_size = 0, filesize;
|
||||
const char *adapter_type = NULL;
|
||||
const char *backing_file = NULL;
|
||||
const char *fmt = NULL;
|
||||
char *adapter_type = NULL;
|
||||
char *backing_file = NULL;
|
||||
char *fmt = NULL;
|
||||
int flags = 0;
|
||||
int ret = 0;
|
||||
bool flat, split, compress;
|
||||
@ -1745,24 +1744,19 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
goto exit;
|
||||
}
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||
total_size = options->value.n;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_ADAPTER_TYPE)) {
|
||||
adapter_type = options->value.s;
|
||||
} 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;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
|
||||
fmt = options->value.s;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_ZEROED_GRAIN)) {
|
||||
zeroed_grain |= options->value.n;
|
||||
}
|
||||
options++;
|
||||
total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
adapter_type = qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE);
|
||||
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
|
||||
if (qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false)) {
|
||||
flags |= BLOCK_FLAG_COMPAT6;
|
||||
}
|
||||
fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
|
||||
if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false)) {
|
||||
zeroed_grain = true;
|
||||
}
|
||||
|
||||
if (!adapter_type) {
|
||||
adapter_type = "ide";
|
||||
adapter_type = g_strdup("ide");
|
||||
} else if (strcmp(adapter_type, "ide") &&
|
||||
strcmp(adapter_type, "buslogic") &&
|
||||
strcmp(adapter_type, "lsilogic") &&
|
||||
@ -1778,7 +1772,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
if (!fmt) {
|
||||
/* Default format to monolithicSparse */
|
||||
fmt = "monolithicSparse";
|
||||
fmt = g_strdup("monolithicSparse");
|
||||
} else if (strcmp(fmt, "monolithicFlat") &&
|
||||
strcmp(fmt, "monolithicSparse") &&
|
||||
strcmp(fmt, "twoGbMaxExtentSparse") &&
|
||||
@ -1879,7 +1873,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
if (!split && !flat) {
|
||||
desc_offset = 0x200;
|
||||
} else {
|
||||
ret = bdrv_create_file(filename, options, &local_err);
|
||||
ret = bdrv_create_file(filename, opts, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
goto exit;
|
||||
@ -1909,6 +1903,9 @@ exit:
|
||||
if (new_bs) {
|
||||
bdrv_unref(new_bs);
|
||||
}
|
||||
g_free(adapter_type);
|
||||
g_free(backing_file);
|
||||
g_free(fmt);
|
||||
g_free(desc);
|
||||
g_string_free(ext_desc_lines, true);
|
||||
return ret;
|
||||
@ -2117,41 +2114,47 @@ static void vmdk_attach_aio_context(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
|
||||
static QEMUOptionParameter vmdk_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_ADAPTER_TYPE,
|
||||
.type = OPT_STRING,
|
||||
.help = "Virtual adapter type, can be one of "
|
||||
"ide (default), lsilogic, buslogic or legacyESX"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_COMPAT6,
|
||||
.type = OPT_FLAG,
|
||||
.help = "VMDK version 6 image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_SUBFMT,
|
||||
.type = OPT_STRING,
|
||||
.help =
|
||||
"VMDK flat extent format, can be one of "
|
||||
"{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_ZEROED_GRAIN,
|
||||
.type = OPT_FLAG,
|
||||
.help = "Enable efficient zero writes using the zeroed-grain GTE feature"
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList vmdk_create_opts = {
|
||||
.name = "vmdk-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_ADAPTER_TYPE,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Virtual adapter type, can be one of "
|
||||
"ide (default), lsilogic, buslogic or legacyESX"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_BACKING_FILE,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_COMPAT6,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "VMDK version 6 image",
|
||||
.def_value_str = "off"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_SUBFMT,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help =
|
||||
"VMDK flat extent format, can be one of "
|
||||
"{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_ZEROED_GRAIN,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Enable efficient zero writes "
|
||||
"using the zeroed-grain GTE feature"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_vmdk = {
|
||||
@ -2177,7 +2180,7 @@ static BlockDriver bdrv_vmdk = {
|
||||
.bdrv_detach_aio_context = vmdk_detach_aio_context,
|
||||
.bdrv_attach_aio_context = vmdk_attach_aio_context,
|
||||
|
||||
.create_options = vmdk_create_options,
|
||||
.create_opts = &vmdk_create_opts,
|
||||
};
|
||||
|
||||
static void bdrv_vmdk_init(void)
|
||||
|
60
block/vpc.c
60
block/vpc.c
@ -738,12 +738,11 @@ static int create_fixed_disk(int fd, uint8_t *buf, int64_t total_size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vpc_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
VHDFooter *footer = (VHDFooter *) buf;
|
||||
QEMUOptionParameter *disk_type_param;
|
||||
char *disk_type_param;
|
||||
int fd, i;
|
||||
uint16_t cyls = 0;
|
||||
uint8_t heads = 0;
|
||||
@ -754,16 +753,16 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options,
|
||||
int ret = -EIO;
|
||||
|
||||
/* Read out options */
|
||||
total_size = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n;
|
||||
|
||||
disk_type_param = get_option_parameter(options, BLOCK_OPT_SUBFMT);
|
||||
if (disk_type_param && disk_type_param->value.s) {
|
||||
if (!strcmp(disk_type_param->value.s, "dynamic")) {
|
||||
total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
|
||||
disk_type_param = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
|
||||
if (disk_type_param) {
|
||||
if (!strcmp(disk_type_param, "dynamic")) {
|
||||
disk_type = VHD_DYNAMIC;
|
||||
} else if (!strcmp(disk_type_param->value.s, "fixed")) {
|
||||
} else if (!strcmp(disk_type_param, "fixed")) {
|
||||
disk_type = VHD_FIXED;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
disk_type = VHD_DYNAMIC;
|
||||
@ -772,7 +771,8 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options,
|
||||
/* Create the file */
|
||||
fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
|
||||
if (fd < 0) {
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -837,8 +837,10 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options,
|
||||
ret = create_fixed_disk(fd, buf, total_size);
|
||||
}
|
||||
|
||||
fail:
|
||||
fail:
|
||||
qemu_close(fd);
|
||||
out:
|
||||
g_free(disk_type_param);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -866,20 +868,24 @@ static void vpc_close(BlockDriverState *bs)
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static QEMUOptionParameter vpc_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_SUBFMT,
|
||||
.type = OPT_STRING,
|
||||
.help =
|
||||
"Type of virtual hard disk format. Supported formats are "
|
||||
"{dynamic (default) | fixed} "
|
||||
},
|
||||
{ NULL }
|
||||
static QemuOptsList vpc_create_opts = {
|
||||
.name = "vpc-create-opts",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(vpc_create_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Virtual disk size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_SUBFMT,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help =
|
||||
"Type of virtual hard disk format. Supported formats are "
|
||||
"{dynamic (default) | fixed} "
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_vpc = {
|
||||
@ -897,7 +903,7 @@ static BlockDriver bdrv_vpc = {
|
||||
|
||||
.bdrv_get_info = vpc_get_info,
|
||||
|
||||
.create_options = vpc_create_options,
|
||||
.create_opts = &vpc_create_opts,
|
||||
.bdrv_has_zero_init = vpc_has_zero_init,
|
||||
};
|
||||
|
||||
|
@ -2910,8 +2910,8 @@ static BlockDriver vvfat_write_target = {
|
||||
|
||||
static int enable_write_target(BDRVVVFATState *s, Error **errp)
|
||||
{
|
||||
BlockDriver *bdrv_qcow;
|
||||
QEMUOptionParameter *options;
|
||||
BlockDriver *bdrv_qcow = NULL;
|
||||
QemuOpts *opts = NULL;
|
||||
int ret;
|
||||
int size = sector2cluster(s, s->sector_count);
|
||||
s->used_clusters = calloc(size, 1);
|
||||
@ -2926,12 +2926,12 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
|
||||
}
|
||||
|
||||
bdrv_qcow = bdrv_find_format("qcow");
|
||||
options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
|
||||
set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
|
||||
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
|
||||
opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
|
||||
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512);
|
||||
qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:");
|
||||
|
||||
ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, errp);
|
||||
free_option_parameters(options);
|
||||
ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
|
||||
qemu_opts_del(opts);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
48
blockdev.c
48
blockdev.c
@ -106,7 +106,7 @@ void blockdev_auto_del(BlockDriverState *bs)
|
||||
DriveInfo *dinfo = drive_get_by_blockdev(bs);
|
||||
|
||||
if (dinfo && dinfo->auto_del) {
|
||||
drive_put_ref(dinfo);
|
||||
drive_del(dinfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ static void bdrv_format_print(void *opaque, const char *name)
|
||||
error_printf(" %s", name);
|
||||
}
|
||||
|
||||
static void drive_uninit(DriveInfo *dinfo)
|
||||
void drive_del(DriveInfo *dinfo)
|
||||
{
|
||||
if (dinfo->opts) {
|
||||
qemu_opts_del(dinfo->opts);
|
||||
@ -226,19 +226,6 @@ static void drive_uninit(DriveInfo *dinfo)
|
||||
g_free(dinfo);
|
||||
}
|
||||
|
||||
void drive_put_ref(DriveInfo *dinfo)
|
||||
{
|
||||
assert(dinfo->refcount);
|
||||
if (--dinfo->refcount == 0) {
|
||||
drive_uninit(dinfo);
|
||||
}
|
||||
}
|
||||
|
||||
void drive_get_ref(DriveInfo *dinfo)
|
||||
{
|
||||
dinfo->refcount++;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
QEMUBH *bh;
|
||||
BlockDriverState *bs;
|
||||
@ -329,7 +316,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
||||
Error **errp)
|
||||
{
|
||||
const char *buf;
|
||||
const char *serial;
|
||||
int ro = 0;
|
||||
int bdrv_flags = 0;
|
||||
int on_read_error, on_write_error;
|
||||
@ -371,8 +357,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
||||
ro = qemu_opt_get_bool(opts, "read-only", 0);
|
||||
copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
|
||||
|
||||
serial = qemu_opt_get(opts, "serial");
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
|
||||
if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) {
|
||||
error_setg(errp, "invalid discard option");
|
||||
@ -500,10 +484,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
||||
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
|
||||
dinfo->bdrv->read_only = ro;
|
||||
dinfo->bdrv->detect_zeroes = detect_zeroes;
|
||||
dinfo->refcount = 1;
|
||||
if (serial != NULL) {
|
||||
dinfo->serial = g_strdup(serial);
|
||||
}
|
||||
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
|
||||
|
||||
bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
|
||||
@ -629,6 +609,10 @@ QemuOptsList qemu_legacy_drive_opts = {
|
||||
.name = "addr",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "pci address (virtio only)",
|
||||
},{
|
||||
.name = "serial",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "disk serial number",
|
||||
},{
|
||||
.name = "file",
|
||||
.type = QEMU_OPT_STRING,
|
||||
@ -658,7 +642,7 @@ QemuOptsList qemu_legacy_drive_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
{
|
||||
const char *value;
|
||||
DriveInfo *dinfo = NULL;
|
||||
@ -672,6 +656,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
const char *werror, *rerror;
|
||||
bool read_only = false;
|
||||
bool copy_on_read;
|
||||
const char *serial;
|
||||
const char *filename;
|
||||
Error *local_err = NULL;
|
||||
|
||||
@ -875,6 +860,9 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Serial number */
|
||||
serial = qemu_opt_get(legacy_opts, "serial");
|
||||
|
||||
/* no id supplied -> create one */
|
||||
if (qemu_opts_id(all_opts) == NULL) {
|
||||
char *new_id;
|
||||
@ -965,6 +953,8 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
dinfo->unit = unit_id;
|
||||
dinfo->devaddr = devaddr;
|
||||
|
||||
dinfo->serial = g_strdup(serial);
|
||||
|
||||
switch(type) {
|
||||
case IF_IDE:
|
||||
case IF_SCSI:
|
||||
@ -1797,7 +1787,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
|
||||
BLOCKDEV_ON_ERROR_REPORT);
|
||||
} else {
|
||||
drive_uninit(drive_get_by_blockdev(bs));
|
||||
drive_del(drive_get_by_blockdev(bs));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2340,9 +2330,9 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* TODO Sort it out in raw-posix and drive_init: Reject aio=native with
|
||||
/* TODO Sort it out in raw-posix and drive_new(): Reject aio=native with
|
||||
* cache.direct=false instead of silently switching to aio=threads, except
|
||||
* if called from drive_init.
|
||||
* when called from drive_new().
|
||||
*
|
||||
* For now, simply forbidding the combination for all drivers will do. */
|
||||
if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
|
||||
@ -2374,7 +2364,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||
}
|
||||
|
||||
if (bdrv_key_required(dinfo->bdrv)) {
|
||||
drive_uninit(dinfo);
|
||||
drive_del(dinfo);
|
||||
error_setg(errp, "blockdev-add doesn't support encrypted devices");
|
||||
goto fail;
|
||||
}
|
||||
@ -2437,10 +2427,6 @@ QemuOptsList qemu_common_drive_opts = {
|
||||
.name = "format",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "disk format (raw, qcow2, ...)",
|
||||
},{
|
||||
.name = "serial",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "disk serial number",
|
||||
},{
|
||||
.name = "rerror",
|
||||
.type = QEMU_OPT_STRING,
|
||||
|
39
configure
vendored
39
configure
vendored
@ -311,8 +311,8 @@ libusb=""
|
||||
usb_redir=""
|
||||
glx=""
|
||||
zlib="yes"
|
||||
lzo="no"
|
||||
snappy="no"
|
||||
lzo=""
|
||||
snappy=""
|
||||
guest_agent=""
|
||||
guest_agent_with_vss="no"
|
||||
vss_win32_sdk=""
|
||||
@ -333,7 +333,7 @@ vte=""
|
||||
tpm="no"
|
||||
libssh2=""
|
||||
vhdx=""
|
||||
quorum="no"
|
||||
quorum=""
|
||||
|
||||
# parse CC options first
|
||||
for opt do
|
||||
@ -1050,8 +1050,12 @@ for opt do
|
||||
;;
|
||||
--disable-zlib-test) zlib="no"
|
||||
;;
|
||||
--disable-lzo) lzo="no"
|
||||
;;
|
||||
--enable-lzo) lzo="yes"
|
||||
;;
|
||||
--disable-snappy) snappy="no"
|
||||
;;
|
||||
--enable-snappy) snappy="yes"
|
||||
;;
|
||||
--enable-guest-agent) guest_agent="yes"
|
||||
@ -1749,13 +1753,14 @@ if test "$lzo" != "no" ; then
|
||||
int main(void) { lzo_version(); return 0; }
|
||||
EOF
|
||||
if compile_prog "" "-llzo2" ; then
|
||||
:
|
||||
libs_softmmu="$libs_softmmu -llzo2"
|
||||
lzo="yes"
|
||||
else
|
||||
error_exit "lzo check failed" \
|
||||
"Make sure to have the lzo libs and headers installed."
|
||||
if test "$lzo" = "yes"; then
|
||||
feature_not_found "liblzo2" "Install liblzo2 devel"
|
||||
fi
|
||||
lzo="no"
|
||||
fi
|
||||
|
||||
libs_softmmu="$libs_softmmu -llzo2"
|
||||
fi
|
||||
|
||||
##########################################
|
||||
@ -1767,13 +1772,14 @@ if test "$snappy" != "no" ; then
|
||||
int main(void) { snappy_max_compressed_length(4096); return 0; }
|
||||
EOF
|
||||
if compile_prog "" "-lsnappy" ; then
|
||||
:
|
||||
libs_softmmu="$libs_softmmu -lsnappy"
|
||||
snappy="yes"
|
||||
else
|
||||
error_exit "snappy check failed" \
|
||||
"Make sure to have the snappy libs and headers installed."
|
||||
if test "$snappy" = "yes"; then
|
||||
feature_not_found "libsnappy" "Install libsnappy devel"
|
||||
fi
|
||||
snappy="no"
|
||||
fi
|
||||
|
||||
libs_softmmu="$libs_softmmu -lsnappy"
|
||||
fi
|
||||
|
||||
##########################################
|
||||
@ -2219,9 +2225,12 @@ if compile_prog "$quorum_tls_cflags" "$quorum_tls_libs" ; then
|
||||
libs_softmmu="$quorum_tls_libs $libs_softmmu"
|
||||
libs_tools="$quorum_tls_libs $libs_softmmu"
|
||||
QEMU_CFLAGS="$QEMU_CFLAGS $quorum_tls_cflags"
|
||||
quorum="yes"
|
||||
else
|
||||
echo "gnutls > 2.10.0 required to compile Quorum"
|
||||
exit 1
|
||||
if test "$quorum" = "yes"; then
|
||||
feature_not_found "gnutls" "gnutls > 2.10.0 required to compile Quorum"
|
||||
fi
|
||||
quorum="no"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -40,7 +40,7 @@ DriveInfo *add_init_drive(const char *optstr)
|
||||
return NULL;
|
||||
|
||||
mc = MACHINE_GET_CLASS(current_machine);
|
||||
dinfo = drive_init(opts, mc->block_default_type);
|
||||
dinfo = drive_new(opts, mc->block_default_type);
|
||||
if (!dinfo) {
|
||||
qemu_opts_del(opts);
|
||||
return NULL;
|
||||
@ -76,6 +76,6 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
|
||||
|
||||
err:
|
||||
if (dinfo) {
|
||||
drive_put_ref(dinfo);
|
||||
drive_del(dinfo);
|
||||
}
|
||||
}
|
||||
|
@ -335,9 +335,7 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
|
||||
dp, 1) < 0;
|
||||
}
|
||||
}
|
||||
if (dp) {
|
||||
g_free(dp);
|
||||
}
|
||||
g_free(dp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
|
||||
}
|
||||
bdrv_close(di->bdrv);
|
||||
pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
|
||||
drive_put_ref(di);
|
||||
drive_del(di);
|
||||
}
|
||||
}
|
||||
qdev_reset_all(DEVICE(dev));
|
||||
|
@ -691,7 +691,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
|
||||
qemu_opt_set(opts, "if", "none");
|
||||
|
||||
/* create host drive */
|
||||
dinfo = drive_init(opts, 0);
|
||||
dinfo = drive_new(opts, 0);
|
||||
if (!dinfo) {
|
||||
qemu_opts_del(opts);
|
||||
return NULL;
|
||||
|
@ -204,9 +204,8 @@ BlockDriver *bdrv_find_format(const char *format_name);
|
||||
BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
|
||||
bool readonly);
|
||||
int bdrv_create(BlockDriver *drv, const char* filename,
|
||||
QEMUOptionParameter *options, Error **errp);
|
||||
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
|
||||
Error **errp);
|
||||
QemuOpts *opts, Error **errp);
|
||||
int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
|
||||
BlockDriverState *bdrv_new(const char *device_name, Error **errp);
|
||||
void bdrv_make_anon(BlockDriverState *bs);
|
||||
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
|
||||
@ -312,7 +311,7 @@ typedef enum {
|
||||
|
||||
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
|
||||
|
||||
int bdrv_amend_options(BlockDriverState *bs_new, QEMUOptionParameter *options);
|
||||
int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts);
|
||||
|
||||
/* external snapshots */
|
||||
bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
|
||||
|
@ -116,8 +116,7 @@ struct BlockDriver {
|
||||
const uint8_t *buf, int nb_sectors);
|
||||
void (*bdrv_close)(BlockDriverState *bs);
|
||||
void (*bdrv_rebind)(BlockDriverState *bs);
|
||||
int (*bdrv_create)(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp);
|
||||
int (*bdrv_create)(const char *filename, QemuOpts *opts, Error **errp);
|
||||
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
|
||||
int (*bdrv_make_empty)(BlockDriverState *bs);
|
||||
/* aio */
|
||||
@ -216,8 +215,7 @@ struct BlockDriver {
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
|
||||
/* List of options for creating images, terminated by name == NULL */
|
||||
QEMUOptionParameter *create_options;
|
||||
|
||||
QemuOptsList *create_opts;
|
||||
|
||||
/*
|
||||
* Returns 0 for completed check, -errno for internal errors.
|
||||
@ -226,8 +224,7 @@ struct BlockDriver {
|
||||
int (*bdrv_check)(BlockDriverState* bs, BdrvCheckResult *result,
|
||||
BdrvCheckMode fix);
|
||||
|
||||
int (*bdrv_amend_options)(BlockDriverState *bs,
|
||||
QEMUOptionParameter *options);
|
||||
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts);
|
||||
|
||||
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
|
||||
|
||||
|
@ -31,25 +31,6 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.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;
|
||||
const char *help;
|
||||
bool assigned;
|
||||
} 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);
|
||||
int get_next_param_value(char *buf, int buf_size,
|
||||
@ -58,32 +39,11 @@ int get_param_value(char *buf, int buf_size,
|
||||
const char *tag, const char *str);
|
||||
|
||||
|
||||
/*
|
||||
* The following functions take a parameter list as input. This is a pointer to
|
||||
* the first element of a QEMUOptionParameter array which is terminated by an
|
||||
* entry with entry->name == NULL.
|
||||
*/
|
||||
|
||||
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 *append_option_parameters(QEMUOptionParameter *dest,
|
||||
QEMUOptionParameter *list);
|
||||
QEMUOptionParameter *parse_option_parameters(const char *param,
|
||||
QEMUOptionParameter *list, QEMUOptionParameter *dest);
|
||||
void parse_option_size(const char *name, const char *value,
|
||||
uint64_t *ret, Error **errp);
|
||||
void free_option_parameters(QEMUOptionParameter *list);
|
||||
void print_option_parameters(QEMUOptionParameter *list);
|
||||
void print_option_help(QEMUOptionParameter *list);
|
||||
bool has_help_option(const char *param);
|
||||
bool is_valid_option_list(const char *param);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
typedef struct QemuOpt QemuOpt;
|
||||
typedef struct QemuOpts QemuOpts;
|
||||
typedef struct QemuOptsList QemuOptsList;
|
||||
@ -99,6 +59,7 @@ typedef struct QemuOptDesc {
|
||||
const char *name;
|
||||
enum QemuOptType type;
|
||||
const char *help;
|
||||
const char *def_value_str;
|
||||
} QemuOptDesc;
|
||||
|
||||
struct QemuOptsList {
|
||||
@ -110,6 +71,7 @@ struct QemuOptsList {
|
||||
};
|
||||
|
||||
const char *qemu_opt_get(QemuOpts *opts, const char *name);
|
||||
char *qemu_opt_get_del(QemuOpts *opts, const char *name);
|
||||
/**
|
||||
* qemu_opt_has_help_opt:
|
||||
* @opts: options to search for a help request
|
||||
@ -122,9 +84,15 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name);
|
||||
* Returns: true if @opts includes 'help' or equivalent.
|
||||
*/
|
||||
bool qemu_opt_has_help_opt(QemuOpts *opts);
|
||||
QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name);
|
||||
bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
|
||||
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
|
||||
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
|
||||
bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
|
||||
uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
|
||||
uint64_t defval);
|
||||
uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
|
||||
uint64_t defval);
|
||||
int qemu_opt_unset(QemuOpts *opts, const char *name);
|
||||
int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
|
||||
void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
|
||||
@ -156,8 +124,11 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
|
||||
void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp);
|
||||
|
||||
typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
|
||||
int qemu_opts_print(QemuOpts *opts, void *dummy);
|
||||
void qemu_opts_print(QemuOpts *opts);
|
||||
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
|
||||
int abort_on_failure);
|
||||
void qemu_opts_print_help(QemuOptsList *list);
|
||||
void qemu_opts_free(QemuOptsList *list);
|
||||
QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
|
||||
|
||||
#endif
|
||||
|
@ -30,8 +30,8 @@
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
struct QemuOpt {
|
||||
const char *name;
|
||||
const char *str;
|
||||
char *name;
|
||||
char *str;
|
||||
|
||||
const QemuOptDesc *desc;
|
||||
union {
|
||||
|
@ -37,27 +37,25 @@ struct DriveInfo {
|
||||
int bus;
|
||||
int unit;
|
||||
int auto_del; /* see blockdev_mark_auto_del() */
|
||||
bool enable_auto_del; /* Only for legacy drive_init() */
|
||||
bool enable_auto_del; /* Only for legacy drive_new() */
|
||||
int media_cd;
|
||||
int cyls, heads, secs, trans;
|
||||
QemuOpts *opts;
|
||||
char *serial;
|
||||
QTAILQ_ENTRY(DriveInfo) next;
|
||||
int refcount;
|
||||
};
|
||||
|
||||
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
|
||||
DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
|
||||
int drive_get_max_bus(BlockInterfaceType type);
|
||||
DriveInfo *drive_get_next(BlockInterfaceType type);
|
||||
void drive_get_ref(DriveInfo *dinfo);
|
||||
void drive_put_ref(DriveInfo *dinfo);
|
||||
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
|
||||
|
||||
QemuOpts *drive_def(const char *optstr);
|
||||
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
|
||||
const char *optstr);
|
||||
DriveInfo *drive_init(QemuOpts *arg, BlockInterfaceType block_default_type);
|
||||
DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type);
|
||||
void drive_del(DriveInfo *dinfo);
|
||||
|
||||
/* device-hotplug */
|
||||
|
||||
|
@ -2855,12 +2855,15 @@
|
||||
#
|
||||
# @help: #optional human readable text string, not suitable for parsing.
|
||||
#
|
||||
# @default: #optional default value string (since 2.1)
|
||||
#
|
||||
# Since 1.5
|
||||
##
|
||||
{ 'type': 'CommandLineParameterInfo',
|
||||
'data': { 'name': 'str',
|
||||
'type': 'CommandLineParameterType',
|
||||
'*help': 'str' } }
|
||||
'*help': 'str',
|
||||
'*default': 'str' } }
|
||||
|
||||
##
|
||||
# @CommandLineOptionInfo:
|
||||
|
@ -143,8 +143,8 @@ opts_start_struct(Visitor *v, void **obj, const char *kind,
|
||||
if (ov->opts_root->id != NULL) {
|
||||
ov->fake_id_opt = g_malloc0(sizeof *ov->fake_id_opt);
|
||||
|
||||
ov->fake_id_opt->name = "id";
|
||||
ov->fake_id_opt->str = ov->opts_root->id;
|
||||
ov->fake_id_opt->name = g_strdup("id");
|
||||
ov->fake_id_opt->str = g_strdup(ov->opts_root->id);
|
||||
opts_visitor_insert(ov->unprocessed_opts, ov->fake_id_opt);
|
||||
}
|
||||
}
|
||||
@ -177,7 +177,11 @@ opts_end_struct(Visitor *v, Error **errp)
|
||||
}
|
||||
g_hash_table_destroy(ov->unprocessed_opts);
|
||||
ov->unprocessed_opts = NULL;
|
||||
g_free(ov->fake_id_opt);
|
||||
if (ov->fake_id_opt) {
|
||||
g_free(ov->fake_id_opt->name);
|
||||
g_free(ov->fake_id_opt->str);
|
||||
g_free(ov->fake_id_opt);
|
||||
}
|
||||
ov->fake_id_opt = NULL;
|
||||
}
|
||||
|
||||
|
91
qemu-img.c
91
qemu-img.c
@ -271,7 +271,7 @@ static int read_password(char *buf, int buf_size)
|
||||
static int print_block_option_help(const char *filename, const char *fmt)
|
||||
{
|
||||
BlockDriver *drv, *proto_drv;
|
||||
QEMUOptionParameter *create_options = NULL;
|
||||
QemuOptsList *create_opts = NULL;
|
||||
|
||||
/* Find driver and parse its options */
|
||||
drv = bdrv_find_format(fmt);
|
||||
@ -280,22 +280,19 @@ 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_opts = qemu_opts_append(create_opts, drv->create_opts);
|
||||
if (filename) {
|
||||
proto_drv = bdrv_find_protocol(filename, true);
|
||||
if (!proto_drv) {
|
||||
error_report("Unknown protocol '%s'", filename);
|
||||
free_option_parameters(create_options);
|
||||
qemu_opts_free(create_opts);
|
||||
return 1;
|
||||
}
|
||||
create_options = append_option_parameters(create_options,
|
||||
proto_drv->create_options);
|
||||
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
|
||||
}
|
||||
|
||||
print_option_help(create_options);
|
||||
free_option_parameters(create_options);
|
||||
qemu_opts_print_help(create_opts);
|
||||
qemu_opts_free(create_opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -349,19 +346,19 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
|
||||
static int add_old_style_options(const char *fmt, QemuOpts *opts,
|
||||
const char *base_filename,
|
||||
const char *base_fmt)
|
||||
{
|
||||
if (base_filename) {
|
||||
if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
|
||||
if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
|
||||
error_report("Backing file not supported for file format '%s'",
|
||||
fmt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (base_fmt) {
|
||||
if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
|
||||
if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
|
||||
error_report("Backing file format not supported for file "
|
||||
"format '%s'", fmt);
|
||||
return -1;
|
||||
@ -1191,8 +1188,9 @@ static int img_convert(int argc, char **argv)
|
||||
size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE;
|
||||
const uint8_t *buf1;
|
||||
BlockDriverInfo bdi;
|
||||
QEMUOptionParameter *param = NULL, *create_options = NULL;
|
||||
QEMUOptionParameter *out_baseimg_param;
|
||||
QemuOpts *opts = NULL;
|
||||
QemuOptsList *create_opts = NULL;
|
||||
const char *out_baseimg_param;
|
||||
char *options = NULL;
|
||||
const char *snapshot_name = NULL;
|
||||
int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
|
||||
@ -1381,40 +1379,34 @@ static int img_convert(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
create_options = append_option_parameters(create_options,
|
||||
drv->create_options);
|
||||
create_options = append_option_parameters(create_options,
|
||||
proto_drv->create_options);
|
||||
create_opts = qemu_opts_append(create_opts, drv->create_opts);
|
||||
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
|
||||
|
||||
if (options) {
|
||||
param = parse_option_parameters(options, create_options, param);
|
||||
if (param == NULL) {
|
||||
error_report("Invalid options for file format '%s'.", out_fmt);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
param = parse_option_parameters("", create_options, param);
|
||||
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
|
||||
if (options && qemu_opts_do_parse(opts, options, NULL)) {
|
||||
error_report("Invalid options for file format '%s'", out_fmt);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
|
||||
ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
|
||||
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512);
|
||||
ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get backing file name if -o backing_file was used */
|
||||
out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
|
||||
out_baseimg_param = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
|
||||
if (out_baseimg_param) {
|
||||
out_baseimg = out_baseimg_param->value.s;
|
||||
out_baseimg = out_baseimg_param;
|
||||
}
|
||||
|
||||
/* Check if compression is supported */
|
||||
if (compress) {
|
||||
QEMUOptionParameter *encryption =
|
||||
get_option_parameter(param, BLOCK_OPT_ENCRYPT);
|
||||
QEMUOptionParameter *preallocation =
|
||||
get_option_parameter(param, BLOCK_OPT_PREALLOC);
|
||||
bool encryption =
|
||||
qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
|
||||
const char *preallocation =
|
||||
qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
|
||||
|
||||
if (!drv->bdrv_write_compressed) {
|
||||
error_report("Compression not supported for this file format");
|
||||
@ -1422,15 +1414,15 @@ static int img_convert(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (encryption && encryption->value.n) {
|
||||
if (encryption) {
|
||||
error_report("Compression and encryption not supported at "
|
||||
"the same time");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (preallocation && preallocation->value.s
|
||||
&& strcmp(preallocation->value.s, "off"))
|
||||
if (preallocation
|
||||
&& strcmp(preallocation, "off"))
|
||||
{
|
||||
error_report("Compression and preallocation not supported at "
|
||||
"the same time");
|
||||
@ -1441,7 +1433,7 @@ static int img_convert(int argc, char **argv)
|
||||
|
||||
if (!skip_create) {
|
||||
/* Create the new image */
|
||||
ret = bdrv_create(drv, out_filename, param, &local_err);
|
||||
ret = bdrv_create(drv, out_filename, opts, &local_err);
|
||||
if (ret < 0) {
|
||||
error_report("%s: error while converting %s: %s",
|
||||
out_filename, out_fmt, error_get_pretty(local_err));
|
||||
@ -1706,8 +1698,8 @@ out:
|
||||
qemu_progress_print(100, 0);
|
||||
}
|
||||
qemu_progress_end();
|
||||
free_option_parameters(create_options);
|
||||
free_option_parameters(param);
|
||||
qemu_opts_del(opts);
|
||||
qemu_opts_free(create_opts);
|
||||
qemu_vfree(buf);
|
||||
if (sn_opts) {
|
||||
qemu_opts_del(sn_opts);
|
||||
@ -2698,7 +2690,8 @@ static int img_amend(int argc, char **argv)
|
||||
{
|
||||
int c, ret = 0;
|
||||
char *options = NULL;
|
||||
QEMUOptionParameter *create_options = NULL, *options_param = NULL;
|
||||
QemuOptsList *create_opts = NULL;
|
||||
QemuOpts *opts = NULL;
|
||||
const char *fmt = NULL, *filename;
|
||||
bool quiet = false;
|
||||
BlockDriverState *bs = NULL;
|
||||
@ -2769,17 +2762,15 @@ static int img_amend(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
create_options = append_option_parameters(create_options,
|
||||
bs->drv->create_options);
|
||||
options_param = parse_option_parameters(options, create_options,
|
||||
options_param);
|
||||
if (options_param == NULL) {
|
||||
create_opts = qemu_opts_append(create_opts, bs->drv->create_opts);
|
||||
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
|
||||
if (options && qemu_opts_do_parse(opts, options, NULL)) {
|
||||
error_report("Invalid options for file format '%s'", fmt);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = bdrv_amend_options(bs, options_param);
|
||||
ret = bdrv_amend_options(bs, opts);
|
||||
if (ret < 0) {
|
||||
error_report("Error while amending options: %s", strerror(-ret));
|
||||
goto out;
|
||||
@ -2789,8 +2780,8 @@ out:
|
||||
if (bs) {
|
||||
bdrv_unref(bs);
|
||||
}
|
||||
free_option_parameters(create_options);
|
||||
free_option_parameters(options_param);
|
||||
qemu_opts_del(opts);
|
||||
qemu_opts_free(create_opts);
|
||||
g_free(options);
|
||||
|
||||
if (ret) {
|
||||
|
@ -2898,6 +2898,8 @@ Each array entry contains the following:
|
||||
or 'size')
|
||||
- "help": human readable description of the parameter
|
||||
(json-string, optional)
|
||||
- "default": default value string for the parameter
|
||||
(json-string, optional)
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -120,7 +120,7 @@ qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
|
||||
|
||||
qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
|
||||
qemu-img: Parameter 'size' expects a size
|
||||
qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'.
|
||||
qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'
|
||||
|
||||
== Check correct interpretation of suffixes for cluster size ==
|
||||
|
||||
|
@ -281,7 +281,7 @@ Lazy refcounts only supported with compatibility level 1.1 and above (use compat
|
||||
qemu-img: Error while amending options: Invalid argument
|
||||
Unknown compatibility level 0.42.
|
||||
qemu-img: Error while amending options: Invalid argument
|
||||
Unknown option 'foo'
|
||||
qemu-img: Invalid parameter 'foo'
|
||||
qemu-img: Invalid options for file format 'qcow2'
|
||||
Changing the cluster size is not supported.
|
||||
qemu-img: Error while amending options: Operation not supported
|
||||
|
@ -45,5 +45,5 @@ wrote 10485760/10485760 bytes at offset 0
|
||||
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
== checking that quorum is broken ==
|
||||
qemu-io: can't open device (null): Could not read image for determining its format: Input/output error
|
||||
qemu-io: can't open: Could not read image for determining its format: Input/output error
|
||||
*** done
|
||||
|
@ -82,6 +82,10 @@ static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc)
|
||||
info->has_help = true;
|
||||
info->help = g_strdup(desc[i].help);
|
||||
}
|
||||
if (desc[i].def_value_str) {
|
||||
info->has_q_default = true;
|
||||
info->q_default = g_strdup(desc[i].def_value_str);
|
||||
}
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
|
@ -123,22 +123,6 @@ int get_param_value(char *buf, int buf_size,
|
||||
return get_next_param_value(buf, buf_size, tag, &str);
|
||||
}
|
||||
|
||||
/*
|
||||
* Searches an option list for an option with the given name
|
||||
*/
|
||||
QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
|
||||
const char *name)
|
||||
{
|
||||
while (list && list->name) {
|
||||
if (!strcmp(list->name, name)) {
|
||||
return list;
|
||||
}
|
||||
list++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void parse_option_bool(const char *name, const char *value, bool *ret,
|
||||
Error **errp)
|
||||
{
|
||||
@ -173,6 +157,20 @@ static void parse_option_number(const char *name, const char *value,
|
||||
}
|
||||
}
|
||||
|
||||
static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
|
||||
const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; desc[i].name != NULL; i++) {
|
||||
if (strcmp(desc[i].name, name) == 0) {
|
||||
return &desc[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void parse_option_size(const char *name, const char *value,
|
||||
uint64_t *ret, Error **errp)
|
||||
{
|
||||
@ -212,244 +210,6 @@ void parse_option_size(const char *name, const char *value,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the value of a parameter in a given option list. The parsing of the
|
||||
* value depends on the type of option:
|
||||
*
|
||||
* OPT_FLAG (uses value.n):
|
||||
* If no value is given, the flag is set to 1.
|
||||
* Otherwise the value must be "on" (set to 1) or "off" (set to 0)
|
||||
*
|
||||
* OPT_STRING (uses value.s):
|
||||
* value is strdup()ed and assigned as option value
|
||||
*
|
||||
* OPT_SIZE (uses value.n):
|
||||
* The value is converted to an integer. Suffixes for kilobytes etc. are
|
||||
* allowed (powers of 1024).
|
||||
*
|
||||
* Returns 0 on succes, -1 in error cases
|
||||
*/
|
||||
int set_option_parameter(QEMUOptionParameter *list, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
bool flag;
|
||||
Error *local_err = NULL;
|
||||
|
||||
// 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:
|
||||
parse_option_bool(name, value, &flag, &local_err);
|
||||
if (!local_err) {
|
||||
list->value.n = flag;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_STRING:
|
||||
if (value != NULL) {
|
||||
list->value.s = g_strdup(value);
|
||||
} else {
|
||||
fprintf(stderr, "Option '%s' needs a parameter\n", name);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_SIZE:
|
||||
parse_option_size(name, value, &list->value.n, &local_err);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (local_err) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list->assigned = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the given parameter to an integer instead of a string.
|
||||
* This function cannot be used to set string options.
|
||||
*
|
||||
* Returns 0 on success, -1 in error cases
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
list->assigned = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees a option list. If it contains strings, the strings are freed as well.
|
||||
*/
|
||||
void free_option_parameters(QEMUOptionParameter *list)
|
||||
{
|
||||
QEMUOptionParameter *cur = list;
|
||||
|
||||
while (cur && cur->name) {
|
||||
if (cur->type == OPT_STRING) {
|
||||
g_free(cur->value.s);
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
|
||||
g_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 = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
|
||||
dest[num_dest_options].name = NULL;
|
||||
|
||||
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).
|
||||
*
|
||||
* list is the template option list. If dest is NULL, a new copy of list is
|
||||
* created. If list is NULL, this function fails.
|
||||
*
|
||||
* A parameter string consists of one or more parameters, separated by commas.
|
||||
* Each parameter consists of its name and possibly of a value. In the latter
|
||||
* case, the value is delimited by an = character. To specify a value which
|
||||
* contains commas, double each comma so it won't be recognized as the end of
|
||||
* the parameter.
|
||||
*
|
||||
* For more details of the parsing see above.
|
||||
*
|
||||
* Returns a pointer to the first element of dest (or the newly allocated copy)
|
||||
* or NULL in error cases
|
||||
*/
|
||||
QEMUOptionParameter *parse_option_parameters(const char *param,
|
||||
QEMUOptionParameter *list, QEMUOptionParameter *dest)
|
||||
{
|
||||
QEMUOptionParameter *allocated = NULL;
|
||||
char name[256];
|
||||
char value[256];
|
||||
char *param_delim, *value_delim;
|
||||
char next_delim;
|
||||
int i;
|
||||
|
||||
if (list == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dest == NULL) {
|
||||
dest = allocated = append_option_parameters(NULL, list);
|
||||
}
|
||||
|
||||
for (i = 0; dest[i].name; i++) {
|
||||
dest[i].assigned = false;
|
||||
}
|
||||
|
||||
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:
|
||||
// Only free the list if it was newly allocated
|
||||
free_option_parameters(allocated);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool has_help_option(const char *param)
|
||||
{
|
||||
size_t buflen = strlen(param) + 1;
|
||||
@ -499,49 +259,22 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints all options of a list that have a value to stdout
|
||||
*/
|
||||
void print_option_parameters(QEMUOptionParameter *list)
|
||||
void qemu_opts_print_help(QemuOptsList *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=(unknown type) ", list->name);
|
||||
break;
|
||||
}
|
||||
list++;
|
||||
}
|
||||
}
|
||||
QemuOptDesc *desc;
|
||||
|
||||
/*
|
||||
* Prints an overview of all available options
|
||||
*/
|
||||
void print_option_help(QEMUOptionParameter *list)
|
||||
{
|
||||
assert(list);
|
||||
desc = list->desc;
|
||||
printf("Supported options:\n");
|
||||
while (list && list->name) {
|
||||
printf("%-16s %s\n", list->name,
|
||||
list->help ? list->help : "No description available");
|
||||
list++;
|
||||
while (desc && desc->name) {
|
||||
printf("%-16s %s\n", desc->name,
|
||||
desc->help ? desc->help : "No description available");
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
|
||||
QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
|
||||
{
|
||||
QemuOpt *opt;
|
||||
|
||||
@ -553,12 +286,69 @@ static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void qemu_opt_del(QemuOpt *opt)
|
||||
{
|
||||
QTAILQ_REMOVE(&opt->opts->head, opt, next);
|
||||
g_free(opt->name);
|
||||
g_free(opt->str);
|
||||
g_free(opt);
|
||||
}
|
||||
|
||||
/* qemu_opt_set allows many settings for the same option.
|
||||
* This function deletes all settings for an option.
|
||||
*/
|
||||
static void qemu_opt_del_all(QemuOpts *opts, const char *name)
|
||||
{
|
||||
QemuOpt *opt, *next_opt;
|
||||
|
||||
QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next_opt) {
|
||||
if (!strcmp(opt->name, name)) {
|
||||
qemu_opt_del(opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *qemu_opt_get(QemuOpts *opts, const char *name)
|
||||
{
|
||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||
|
||||
if (!opt) {
|
||||
const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
|
||||
if (desc && desc->def_value_str) {
|
||||
return desc->def_value_str;
|
||||
}
|
||||
}
|
||||
return opt ? opt->str : NULL;
|
||||
}
|
||||
|
||||
/* Get a known option (or its default) and remove it from the list
|
||||
* all in one action. Return a malloced string of the option value.
|
||||
* Result must be freed by caller with g_free().
|
||||
*/
|
||||
char *qemu_opt_get_del(QemuOpts *opts, const char *name)
|
||||
{
|
||||
QemuOpt *opt;
|
||||
const QemuOptDesc *desc;
|
||||
char *str = NULL;
|
||||
|
||||
if (opts == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
opt = qemu_opt_find(opts, name);
|
||||
if (!opt) {
|
||||
desc = find_desc_by_name(opts->list->desc, name);
|
||||
if (desc && desc->def_value_str) {
|
||||
str = g_strdup(desc->def_value_str);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
str = opt->str;
|
||||
opt->str = NULL;
|
||||
qemu_opt_del_all(opts, name);
|
||||
return str;
|
||||
}
|
||||
|
||||
bool qemu_opt_has_help_opt(QemuOpts *opts)
|
||||
{
|
||||
QemuOpt *opt;
|
||||
@ -571,34 +361,99 @@ bool qemu_opt_has_help_opt(QemuOpts *opts)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
|
||||
static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
|
||||
bool defval, bool del)
|
||||
{
|
||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||
bool ret = defval;
|
||||
|
||||
if (opt == NULL)
|
||||
return defval;
|
||||
if (opt == NULL) {
|
||||
const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
|
||||
if (desc && desc->def_value_str) {
|
||||
parse_option_bool(name, desc->def_value_str, &ret, &error_abort);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
|
||||
return opt->value.boolean;
|
||||
ret = opt->value.boolean;
|
||||
if (del) {
|
||||
qemu_opt_del_all(opts, name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
|
||||
{
|
||||
return qemu_opt_get_bool_helper(opts, name, defval, false);
|
||||
}
|
||||
|
||||
bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
|
||||
{
|
||||
return qemu_opt_get_bool_helper(opts, name, defval, true);
|
||||
}
|
||||
|
||||
static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
|
||||
uint64_t defval, bool del)
|
||||
{
|
||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||
uint64_t ret = defval;
|
||||
|
||||
if (opt == NULL) {
|
||||
const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
|
||||
if (desc && desc->def_value_str) {
|
||||
parse_option_number(name, desc->def_value_str, &ret, &error_abort);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
|
||||
ret = opt->value.uint;
|
||||
if (del) {
|
||||
qemu_opt_del_all(opts, name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
|
||||
{
|
||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||
return qemu_opt_get_number_helper(opts, name, defval, false);
|
||||
}
|
||||
|
||||
if (opt == NULL)
|
||||
return defval;
|
||||
assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
|
||||
return opt->value.uint;
|
||||
uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
|
||||
uint64_t defval)
|
||||
{
|
||||
return qemu_opt_get_number_helper(opts, name, defval, true);
|
||||
}
|
||||
|
||||
static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
|
||||
uint64_t defval, bool del)
|
||||
{
|
||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||
uint64_t ret = defval;
|
||||
|
||||
if (opt == NULL) {
|
||||
const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
|
||||
if (desc && desc->def_value_str) {
|
||||
parse_option_size(name, desc->def_value_str, &ret, &error_abort);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
|
||||
ret = opt->value.uint;
|
||||
if (del) {
|
||||
qemu_opt_del_all(opts, name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
|
||||
{
|
||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||
return qemu_opt_get_size_helper(opts, name, defval, false);
|
||||
}
|
||||
|
||||
if (opt == NULL)
|
||||
return defval;
|
||||
assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
|
||||
return opt->value.uint;
|
||||
uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
|
||||
uint64_t defval)
|
||||
{
|
||||
return qemu_opt_get_size_helper(opts, name, defval, true);
|
||||
}
|
||||
|
||||
static void qemu_opt_parse(QemuOpt *opt, Error **errp)
|
||||
@ -624,33 +479,11 @@ static void qemu_opt_parse(QemuOpt *opt, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_opt_del(QemuOpt *opt)
|
||||
{
|
||||
QTAILQ_REMOVE(&opt->opts->head, opt, next);
|
||||
g_free((/* !const */ char*)opt->name);
|
||||
g_free((/* !const */ char*)opt->str);
|
||||
g_free(opt);
|
||||
}
|
||||
|
||||
static bool opts_accepts_any(const QemuOpts *opts)
|
||||
{
|
||||
return opts->list->desc[0].name == NULL;
|
||||
}
|
||||
|
||||
static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
|
||||
const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; desc[i].name != NULL; i++) {
|
||||
if (strcmp(desc[i].name, name) == 0) {
|
||||
return &desc[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int qemu_opt_unset(QemuOpts *opts, const char *name)
|
||||
{
|
||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||
@ -884,6 +717,10 @@ void qemu_opts_del(QemuOpts *opts)
|
||||
{
|
||||
QemuOpt *opt;
|
||||
|
||||
if (opts == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
opt = QTAILQ_FIRST(&opts->head);
|
||||
if (opt == NULL)
|
||||
@ -895,17 +732,34 @@ void qemu_opts_del(QemuOpts *opts)
|
||||
g_free(opts);
|
||||
}
|
||||
|
||||
int qemu_opts_print(QemuOpts *opts, void *dummy)
|
||||
void qemu_opts_print(QemuOpts *opts)
|
||||
{
|
||||
QemuOpt *opt;
|
||||
QemuOptDesc *desc = opts->list->desc;
|
||||
|
||||
fprintf(stderr, "%s: %s:", opts->list->name,
|
||||
opts->id ? opts->id : "<noid>");
|
||||
QTAILQ_FOREACH(opt, &opts->head, next) {
|
||||
fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
|
||||
if (desc[0].name == NULL) {
|
||||
QTAILQ_FOREACH(opt, &opts->head, next) {
|
||||
printf("%s=\"%s\" ", opt->name, opt->str);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (; desc && desc->name; desc++) {
|
||||
const char *value;
|
||||
QemuOpt *opt = qemu_opt_find(opts, desc->name);
|
||||
|
||||
value = opt ? opt->str : desc->def_value_str;
|
||||
if (!value) {
|
||||
continue;
|
||||
}
|
||||
if (desc->type == QEMU_OPT_STRING) {
|
||||
printf("%s='%s' ", desc->name, value);
|
||||
} else if ((desc->type == QEMU_OPT_SIZE ||
|
||||
desc->type == QEMU_OPT_NUMBER) && opt) {
|
||||
printf("%s=%" PRId64 " ", desc->name, opt->value.uint);
|
||||
} else {
|
||||
printf("%s=%s ", desc->name, value);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opts_do_parse(QemuOpts *opts, const char *params,
|
||||
@ -1202,3 +1056,77 @@ int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
|
||||
loc_pop(&loc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static size_t count_opts_list(QemuOptsList *list)
|
||||
{
|
||||
QemuOptDesc *desc = NULL;
|
||||
size_t num_opts = 0;
|
||||
|
||||
if (!list) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
desc = list->desc;
|
||||
while (desc && desc->name) {
|
||||
num_opts++;
|
||||
desc++;
|
||||
}
|
||||
|
||||
return num_opts;
|
||||
}
|
||||
|
||||
void qemu_opts_free(QemuOptsList *list)
|
||||
{
|
||||
g_free(list);
|
||||
}
|
||||
|
||||
/* Realloc dst option list and append options from an option list (list)
|
||||
* to it. dst could be NULL or a malloced list.
|
||||
* The lifetime of dst must be shorter than the input list because the
|
||||
* QemuOptDesc->name, ->help, and ->def_value_str strings are shared.
|
||||
*/
|
||||
QemuOptsList *qemu_opts_append(QemuOptsList *dst,
|
||||
QemuOptsList *list)
|
||||
{
|
||||
size_t num_opts, num_dst_opts;
|
||||
QemuOptDesc *desc;
|
||||
bool need_init = false;
|
||||
|
||||
if (!list) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* If dst is NULL, after realloc, some area of dst should be initialized
|
||||
* before adding options to it.
|
||||
*/
|
||||
if (!dst) {
|
||||
need_init = true;
|
||||
}
|
||||
|
||||
num_opts = count_opts_list(dst);
|
||||
num_dst_opts = num_opts;
|
||||
num_opts += count_opts_list(list);
|
||||
dst = g_realloc(dst, sizeof(QemuOptsList) +
|
||||
(num_opts + 1) * sizeof(QemuOptDesc));
|
||||
if (need_init) {
|
||||
dst->name = NULL;
|
||||
dst->implied_opt_name = NULL;
|
||||
QTAILQ_INIT(&dst->head);
|
||||
dst->merge_lists = false;
|
||||
}
|
||||
dst->desc[num_dst_opts].name = NULL;
|
||||
|
||||
/* append list->desc to dst->desc */
|
||||
if (list) {
|
||||
desc = list->desc;
|
||||
while (desc && desc->name) {
|
||||
if (find_desc_by_name(dst->desc, desc->name) == NULL) {
|
||||
dst->desc[num_dst_opts++] = *desc;
|
||||
dst->desc[num_dst_opts].name = NULL;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
4
vl.c
4
vl.c
@ -1074,7 +1074,7 @@ static int drive_init_func(QemuOpts *opts, void *opaque)
|
||||
{
|
||||
BlockInterfaceType *block_default_type = opaque;
|
||||
|
||||
return drive_init(opts, *block_default_type) == NULL;
|
||||
return drive_new(opts, *block_default_type) == NULL;
|
||||
}
|
||||
|
||||
static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
|
||||
@ -1098,7 +1098,7 @@ static void default_drive(int enable, int snapshot, BlockInterfaceType type,
|
||||
if (snapshot) {
|
||||
drive_enable_snapshot(opts, NULL);
|
||||
}
|
||||
if (!drive_init(opts, type)) {
|
||||
if (!drive_new(opts, type)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user