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) Error **errp)
{ {
ImageInfo **p_image_info; ImageInfo **p_image_info;
ImageInfo *backing_info;
BlockDriverState *bs0, *backing; BlockDriverState *bs0, *backing;
BlockDeviceInfo *info; BlockDeviceInfo *info;
ERRP_GUARD();
if (!bs->drv) { if (!bs->drv) {
error_setg(errp, "Block device %s is ejected", bs->node_name); error_setg(errp, "Block device %s is ejected", bs->node_name);
@ -147,37 +149,21 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
bs0 = bs; bs0 = bs;
p_image_info = &info->image; p_image_info = &info->image;
info->backing_file_depth = 0; 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) { * Skip automatically inserted nodes that the user isn't aware of for
break; * 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)) { backing_info = info->image->backing_image;
/* while (backing_info) {
* Put any filtered child here (for backwards compatibility to when info->backing_file_depth++;
* we put bs0->backing here, which might be any filtered child). backing_info = backing_info->backing_image;
*/
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);
}
} }
return info; return info;
@ -355,19 +341,28 @@ void bdrv_query_block_node_info(BlockDriverState *bs,
* bdrv_query_image_info: * bdrv_query_image_info:
* @bs: block node to examine * @bs: block node to examine
* @p_info: location to store image information * @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 * @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, * If @flat is true, do not query backing image information, i.e.
* i.e. (*pinfo)->has_backing_image will be set to false and * (*p_info)->has_backing_image will be set to false and
* (*pinfo)->backing_image to NULL even when the image does in fact have * (*p_info)->backing_image to NULL even when the image does in fact have a
* a backing image. * 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. * @p_info will be set only on success. On error, store error in @errp.
*/ */
void bdrv_query_image_info(BlockDriverState *bs, void bdrv_query_image_info(BlockDriverState *bs,
ImageInfo **p_info, ImageInfo **p_info,
bool flat,
bool skip_implicit_filters,
Error **errp) Error **errp)
{ {
ImageInfo *info; ImageInfo *info;
@ -376,11 +371,36 @@ void bdrv_query_image_info(BlockDriverState *bs,
info = g_new0(ImageInfo, 1); info = g_new0(ImageInfo, 1);
bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp); bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
if (*errp) { if (*errp) {
qapi_free_ImageInfo(info); goto fail;
return; }
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; *p_info = info;
return;
fail:
assert(*errp);
qapi_free_ImageInfo(info);
} }
/* @p_info will be set only on success. */ /* @p_info will be set only on success. */

View File

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