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:
Max Reitz 2015-10-19 17:53:09 +02:00 committed by Kevin Wolf
parent d44f928a54
commit be4b67bc7d
4 changed files with 43 additions and 20 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -54,7 +54,7 @@ size=128M
_make_test_img $size
echo
echo === Missing ID ===
echo === Missing ID and node-name ===
echo
run_qemu <<EOF

View File

@ -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"}