block: Accept node-name for blockdev-snapshot-internal-sync

In order to remove the necessity to use BlockBackend names in the
external API, we want to allow node-names everywhere. This converts
blockdev-snapshot-internal-sync to accept a node-name without lifting
the restriction that we're operating at a root node.

In case of an invalid device name, the command returns the GenericError
error class now instead of DeviceNotFound, because this is what
qmp_get_root_bs() returns.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Kevin Wolf 2016-06-23 14:20:24 +02:00
parent 2dfb4c033f
commit 75dfd402a7
4 changed files with 11 additions and 17 deletions

View File

@ -1511,7 +1511,6 @@ static void internal_snapshot_prepare(BlkActionState *common,
Error *local_err = NULL; Error *local_err = NULL;
const char *device; const char *device;
const char *name; const char *name;
BlockBackend *blk;
BlockDriverState *bs; BlockDriverState *bs;
QEMUSnapshotInfo old_sn, *sn; QEMUSnapshotInfo old_sn, *sn;
bool ret; bool ret;
@ -1534,23 +1533,15 @@ static void internal_snapshot_prepare(BlkActionState *common,
return; return;
} }
blk = blk_by_name(device); bs = qmp_get_root_bs(device, errp);
if (!blk) { if (!bs) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", device);
return; return;
} }
/* AioContext is released in .clean() */ /* AioContext is released in .clean() */
state->aio_context = blk_get_aio_context(blk); state->aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(state->aio_context); aio_context_acquire(state->aio_context);
if (!blk_is_available(blk)) {
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
return;
}
bs = blk_bs(blk);
state->bs = bs; state->bs = bs;
bdrv_drained_begin(bs); bdrv_drained_begin(bs);

View File

@ -58,7 +58,8 @@
## ##
# @BlockdevSnapshotInternal # @BlockdevSnapshotInternal
# #
# @device: the name of the device to generate the snapshot from # @device: the device name or node-name of a root node to generate the snapshot
# from
# #
# @name: the name of the internal snapshot to be created # @name: the name of the internal snapshot to be created
# #
@ -80,7 +81,7 @@
# For the arguments, see the documentation of BlockdevSnapshotInternal. # For the arguments, see the documentation of BlockdevSnapshotInternal.
# #
# Returns: nothing on success # Returns: nothing on success
# If @device is not a valid block device, DeviceNotFound # If @device is not a valid block device, GenericError
# If any snapshot matching @name exists, or @name is empty, # If any snapshot matching @name exists, or @name is empty,
# GenericError # GenericError
# If the format of the image used does not support it, # If the format of the image used does not support it,

View File

@ -1407,7 +1407,8 @@ actions array:
- "mode": whether and how QEMU should create the snapshot file - "mode": whether and how QEMU should create the snapshot file
(NewImageMode, optional, default "absolute-paths") (NewImageMode, optional, default "absolute-paths")
When "type" is "blockdev-snapshot-internal-sync": When "type" is "blockdev-snapshot-internal-sync":
- "device": device name to snapshot (json-string) - "device": the device name or node-name of a root node to snapshot
(json-string)
- "name": name of the new snapshot (json-string) - "name": name of the new snapshot (json-string)
Example: Example:
@ -1608,7 +1609,8 @@ name already exists, the operation will fail.
Arguments: Arguments:
- "device": device name to snapshot (json-string) - "device": the device name or node-name of a root node to snapshot
(json-string)
- "name": name of the new snapshot (json-string) - "name": name of the new snapshot (json-string)
Example: Example:

View File

@ -182,7 +182,7 @@ class TestSingleTransaction(ImageSnapshotTestCase):
'name': 'a' }, 'name': 'a' },
}] }]
result = self.vm.qmp('transaction', actions = actions) result = self.vm.qmp('transaction', actions = actions)
self.assert_qmp(result, 'error/class', 'DeviceNotFound') self.assert_qmp(result, 'error/class', 'GenericError')
def test_error_exist(self): def test_error_exist(self):
self.createSnapshotInTransaction(1) self.createSnapshotInTransaction(1)