mirror of https://gitee.com/openkylin/qemu.git
block: Reuse success path from bdrv_open()
The fail and success paths of bdrv_file_open() may be further shortened by reusing code already existent in bdrv_open(). This includes bdrv_file_open() not taking the reference to options which allows the removal of QDECREF(options) in that function. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Benoit Canet <benoit@irqsave.net> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
5469a2a688
commit
5acd9d81e1
63
block.c
63
block.c
|
@ -955,13 +955,15 @@ free_and_fail:
|
||||||
/*
|
/*
|
||||||
* Opens a file using a protocol (file, host_device, nbd, ...)
|
* Opens a file using a protocol (file, host_device, nbd, ...)
|
||||||
*
|
*
|
||||||
* options is a QDict of options to pass to the block drivers, or NULL for an
|
* options is an indirect pointer to a QDict of options to pass to the block
|
||||||
* empty set of options. The reference to the QDict belongs to the block layer
|
* drivers, or pointer to NULL for an empty set of options. If this function
|
||||||
* after the call (even on failure), so if the caller intends to reuse the
|
* takes ownership of the QDict reference, it will set *options to NULL;
|
||||||
* dictionary, it needs to use QINCREF() before calling bdrv_file_open.
|
* otherwise, it will contain unused/unrecognized options after this function
|
||||||
|
* returns. Then, the caller is responsible for freeing it. If it intends to
|
||||||
|
* reuse the QDict, QINCREF() should be called beforehand.
|
||||||
*/
|
*/
|
||||||
static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
||||||
QDict *options, int flags, Error **errp)
|
QDict **options, int flags, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriver *drv;
|
BlockDriver *drv;
|
||||||
const char *drvname;
|
const char *drvname;
|
||||||
|
@ -971,9 +973,9 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
||||||
|
|
||||||
/* Fetch the file name from the options QDict if necessary */
|
/* Fetch the file name from the options QDict if necessary */
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
filename = qdict_get_try_str(options, "filename");
|
filename = qdict_get_try_str(*options, "filename");
|
||||||
} else if (filename && !qdict_haskey(options, "filename")) {
|
} else if (filename && !qdict_haskey(*options, "filename")) {
|
||||||
qdict_put(options, "filename", qstring_from_str(filename));
|
qdict_put(*options, "filename", qstring_from_str(filename));
|
||||||
allow_protocol_prefix = true;
|
allow_protocol_prefix = true;
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "Can't specify 'file' and 'filename' options at the "
|
error_setg(errp, "Can't specify 'file' and 'filename' options at the "
|
||||||
|
@ -983,13 +985,13 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the right block driver */
|
/* Find the right block driver */
|
||||||
drvname = qdict_get_try_str(options, "driver");
|
drvname = qdict_get_try_str(*options, "driver");
|
||||||
if (drvname) {
|
if (drvname) {
|
||||||
drv = bdrv_find_format(drvname);
|
drv = bdrv_find_format(drvname);
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
error_setg(errp, "Unknown driver '%s'", drvname);
|
error_setg(errp, "Unknown driver '%s'", drvname);
|
||||||
}
|
}
|
||||||
qdict_del(options, "driver");
|
qdict_del(*options, "driver");
|
||||||
} else if (filename) {
|
} else if (filename) {
|
||||||
drv = bdrv_find_protocol(filename, allow_protocol_prefix);
|
drv = bdrv_find_protocol(filename, allow_protocol_prefix);
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
|
@ -1008,41 +1010,30 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
||||||
|
|
||||||
/* Parse the filename and open it */
|
/* Parse the filename and open it */
|
||||||
if (drv->bdrv_parse_filename && filename) {
|
if (drv->bdrv_parse_filename && 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);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
qdict_del(options, "filename");
|
qdict_del(*options, "filename");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drv->bdrv_file_open) {
|
if (!drv->bdrv_file_open) {
|
||||||
ret = bdrv_open(&bs, filename, NULL, options, flags, drv, &local_err);
|
ret = bdrv_open(&bs, filename, NULL, *options, flags, drv, &local_err);
|
||||||
options = NULL;
|
*options = NULL;
|
||||||
} else {
|
} else {
|
||||||
ret = bdrv_open_common(bs, NULL, options, flags, drv, &local_err);
|
ret = bdrv_open_common(bs, NULL, *options, flags, drv, &local_err);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any unknown options were used */
|
|
||||||
if (options && (qdict_size(options) != 0)) {
|
|
||||||
const QDictEntry *entry = qdict_first(options);
|
|
||||||
error_setg(errp, "Block protocol '%s' doesn't support the option '%s'",
|
|
||||||
drv->format_name, entry->key);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
QDECREF(options);
|
|
||||||
|
|
||||||
bs->growable = 1;
|
bs->growable = 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
QDECREF(options);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1253,12 +1244,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||||
|
|
||||||
if (flags & BDRV_O_PROTOCOL) {
|
if (flags & BDRV_O_PROTOCOL) {
|
||||||
assert(!drv);
|
assert(!drv);
|
||||||
ret = bdrv_file_open(bs, filename, options, flags & ~BDRV_O_PROTOCOL,
|
ret = bdrv_file_open(bs, filename, &options, flags & ~BDRV_O_PROTOCOL,
|
||||||
&local_err);
|
&local_err);
|
||||||
options = NULL;
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
*pbs = bs;
|
goto done;
|
||||||
return 0;
|
|
||||||
} else if (bs->drv) {
|
} else if (bs->drv) {
|
||||||
goto close_and_fail;
|
goto close_and_fail;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1395,12 +1384,18 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
/* Check if any unknown options were used */
|
/* Check if any unknown options were used */
|
||||||
if (qdict_size(options) != 0) {
|
if (options && (qdict_size(options) != 0)) {
|
||||||
const QDictEntry *entry = qdict_first(options);
|
const QDictEntry *entry = qdict_first(options);
|
||||||
error_setg(errp, "Block format '%s' used by device '%s' doesn't "
|
if (flags & BDRV_O_PROTOCOL) {
|
||||||
"support the option '%s'", drv->format_name, bs->device_name,
|
error_setg(errp, "Block protocol '%s' doesn't support the option "
|
||||||
entry->key);
|
"'%s'", drv->format_name, entry->key);
|
||||||
|
} else {
|
||||||
|
error_setg(errp, "Block format '%s' used by device '%s' doesn't "
|
||||||
|
"support the option '%s'", drv->format_name,
|
||||||
|
bs->device_name, entry->key);
|
||||||
|
}
|
||||||
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto close_and_fail;
|
goto close_and_fail;
|
||||||
|
|
Loading…
Reference in New Issue