block: Always pass driver name through options QDict

The "driver" entry in the options QDict is now only missing if we're
opening an image with format probing.

We also catch cases now where both the drv argument and a "driver"
option is specified, e.g. by specifying -drive format=qcow2,driver=raw

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Kevin Wolf 2014-05-27 10:50:29 +02:00
parent 5e5c4f63f4
commit 17b005f1d4
3 changed files with 45 additions and 37 deletions

76
block.c
View File

@ -1037,14 +1037,13 @@ static QDict *parse_json_filename(const char *filename, Error **errp)
* filename/flags pair to option QDict entries. * filename/flags pair to option QDict entries.
*/ */
static int bdrv_fill_options(QDict **options, const char **pfilename, int flags, static int bdrv_fill_options(QDict **options, const char **pfilename, int flags,
Error **errp) BlockDriver *drv, Error **errp)
{ {
const char *filename = *pfilename; const char *filename = *pfilename;
const char *drvname; const char *drvname;
bool protocol = flags & BDRV_O_PROTOCOL; bool protocol = flags & BDRV_O_PROTOCOL;
bool parse_filename = false; bool parse_filename = false;
Error *local_err = NULL; Error *local_err = NULL;
BlockDriver *drv;
/* Parse json: pseudo-protocol */ /* Parse json: pseudo-protocol */
if (filename && g_str_has_prefix(filename, "json:")) { if (filename && g_str_has_prefix(filename, "json:")) {
@ -1061,12 +1060,8 @@ static int bdrv_fill_options(QDict **options, const char **pfilename, int flags,
*pfilename = filename = NULL; *pfilename = filename = NULL;
} }
if (!protocol) {
return 0;
}
/* Fetch the file name from the options QDict if necessary */ /* Fetch the file name from the options QDict if necessary */
if (filename) { if (protocol && filename) {
if (!qdict_haskey(*options, "filename")) { if (!qdict_haskey(*options, "filename")) {
qdict_put(*options, "filename", qstring_from_str(filename)); qdict_put(*options, "filename", qstring_from_str(filename));
parse_filename = true; parse_filename = true;
@ -1081,30 +1076,41 @@ static int bdrv_fill_options(QDict **options, const char **pfilename, int flags,
filename = qdict_get_try_str(*options, "filename"); filename = qdict_get_try_str(*options, "filename");
drvname = qdict_get_try_str(*options, "driver"); drvname = qdict_get_try_str(*options, "driver");
if (!drvname) { if (drv) {
if (filename) { if (drvname) {
drv = bdrv_find_protocol(filename, parse_filename); error_setg(errp, "Driver specified twice");
if (!drv) { return -EINVAL;
error_setg(errp, "Unknown protocol"); }
drvname = drv->format_name;
qdict_put(*options, "driver", qstring_from_str(drvname));
} else {
if (!drvname && protocol) {
if (filename) {
drv = bdrv_find_protocol(filename, parse_filename);
if (!drv) {
error_setg(errp, "Unknown protocol");
return -EINVAL;
}
drvname = drv->format_name;
qdict_put(*options, "driver", qstring_from_str(drvname));
} else {
error_setg(errp, "Must specify either driver or file");
return -EINVAL; return -EINVAL;
} }
} else if (drvname) {
drvname = drv->format_name; drv = bdrv_find_format(drvname);
qdict_put(*options, "driver", qstring_from_str(drvname)); if (!drv) {
} else { error_setg(errp, "Unknown driver '%s'", drvname);
error_setg(errp, "Must specify either driver or file"); return -ENOENT;
return -EINVAL; }
} }
} }
drv = bdrv_find_format(drvname); assert(drv || !protocol);
if (!drv) {
error_setg(errp, "Unknown driver '%s'", drvname);
return -ENOENT;
}
/* Driver-specific filename parsing */ /* Driver-specific filename parsing */
if (drv->bdrv_parse_filename && parse_filename) { if (drv && drv->bdrv_parse_filename && parse_filename) {
drv->bdrv_parse_filename(filename, *options, &local_err); drv->bdrv_parse_filename(filename, *options, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
@ -1438,7 +1444,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
options = qdict_new(); options = qdict_new();
} }
ret = bdrv_fill_options(&options, &filename, flags, &local_err); ret = bdrv_fill_options(&options, &filename, flags, drv, &local_err);
if (local_err) { if (local_err) {
goto fail; goto fail;
} }
@ -1478,7 +1484,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
} }
/* Find the right image format driver */ /* Find the right image format driver */
drv = NULL;
drvname = qdict_get_try_str(options, "driver"); drvname = qdict_get_try_str(options, "driver");
assert(drvname || !(flags & BDRV_O_PROTOCOL));
if (drvname) { if (drvname) {
drv = bdrv_find_format(drvname); drv = bdrv_find_format(drvname);
qdict_del(options, "driver"); qdict_del(options, "driver");
@ -1487,19 +1496,14 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
} } else if (file) {
ret = find_image_format(file, filename, &drv, &local_err);
if (!drv) { if (ret < 0) {
if (file) {
ret = find_image_format(file, filename, &drv, &local_err);
} else {
error_setg(errp, "Must specify either driver or file");
ret = -EINVAL;
goto fail; goto fail;
} }
} } else {
error_setg(errp, "Must specify either driver or file");
if (!drv) { ret = -EINVAL;
goto fail; goto fail;
} }

View File

@ -92,6 +92,7 @@ echo
run_qemu -drive file="$TEST_IMG",format=foo run_qemu -drive file="$TEST_IMG",format=foo
run_qemu -drive file="$TEST_IMG",driver=foo run_qemu -drive file="$TEST_IMG",driver=foo
run_qemu -drive file="$TEST_IMG",driver=raw,format=qcow2
echo echo
echo === Overriding backing file === echo === Overriding backing file ===

View File

@ -38,7 +38,10 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=foo
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=foo: 'foo' invalid format QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=foo: 'foo' invalid format
Testing: -drive file=TEST_DIR/t.qcow2,driver=foo Testing: -drive file=TEST_DIR/t.qcow2,driver=foo
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TEST_DIR/t.qcow2: Invalid driver: 'foo' QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TEST_DIR/t.qcow2: Unknown driver 'foo'
Testing: -drive file=TEST_DIR/t.qcow2,driver=raw,format=qcow2
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=raw,format=qcow2: could not open disk image TEST_DIR/t.qcow2: Driver specified twice
=== Overriding backing file === === Overriding backing file ===