blockdev: Allow creation of BDS trees without BB
If the "id" field is missing from the options given to blockdev-add, just omit the BlockBackend and create the BlockDriverState tree alone. However, if "id" is missing, "node-name" must be specified; otherwise, the BDS tree would no longer be accessible. Many BDS options which are not parsed by bdrv_open() (like caching) cannot be specified for these BB-less BDS trees yet. A future patch will remove this limitation. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Alberto Garcia <berto@igalia.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
d44f928a54
commit
be4b67bc7d
44
blockdev.c
44
blockdev.c
@ -3026,17 +3026,12 @@ out:
|
||||
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||
{
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
BlockBackend *blk = NULL;
|
||||
QObject *obj;
|
||||
QDict *qdict;
|
||||
Error *local_err = NULL;
|
||||
|
||||
/* Require an ID in the top level */
|
||||
if (!options->has_id) {
|
||||
error_setg(errp, "Block device needs an ID");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* when called from drive_new().
|
||||
@ -3064,14 +3059,37 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||
|
||||
qdict_flatten(qdict);
|
||||
|
||||
blk = blockdev_init(NULL, qdict, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
if (options->has_id) {
|
||||
blk = blockdev_init(NULL, qdict, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs = blk_bs(blk);
|
||||
} else {
|
||||
int ret;
|
||||
|
||||
if (!qdict_get_try_str(qdict, "node-name")) {
|
||||
error_setg(errp, "'id' and/or 'node-name' need to be specified for "
|
||||
"the root node");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs = NULL;
|
||||
ret = bdrv_open(&bs, NULL, NULL, qdict, BDRV_O_RDWR | BDRV_O_CACHE_WB,
|
||||
errp);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (bdrv_key_required(blk_bs(blk))) {
|
||||
blk_unref(blk);
|
||||
if (bs && bdrv_key_required(bs)) {
|
||||
if (blk) {
|
||||
blk_unref(blk);
|
||||
} else {
|
||||
bdrv_unref(bs);
|
||||
}
|
||||
error_setg(errp, "blockdev-add doesn't support encrypted devices");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1393,9 +1393,12 @@
|
||||
#
|
||||
# @driver: block driver name
|
||||
# @id: #optional id by which the new block device can be referred to.
|
||||
# This is a required option on the top level of blockdev-add, and
|
||||
# currently not allowed on any other level.
|
||||
# @node-name: #optional the name of a block driver state node (Since 2.0)
|
||||
# This option is only allowed on the top level of blockdev-add.
|
||||
# A BlockBackend will be created by blockdev-add if and only if
|
||||
# this option is given.
|
||||
# @node-name: #optional the name of a block driver state node (Since 2.0).
|
||||
# This option is required on the top level of blockdev-add if
|
||||
# the @id option is not given there.
|
||||
# @discard: #optional discard-related options (default: ignore)
|
||||
# @cache: #optional cache-related options
|
||||
# @aio: #optional AIO backend (default: threads)
|
||||
@ -1859,7 +1862,9 @@
|
||||
##
|
||||
# @blockdev-add:
|
||||
#
|
||||
# Creates a new block device.
|
||||
# Creates a new block device. If the @id option is given at the top level, a
|
||||
# BlockBackend will be created; otherwise, @node-name is mandatory at the top
|
||||
# level and no BlockBackend will be created.
|
||||
#
|
||||
# This command is still a work in progress. It doesn't support all
|
||||
# block drivers, it lacks a matching blockdev-del, and more. Stay
|
||||
|
@ -54,7 +54,7 @@ size=128M
|
||||
_make_test_img $size
|
||||
|
||||
echo
|
||||
echo === Missing ID ===
|
||||
echo === Missing ID and node-name ===
|
||||
echo
|
||||
|
||||
run_qemu <<EOF
|
||||
|
@ -1,12 +1,12 @@
|
||||
QA output created by 087
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||
|
||||
=== Missing ID ===
|
||||
=== Missing ID and node-name ===
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Block device needs an ID"}}
|
||||
{"error": {"class": "GenericError", "desc": "'id' and/or 'node-name' need to be specified for the root node"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user