summaryrefslogtreecommitdiff
path: root/block/qapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/qapi.c')
-rw-r--r--block/qapi.c225
1 files changed, 189 insertions, 36 deletions
diff --git a/block/qapi.c b/block/qapi.c
index a4bc4113b..8f2b4dbe7 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -25,6 +25,63 @@
#include "block/qapi.h"
#include "block/block_int.h"
#include "qmp-commands.h"
+#include "qapi-visit.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/qmp/types.h"
+
+BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs)
+{
+ BlockDeviceInfo *info = g_malloc0(sizeof(*info));
+
+ info->file = g_strdup(bs->filename);
+ info->ro = bs->read_only;
+ info->drv = g_strdup(bs->drv->format_name);
+ info->encrypted = bs->encrypted;
+ info->encryption_key_missing = bdrv_key_required(bs);
+
+ if (bs->node_name[0]) {
+ info->has_node_name = true;
+ info->node_name = g_strdup(bs->node_name);
+ }
+
+ if (bs->backing_file[0]) {
+ info->has_backing_file = true;
+ info->backing_file = g_strdup(bs->backing_file);
+ }
+
+ info->backing_file_depth = bdrv_get_backing_file_depth(bs);
+
+ if (bs->io_limits_enabled) {
+ ThrottleConfig cfg;
+ throttle_get_config(&bs->throttle_state, &cfg);
+ info->bps = cfg.buckets[THROTTLE_BPS_TOTAL].avg;
+ info->bps_rd = cfg.buckets[THROTTLE_BPS_READ].avg;
+ info->bps_wr = cfg.buckets[THROTTLE_BPS_WRITE].avg;
+
+ info->iops = cfg.buckets[THROTTLE_OPS_TOTAL].avg;
+ info->iops_rd = cfg.buckets[THROTTLE_OPS_READ].avg;
+ info->iops_wr = cfg.buckets[THROTTLE_OPS_WRITE].avg;
+
+ info->has_bps_max = cfg.buckets[THROTTLE_BPS_TOTAL].max;
+ info->bps_max = cfg.buckets[THROTTLE_BPS_TOTAL].max;
+ info->has_bps_rd_max = cfg.buckets[THROTTLE_BPS_READ].max;
+ info->bps_rd_max = cfg.buckets[THROTTLE_BPS_READ].max;
+ info->has_bps_wr_max = cfg.buckets[THROTTLE_BPS_WRITE].max;
+ info->bps_wr_max = cfg.buckets[THROTTLE_BPS_WRITE].max;
+
+ info->has_iops_max = cfg.buckets[THROTTLE_OPS_TOTAL].max;
+ info->iops_max = cfg.buckets[THROTTLE_OPS_TOTAL].max;
+ info->has_iops_rd_max = cfg.buckets[THROTTLE_OPS_READ].max;
+ info->iops_rd_max = cfg.buckets[THROTTLE_OPS_READ].max;
+ info->has_iops_wr_max = cfg.buckets[THROTTLE_OPS_WRITE].max;
+ info->iops_wr_max = cfg.buckets[THROTTLE_OPS_WRITE].max;
+
+ info->has_iops_size = cfg.op_size;
+ info->iops_size = cfg.op_size;
+ }
+
+ return info;
+}
/*
* Returns 0 on success, with *p_list either set to describe snapshot
@@ -134,6 +191,9 @@ void bdrv_query_image_info(BlockDriverState *bs,
info->dirty_flag = bdi.is_dirty;
info->has_dirty_flag = true;
}
+ info->format_specific = bdrv_get_specific_info(bs);
+ info->has_format_specific = info->format_specific != NULL;
+
backing_filename = bs->backing_file;
if (backing_filename[0] != '\0') {
info->backing_filename = g_strdup(backing_filename);
@@ -198,50 +258,20 @@ void bdrv_query_info(BlockDriverState *bs,
info->io_status = bs->iostatus;
}
- if (bs->dirty_bitmap) {
- info->has_dirty = true;
- info->dirty = g_malloc0(sizeof(*info->dirty));
- info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE;
- info->dirty->granularity =
- ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap));
+ if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
+ info->has_dirty_bitmaps = true;
+ info->dirty_bitmaps = bdrv_query_dirty_bitmaps(bs);
}
if (bs->drv) {
info->has_inserted = true;
- info->inserted = g_malloc0(sizeof(*info->inserted));
- info->inserted->file = g_strdup(bs->filename);
- info->inserted->ro = bs->read_only;
- info->inserted->drv = g_strdup(bs->drv->format_name);
- info->inserted->encrypted = bs->encrypted;
- info->inserted->encryption_key_missing = bdrv_key_required(bs);
-
- if (bs->backing_file[0]) {
- info->inserted->has_backing_file = true;
- info->inserted->backing_file = g_strdup(bs->backing_file);
- }
-
- info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs);
-
- if (bs->io_limits_enabled) {
- info->inserted->bps =
- bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL];
- info->inserted->bps_rd =
- bs->io_limits.bps[BLOCK_IO_LIMIT_READ];
- info->inserted->bps_wr =
- bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE];
- info->inserted->iops =
- bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL];
- info->inserted->iops_rd =
- bs->io_limits.iops[BLOCK_IO_LIMIT_READ];
- info->inserted->iops_wr =
- bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
- }
+ info->inserted = bdrv_block_device_info(bs);
bs0 = bs;
p_image_info = &info->inserted->image;
while (1) {
bdrv_query_image_info(bs0, p_image_info, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto err;
}
@@ -289,6 +319,11 @@ BlockStats *bdrv_query_stats(const BlockDriverState *bs)
s->parent = bdrv_query_stats(bs->file);
}
+ if (bs->backing_hd) {
+ s->has_backing = true;
+ s->backing = bdrv_query_stats(bs->backing_hd);
+ }
+
return s;
}
@@ -301,7 +336,7 @@ BlockInfoList *qmp_query_block(Error **errp)
while ((bs = bdrv_next(bs))) {
BlockInfoList *info = g_malloc0(sizeof(*info));
bdrv_query_info(bs, &info->value, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto err;
}
@@ -397,6 +432,119 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
}
}
+static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
+ QDict *dict);
+static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
+ QList *list);
+
+static void dump_qobject(fprintf_function func_fprintf, void *f,
+ int comp_indent, QObject *obj)
+{
+ switch (qobject_type(obj)) {
+ case QTYPE_QINT: {
+ QInt *value = qobject_to_qint(obj);
+ func_fprintf(f, "%" PRId64, qint_get_int(value));
+ break;
+ }
+ case QTYPE_QSTRING: {
+ QString *value = qobject_to_qstring(obj);
+ func_fprintf(f, "%s", qstring_get_str(value));
+ break;
+ }
+ case QTYPE_QDICT: {
+ QDict *value = qobject_to_qdict(obj);
+ dump_qdict(func_fprintf, f, comp_indent, value);
+ break;
+ }
+ case QTYPE_QLIST: {
+ QList *value = qobject_to_qlist(obj);
+ dump_qlist(func_fprintf, f, comp_indent, value);
+ break;
+ }
+ case QTYPE_QFLOAT: {
+ QFloat *value = qobject_to_qfloat(obj);
+ func_fprintf(f, "%g", qfloat_get_double(value));
+ break;
+ }
+ case QTYPE_QBOOL: {
+ QBool *value = qobject_to_qbool(obj);
+ func_fprintf(f, "%s", qbool_get_int(value) ? "true" : "false");
+ break;
+ }
+ case QTYPE_QERROR: {
+ QString *value = qerror_human((QError *)obj);
+ func_fprintf(f, "%s", qstring_get_str(value));
+ break;
+ }
+ case QTYPE_NONE:
+ break;
+ case QTYPE_MAX:
+ default:
+ abort();
+ }
+}
+
+static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
+ QList *list)
+{
+ const QListEntry *entry;
+ int i = 0;
+
+ for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
+ qtype_code type = qobject_type(entry->value);
+ bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
+ const char *format = composite ? "%*s[%i]:\n" : "%*s[%i]: ";
+
+ func_fprintf(f, format, indentation * 4, "", i);
+ dump_qobject(func_fprintf, f, indentation + 1, entry->value);
+ if (!composite) {
+ func_fprintf(f, "\n");
+ }
+ }
+}
+
+static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
+ QDict *dict)
+{
+ const QDictEntry *entry;
+
+ for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) {
+ qtype_code type = qobject_type(entry->value);
+ bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
+ const char *format = composite ? "%*s%s:\n" : "%*s%s: ";
+ char key[strlen(entry->key) + 1];
+ int i;
+
+ /* replace dashes with spaces in key (variable) names */
+ for (i = 0; entry->key[i]; i++) {
+ key[i] = entry->key[i] == '-' ? ' ' : entry->key[i];
+ }
+ key[i] = 0;
+
+ func_fprintf(f, format, indentation * 4, "", key);
+ dump_qobject(func_fprintf, f, indentation + 1, entry->value);
+ if (!composite) {
+ func_fprintf(f, "\n");
+ }
+ }
+}
+
+void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
+ ImageInfoSpecific *info_spec)
+{
+ Error *local_err = NULL;
+ QmpOutputVisitor *ov = qmp_output_visitor_new();
+ QObject *obj, *data;
+
+ visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
+ &local_err);
+ obj = qmp_output_get_qobject(ov);
+ assert(qobject_type(obj) == QTYPE_QDICT);
+ data = qdict_get(qobject_to_qdict(obj), "data");
+ dump_qobject(func_fprintf, f, 1, data);
+ qmp_output_visitor_cleanup(ov);
+}
+
void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
ImageInfo *info)
{
@@ -467,4 +615,9 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
func_fprintf(f, "\n");
}
}
+
+ if (info->has_format_specific) {
+ func_fprintf(f, "Format specific information:\n");
+ bdrv_image_info_specific_dump(func_fprintf, f, info->format_specific);
+ }
}