summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2017-07-18 17:24:05 +0200
committerKevin Wolf <kwolf@redhat.com>2017-07-24 15:06:04 +0200
commitd3c8c67469ee70fcae116d5abc277a7ebc8a19fd (patch)
tree4b324a09078175bbc7e0551f8d02b831bc1dabe1 /block
parent24bae02b197d152c2b3e4e0ba95f7942a63bad32 (diff)
downloadqemu-d3c8c67469ee70fcae116d5abc277a7ebc8a19fd.zip
block: Skip implicit nodes in query-block/blockstats
Commits 0db832f and 6cdbceb introduced the automatic insertion of filter nodes above the top layer of mirror and commit block jobs. The assumption made there was that since libvirt doesn't do node-level management of the block layer yet, it shouldn't be affected by added nodes. This is true as far as commands issued by libvirt are concerned. It only uses BlockBackend names to address nodes, so any operations it performs still operate on the root of the tree as intended. However, the assumption breaks down when you consider query commands, which return data for the wrong node now. These commands also return information on some child nodes (bs->file and/or bs->backing), which libvirt does make use of, and which refer to the wrong nodes, too. One of the consequences is that oVirt gets wrong information about the image size and stops the VM in response as long as a mirror or commit job is running: https://bugzilla.redhat.com/show_bug.cgi?id=1470634 This patch fixes the problem by hiding the implicit nodes created automatically by the mirror and commit block jobs in the output of query-block and BlockBackend-based query-blockstats as long as the user doesn't indicate that they are aware of those nodes by providing a node name for them in the QMP command to start the block job. The node-based commands query-named-block-nodes and query-blockstats with query-nodes=true still show all nodes, including implicit ones. This ensures that users that are capable of node-level management can still access the full information; users that only know BlockBackends won't use these commands. Cc: qemu-stable@nongnu.org Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Tested-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'block')
-rw-r--r--block/commit.c3
-rw-r--r--block/mirror.c3
-rw-r--r--block/qapi.c33
3 files changed, 33 insertions, 6 deletions
diff --git a/block/commit.c b/block/commit.c
index 5cc910f567..c7857c3321 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -346,6 +346,9 @@ void commit_start(const char *job_id, BlockDriverState *bs,
if (commit_top_bs == NULL) {
goto fail;
}
+ if (!filter_node_name) {
+ commit_top_bs->implicit = true;
+ }
commit_top_bs->total_sectors = top->total_sectors;
bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(top));
diff --git a/block/mirror.c b/block/mirror.c
index 8583b764a0..c9a6a3ca86 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1168,6 +1168,9 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
if (mirror_top_bs == NULL) {
return;
}
+ if (!filter_node_name) {
+ mirror_top_bs->implicit = true;
+ }
mirror_top_bs->total_sectors = bs->total_sectors;
bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));
diff --git a/block/qapi.c b/block/qapi.c
index 95b2e2daa5..d2b18ee9df 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -64,7 +64,6 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
info->backing_file = g_strdup(bs->backing_file);
}
- info->backing_file_depth = bdrv_get_backing_file_depth(bs);
info->detect_zeroes = bs->detect_zeroes;
if (blk && blk_get_public(blk)->throttle_state) {
@@ -125,6 +124,7 @@ 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);
@@ -133,13 +133,21 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
qapi_free_BlockDeviceInfo(info);
return NULL;
}
+
if (bs0->drv && bs0->backing) {
+ info->backing_file_depth++;
bs0 = bs0->backing->bs;
(*p_image_info)->has_backing_image = true;
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 */
+ while (blk && bs0 && bs0->drv && bs0->implicit) {
+ bs0 = backing_bs(bs0);
+ }
}
return info;
@@ -324,6 +332,11 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
BlockDriverState *bs = blk_bs(blk);
char *qdev;
+ /* Skip automatically inserted nodes that the user isn't aware of */
+ while (bs && bs->drv && bs->implicit) {
+ bs = backing_bs(bs);
+ }
+
info->device = g_strdup(blk_name(blk));
info->type = g_strdup("unknown");
info->locked = blk_dev_is_medium_locked(blk);
@@ -434,8 +447,8 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
}
}
-static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs,
- bool query_backing)
+static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
+ bool blk_level)
{
BlockStats *s = NULL;
@@ -446,6 +459,14 @@ static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs,
return s;
}
+ /* Skip automatically inserted nodes that the user isn't aware of in
+ * a BlockBackend-level command. Stay at the exact node for a node-level
+ * command. */
+ while (blk_level && bs->drv && bs->implicit) {
+ bs = backing_bs(bs);
+ assert(bs);
+ }
+
if (bdrv_get_node_name(bs)[0]) {
s->has_node_name = true;
s->node_name = g_strdup(bdrv_get_node_name(bs));
@@ -455,12 +476,12 @@ static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs,
if (bs->file) {
s->has_parent = true;
- s->parent = bdrv_query_bds_stats(bs->file->bs, query_backing);
+ s->parent = bdrv_query_bds_stats(bs->file->bs, blk_level);
}
- if (query_backing && bs->backing) {
+ if (blk_level && bs->backing) {
s->has_backing = true;
- s->backing = bdrv_query_bds_stats(bs->backing->bs, query_backing);
+ s->backing = bdrv_query_bds_stats(bs->backing->bs, blk_level);
}
return s;