block/qapi: Let bdrv_query_image_info() recurse

There is no real reason why bdrv_query_image_info() should generally not
recurse.  The ImageInfo struct has a pointer to the backing image, so it
should generally be filled, unless the caller explicitly opts out.

This moves the recursing code from bdrv_block_device_info() into
bdrv_query_image_info().

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220620162704.80987-7-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Hanna Reitz 2022-06-20 18:26:58 +02:00 committed by Kevin Wolf
parent b1f4cd1589
commit 5d8813593f
2 changed files with 58 additions and 36 deletions

View File

@ -48,8 +48,10 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
Error **errp)
{
ImageInfo **p_image_info;
ImageInfo *backing_info;
BlockDriverState *bs0, *backing;
BlockDeviceInfo *info;
ERRP_GUARD();
if (!bs->drv) {
error_setg(errp, "Block device %s is ejected", bs->node_name);
@ -147,37 +149,21 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
bs0 = bs;
p_image_info = &info->image;
info->backing_file_depth = 0;
while (1) {
Error *local_err = NULL;
bdrv_query_image_info(bs0, p_image_info, &local_err);
if (local_err) {
error_propagate(errp, local_err);
qapi_free_BlockDeviceInfo(info);
return NULL;
}
/* stop gathering data for flat output */
if (flat) {
break;
}
/*
* Skip automatically inserted nodes that the user isn't aware of for
* query-block (blk != NULL), but not for query-named-block-nodes
*/
bdrv_query_image_info(bs0, p_image_info, flat, blk != NULL, errp);
if (*errp) {
qapi_free_BlockDeviceInfo(info);
return NULL;
}
if (bs0->drv && bdrv_filter_or_cow_child(bs0)) {
/*
* Put any filtered child here (for backwards compatibility to when
* we put bs0->backing here, which might be any filtered child).
*/
info->backing_file_depth++;
bs0 = bdrv_filter_or_cow_bs(bs0);
p_image_info = &((*p_image_info)->backing_image);
} else {
break;
}
/* Skip automatically inserted nodes that the user isn't aware of for
* query-block (blk != NULL), but not for query-named-block-nodes */
if (blk) {
bs0 = bdrv_skip_implicit_filters(bs0);
}
backing_info = info->image->backing_image;
while (backing_info) {
info->backing_file_depth++;
backing_info = backing_info->backing_image;
}
return info;
@ -355,19 +341,28 @@ void bdrv_query_block_node_info(BlockDriverState *bs,
* bdrv_query_image_info:
* @bs: block node to examine
* @p_info: location to store image information
* @flat: skip backing node information
* @skip_implicit_filters: skip implicit filters in the backing chain
* @errp: location to store error information
*
* Store "flat" image information in @p_info.
* Store image information in @p_info, potentially recursively covering the
* backing chain.
*
* "Flat" means it does *not* query backing image information,
* i.e. (*pinfo)->has_backing_image will be set to false and
* (*pinfo)->backing_image to NULL even when the image does in fact have
* a backing image.
* If @flat is true, do not query backing image information, i.e.
* (*p_info)->has_backing_image will be set to false and
* (*p_info)->backing_image to NULL even when the image does in fact have a
* backing image.
*
* If @skip_implicit_filters is true, implicit filter nodes in the backing chain
* will be skipped when querying backing image information.
* (@skip_implicit_filters is ignored when @flat is true.)
*
* @p_info will be set only on success. On error, store error in @errp.
*/
void bdrv_query_image_info(BlockDriverState *bs,
ImageInfo **p_info,
bool flat,
bool skip_implicit_filters,
Error **errp)
{
ImageInfo *info;
@ -376,11 +371,36 @@ void bdrv_query_image_info(BlockDriverState *bs,
info = g_new0(ImageInfo, 1);
bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
if (*errp) {
qapi_free_ImageInfo(info);
return;
goto fail;
}
if (!flat) {
BlockDriverState *backing;
/*
* Use any filtered child here (for backwards compatibility to when
* we always took bs->backing, which might be any filtered child).
*/
backing = bdrv_filter_or_cow_bs(bs);
if (skip_implicit_filters) {
backing = bdrv_skip_implicit_filters(backing);
}
if (backing) {
bdrv_query_image_info(backing, &info->backing_image, false,
skip_implicit_filters, errp);
if (*errp) {
goto fail;
}
}
}
*p_info = info;
return;
fail:
assert(*errp);
qapi_free_ImageInfo(info);
}
/* @p_info will be set only on success. */

View File

@ -40,6 +40,8 @@ void bdrv_query_block_node_info(BlockDriverState *bs,
Error **errp);
void bdrv_query_image_info(BlockDriverState *bs,
ImageInfo **p_info,
bool flat,
bool skip_implicit_filters,
Error **errp);
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);