BlockStatsList *qmp_query_blockstats(bool has_query_nodes, bool query_nodes, Error **errp) { BlockStatsList *head = NULL, **p_next = &head; BlockBackend *blk; BlockDriverState *bs; /* Just to be safe if query_nodes is not always initialized */ if (has_query_nodes && query_nodes) { for (bs = bdrv_next_node(NULL); bs; bs = bdrv_next_node(bs)) { BlockStatsList *info = g_malloc0(sizeof(*info)); AioContext *ctx = bdrv_get_aio_context(bs); aio_context_acquire(ctx); info->value = bdrv_query_bds_stats(bs, false); aio_context_release(ctx); *p_next = info; p_next = &info->next; } } else { for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { BlockStatsList *info = g_malloc0(sizeof(*info)); AioContext *ctx = blk_get_aio_context(blk); BlockStats *s; aio_context_acquire(ctx); s = bdrv_query_bds_stats(blk_bs(blk), true); s->has_device = true; s->device = g_strdup(blk_name(blk)); bdrv_query_blk_stats(s->stats, blk); aio_context_release(ctx); info->value = s; *p_next = info; p_next = &info->next; } } return head; }
static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs, bool blk_level) { BlockStats *s = NULL; s = g_malloc0(sizeof(*s)); s->stats = g_malloc0(sizeof(*s->stats)); if (!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)); } s->stats->wr_highest_offset = stat64_get(&bs->wr_highest_offset); if (bs->file) { s->has_parent = true; s->parent = bdrv_query_bds_stats(bs->file->bs, blk_level); } if (blk_level && bs->backing) { s->has_backing = true; s->backing = bdrv_query_bds_stats(bs->backing->bs, blk_level); } return s; }
static BlockStats *bdrv_query_stats(BlockBackend *blk, const BlockDriverState *bs, bool query_backing) { BlockStats *s; s = g_malloc0(sizeof(*s)); s->stats = g_malloc0(sizeof(*s->stats)); if (blk) { s->has_device = true; s->device = g_strdup(blk_name(blk)); bdrv_query_blk_stats(s->stats, blk); } if (bs) { bdrv_query_bds_stats(s, bs, query_backing); } return s; }