block: Create bdrv_fill_options()

The idea of bdrv_fill_options() is to convert every parameter for
opening images, in particular the filename and flags, to entries in the
options QDict.

This patch starts with moving the filename parsing and driver probing
part from bdrv_file_open() to the new function.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Kevin Wolf 2014-05-26 11:09:59 +02:00
parent f42ca3cad1
commit f54120ff1a
1 changed files with 75 additions and 49 deletions

124
block.c
View File

@ -1005,6 +1005,72 @@ free_and_fail:
return ret;
}
/*
* Fills in default options for opening images and converts the legacy
* filename/flags pair to option QDict entries.
*/
static int bdrv_fill_options(QDict **options, const char *filename,
Error **errp)
{
const char *drvname;
bool parse_filename = false;
Error *local_err = NULL;
BlockDriver *drv;
/* Fetch the file name from the options QDict if necessary */
if (filename) {
if (!qdict_haskey(*options, "filename")) {
qdict_put(*options, "filename", qstring_from_str(filename));
parse_filename = true;
} else {
error_setg(errp, "Can't specify 'file' and 'filename' options at "
"the same time");
return -EINVAL;
}
}
/* Find the right block driver */
filename = qdict_get_try_str(*options, "filename");
drvname = qdict_get_try_str(*options, "driver");
if (!drvname) {
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;
}
}
drv = bdrv_find_format(drvname);
if (!drv) {
error_setg(errp, "Unknown driver '%s'", drvname);
return -ENOENT;
}
/* Driver-specific filename parsing */
if (drv->bdrv_parse_filename && parse_filename) {
drv->bdrv_parse_filename(filename, *options, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return -EINVAL;
}
if (!drv->bdrv_needs_filename) {
qdict_del(*options, "filename");
}
}
return 0;
}
/*
* Opens a file using a protocol (file, host_device, nbd, ...)
*
@ -1020,63 +1086,23 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
{
BlockDriver *drv;
const char *drvname;
bool parse_filename = false;
Error *local_err = NULL;
int ret;
/* Fetch the file name from the options QDict if necessary */
if (!filename) {
filename = qdict_get_try_str(*options, "filename");
} else if (filename && !qdict_haskey(*options, "filename")) {
qdict_put(*options, "filename", qstring_from_str(filename));
parse_filename = true;
} else {
error_setg(errp, "Can't specify 'file' and 'filename' options at the "
"same time");
ret = -EINVAL;
ret = bdrv_fill_options(options, filename, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto fail;
}
/* Find the right block driver */
drvname = qdict_get_try_str(*options, "driver");
if (drvname) {
drv = bdrv_find_format(drvname);
if (!drv) {
error_setg(errp, "Unknown driver '%s'", drvname);
}
qdict_del(*options, "driver");
} else if (filename) {
drv = bdrv_find_protocol(filename, parse_filename);
if (!drv) {
error_setg(errp, "Unknown protocol");
}
} else {
error_setg(errp, "Must specify either driver or file");
drv = NULL;
}
filename = qdict_get_try_str(*options, "filename");
drvname = qdict_get_str(*options, "driver");
if (!drv) {
/* errp has been set already */
ret = -ENOENT;
goto fail;
}
/* Parse the filename and open it */
if (drv->bdrv_parse_filename && parse_filename) {
drv->bdrv_parse_filename(filename, *options, &local_err);
if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
}
if (!drv->bdrv_needs_filename) {
qdict_del(*options, "filename");
} else {
filename = qdict_get_str(*options, "filename");
}
}
drv = bdrv_find_format(drvname);
assert(drv);
qdict_del(*options, "driver");
/* Open the file */
if (!drv->bdrv_file_open) {
ret = bdrv_open(&bs, filename, NULL, *options, flags, drv, &local_err);
*options = NULL;