xref: /qemu/block/qapi.c (revision d5a8ee60)
1f364ec65SWenchao Xia /*
2f364ec65SWenchao Xia  * Block layer qmp and info dump related functions
3f364ec65SWenchao Xia  *
4f364ec65SWenchao Xia  * Copyright (c) 2003-2008 Fabrice Bellard
5f364ec65SWenchao Xia  *
6f364ec65SWenchao Xia  * Permission is hereby granted, free of charge, to any person obtaining a copy
7f364ec65SWenchao Xia  * of this software and associated documentation files (the "Software"), to deal
8f364ec65SWenchao Xia  * in the Software without restriction, including without limitation the rights
9f364ec65SWenchao Xia  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10f364ec65SWenchao Xia  * copies of the Software, and to permit persons to whom the Software is
11f364ec65SWenchao Xia  * furnished to do so, subject to the following conditions:
12f364ec65SWenchao Xia  *
13f364ec65SWenchao Xia  * The above copyright notice and this permission notice shall be included in
14f364ec65SWenchao Xia  * all copies or substantial portions of the Software.
15f364ec65SWenchao Xia  *
16f364ec65SWenchao Xia  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17f364ec65SWenchao Xia  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18f364ec65SWenchao Xia  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19f364ec65SWenchao Xia  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20f364ec65SWenchao Xia  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21f364ec65SWenchao Xia  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22f364ec65SWenchao Xia  * THE SOFTWARE.
23f364ec65SWenchao Xia  */
24f364ec65SWenchao Xia 
25f364ec65SWenchao Xia #include "block/qapi.h"
26f364ec65SWenchao Xia #include "block/block_int.h"
27e2462113SFrancesco Romani #include "block/write-threshold.h"
28f364ec65SWenchao Xia #include "qmp-commands.h"
29a8d8ecb7SMax Reitz #include "qapi-visit.h"
30a8d8ecb7SMax Reitz #include "qapi/qmp-output-visitor.h"
31a8d8ecb7SMax Reitz #include "qapi/qmp/types.h"
32d829a211SMarkus Armbruster #include "sysemu/block-backend.h"
33f364ec65SWenchao Xia 
34*d5a8ee60SAlberto Garcia BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs, Error **errp)
35c13163fbSBenoît Canet {
36*d5a8ee60SAlberto Garcia     ImageInfo **p_image_info;
37*d5a8ee60SAlberto Garcia     BlockDriverState *bs0;
38c13163fbSBenoît Canet     BlockDeviceInfo *info = g_malloc0(sizeof(*info));
39c13163fbSBenoît Canet 
40c13163fbSBenoît Canet     info->file                   = g_strdup(bs->filename);
41c13163fbSBenoît Canet     info->ro                     = bs->read_only;
42c13163fbSBenoît Canet     info->drv                    = g_strdup(bs->drv->format_name);
43c13163fbSBenoît Canet     info->encrypted              = bs->encrypted;
44c13163fbSBenoît Canet     info->encryption_key_missing = bdrv_key_required(bs);
45c13163fbSBenoît Canet 
469e193c5aSKevin Wolf     info->cache = g_new(BlockdevCacheInfo, 1);
479e193c5aSKevin Wolf     *info->cache = (BlockdevCacheInfo) {
489e193c5aSKevin Wolf         .writeback      = bdrv_enable_write_cache(bs),
499e193c5aSKevin Wolf         .direct         = !!(bs->open_flags & BDRV_O_NOCACHE),
509e193c5aSKevin Wolf         .no_flush       = !!(bs->open_flags & BDRV_O_NO_FLUSH),
519e193c5aSKevin Wolf     };
529e193c5aSKevin Wolf 
53c13163fbSBenoît Canet     if (bs->node_name[0]) {
54c13163fbSBenoît Canet         info->has_node_name = true;
55c13163fbSBenoît Canet         info->node_name = g_strdup(bs->node_name);
56c13163fbSBenoît Canet     }
57c13163fbSBenoît Canet 
58c13163fbSBenoît Canet     if (bs->backing_file[0]) {
59c13163fbSBenoît Canet         info->has_backing_file = true;
60c13163fbSBenoît Canet         info->backing_file = g_strdup(bs->backing_file);
61c13163fbSBenoît Canet     }
62c13163fbSBenoît Canet 
63c13163fbSBenoît Canet     info->backing_file_depth = bdrv_get_backing_file_depth(bs);
64465bee1dSPeter Lieven     info->detect_zeroes = bs->detect_zeroes;
65c13163fbSBenoît Canet 
66c13163fbSBenoît Canet     if (bs->io_limits_enabled) {
67c13163fbSBenoît Canet         ThrottleConfig cfg;
68c13163fbSBenoît Canet         throttle_get_config(&bs->throttle_state, &cfg);
69c13163fbSBenoît Canet         info->bps     = cfg.buckets[THROTTLE_BPS_TOTAL].avg;
70c13163fbSBenoît Canet         info->bps_rd  = cfg.buckets[THROTTLE_BPS_READ].avg;
71c13163fbSBenoît Canet         info->bps_wr  = cfg.buckets[THROTTLE_BPS_WRITE].avg;
72c13163fbSBenoît Canet 
73c13163fbSBenoît Canet         info->iops    = cfg.buckets[THROTTLE_OPS_TOTAL].avg;
74c13163fbSBenoît Canet         info->iops_rd = cfg.buckets[THROTTLE_OPS_READ].avg;
75c13163fbSBenoît Canet         info->iops_wr = cfg.buckets[THROTTLE_OPS_WRITE].avg;
76c13163fbSBenoît Canet 
77c13163fbSBenoît Canet         info->has_bps_max     = cfg.buckets[THROTTLE_BPS_TOTAL].max;
78c13163fbSBenoît Canet         info->bps_max         = cfg.buckets[THROTTLE_BPS_TOTAL].max;
79c13163fbSBenoît Canet         info->has_bps_rd_max  = cfg.buckets[THROTTLE_BPS_READ].max;
80c13163fbSBenoît Canet         info->bps_rd_max      = cfg.buckets[THROTTLE_BPS_READ].max;
81c13163fbSBenoît Canet         info->has_bps_wr_max  = cfg.buckets[THROTTLE_BPS_WRITE].max;
82c13163fbSBenoît Canet         info->bps_wr_max      = cfg.buckets[THROTTLE_BPS_WRITE].max;
83c13163fbSBenoît Canet 
84c13163fbSBenoît Canet         info->has_iops_max    = cfg.buckets[THROTTLE_OPS_TOTAL].max;
85c13163fbSBenoît Canet         info->iops_max        = cfg.buckets[THROTTLE_OPS_TOTAL].max;
86c13163fbSBenoît Canet         info->has_iops_rd_max = cfg.buckets[THROTTLE_OPS_READ].max;
87c13163fbSBenoît Canet         info->iops_rd_max     = cfg.buckets[THROTTLE_OPS_READ].max;
88c13163fbSBenoît Canet         info->has_iops_wr_max = cfg.buckets[THROTTLE_OPS_WRITE].max;
89c13163fbSBenoît Canet         info->iops_wr_max     = cfg.buckets[THROTTLE_OPS_WRITE].max;
90c13163fbSBenoît Canet 
91c13163fbSBenoît Canet         info->has_iops_size = cfg.op_size;
92c13163fbSBenoît Canet         info->iops_size = cfg.op_size;
93c13163fbSBenoît Canet     }
94c13163fbSBenoît Canet 
95e2462113SFrancesco Romani     info->write_threshold = bdrv_write_threshold_get(bs);
96e2462113SFrancesco Romani 
97*d5a8ee60SAlberto Garcia     bs0 = bs;
98*d5a8ee60SAlberto Garcia     p_image_info = &info->image;
99*d5a8ee60SAlberto Garcia     while (1) {
100*d5a8ee60SAlberto Garcia         Error *local_err = NULL;
101*d5a8ee60SAlberto Garcia         bdrv_query_image_info(bs0, p_image_info, &local_err);
102*d5a8ee60SAlberto Garcia         if (local_err) {
103*d5a8ee60SAlberto Garcia             error_propagate(errp, local_err);
104*d5a8ee60SAlberto Garcia             qapi_free_BlockDeviceInfo(info);
105*d5a8ee60SAlberto Garcia             return NULL;
106*d5a8ee60SAlberto Garcia         }
107*d5a8ee60SAlberto Garcia         if (bs0->drv && bs0->backing_hd) {
108*d5a8ee60SAlberto Garcia             bs0 = bs0->backing_hd;
109*d5a8ee60SAlberto Garcia             (*p_image_info)->has_backing_image = true;
110*d5a8ee60SAlberto Garcia             p_image_info = &((*p_image_info)->backing_image);
111*d5a8ee60SAlberto Garcia         } else {
112*d5a8ee60SAlberto Garcia             break;
113*d5a8ee60SAlberto Garcia         }
114*d5a8ee60SAlberto Garcia     }
115*d5a8ee60SAlberto Garcia 
116c13163fbSBenoît Canet     return info;
117c13163fbSBenoît Canet }
118c13163fbSBenoît Canet 
119fb0ed453SWenchao Xia /*
120fb0ed453SWenchao Xia  * Returns 0 on success, with *p_list either set to describe snapshot
121fb0ed453SWenchao Xia  * information, or NULL because there are no snapshots.  Returns -errno on
122fb0ed453SWenchao Xia  * error, with *p_list untouched.
123fb0ed453SWenchao Xia  */
124fb0ed453SWenchao Xia int bdrv_query_snapshot_info_list(BlockDriverState *bs,
125fb0ed453SWenchao Xia                                   SnapshotInfoList **p_list,
126fb0ed453SWenchao Xia                                   Error **errp)
127f364ec65SWenchao Xia {
128f364ec65SWenchao Xia     int i, sn_count;
129f364ec65SWenchao Xia     QEMUSnapshotInfo *sn_tab = NULL;
130fb0ed453SWenchao Xia     SnapshotInfoList *info_list, *cur_item = NULL, *head = NULL;
131fb0ed453SWenchao Xia     SnapshotInfo *info;
132fb0ed453SWenchao Xia 
133f364ec65SWenchao Xia     sn_count = bdrv_snapshot_list(bs, &sn_tab);
134fb0ed453SWenchao Xia     if (sn_count < 0) {
135fb0ed453SWenchao Xia         const char *dev = bdrv_get_device_name(bs);
136fb0ed453SWenchao Xia         switch (sn_count) {
137fb0ed453SWenchao Xia         case -ENOMEDIUM:
138fb0ed453SWenchao Xia             error_setg(errp, "Device '%s' is not inserted", dev);
139fb0ed453SWenchao Xia             break;
140fb0ed453SWenchao Xia         case -ENOTSUP:
141fb0ed453SWenchao Xia             error_setg(errp,
142fb0ed453SWenchao Xia                        "Device '%s' does not support internal snapshots",
143fb0ed453SWenchao Xia                        dev);
144fb0ed453SWenchao Xia             break;
145fb0ed453SWenchao Xia         default:
146fb0ed453SWenchao Xia             error_setg_errno(errp, -sn_count,
147fb0ed453SWenchao Xia                              "Can't list snapshots of device '%s'", dev);
148fb0ed453SWenchao Xia             break;
149fb0ed453SWenchao Xia         }
150fb0ed453SWenchao Xia         return sn_count;
151fb0ed453SWenchao Xia     }
152f364ec65SWenchao Xia 
153f364ec65SWenchao Xia     for (i = 0; i < sn_count; i++) {
154fb0ed453SWenchao Xia         info = g_new0(SnapshotInfo, 1);
155fb0ed453SWenchao Xia         info->id            = g_strdup(sn_tab[i].id_str);
156fb0ed453SWenchao Xia         info->name          = g_strdup(sn_tab[i].name);
157fb0ed453SWenchao Xia         info->vm_state_size = sn_tab[i].vm_state_size;
158fb0ed453SWenchao Xia         info->date_sec      = sn_tab[i].date_sec;
159fb0ed453SWenchao Xia         info->date_nsec     = sn_tab[i].date_nsec;
160fb0ed453SWenchao Xia         info->vm_clock_sec  = sn_tab[i].vm_clock_nsec / 1000000000;
161fb0ed453SWenchao Xia         info->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
162f364ec65SWenchao Xia 
163fb0ed453SWenchao Xia         info_list = g_new0(SnapshotInfoList, 1);
164fb0ed453SWenchao Xia         info_list->value = info;
165f364ec65SWenchao Xia 
166f364ec65SWenchao Xia         /* XXX: waiting for the qapi to support qemu-queue.h types */
167f364ec65SWenchao Xia         if (!cur_item) {
168fb0ed453SWenchao Xia             head = cur_item = info_list;
169f364ec65SWenchao Xia         } else {
170f364ec65SWenchao Xia             cur_item->next = info_list;
171f364ec65SWenchao Xia             cur_item = info_list;
172f364ec65SWenchao Xia         }
173f364ec65SWenchao Xia 
174f364ec65SWenchao Xia     }
175f364ec65SWenchao Xia 
176f364ec65SWenchao Xia     g_free(sn_tab);
177fb0ed453SWenchao Xia     *p_list = head;
178fb0ed453SWenchao Xia     return 0;
179f364ec65SWenchao Xia }
180f364ec65SWenchao Xia 
18143526ec8SWenchao Xia /**
18243526ec8SWenchao Xia  * bdrv_query_image_info:
18343526ec8SWenchao Xia  * @bs: block device to examine
18443526ec8SWenchao Xia  * @p_info: location to store image information
18543526ec8SWenchao Xia  * @errp: location to store error information
18643526ec8SWenchao Xia  *
187553a7e87SWenchao Xia  * Store "flat" image information in @p_info.
188553a7e87SWenchao Xia  *
189553a7e87SWenchao Xia  * "Flat" means it does *not* query backing image information,
190553a7e87SWenchao Xia  * i.e. (*pinfo)->has_backing_image will be set to false and
191553a7e87SWenchao Xia  * (*pinfo)->backing_image to NULL even when the image does in fact have
192553a7e87SWenchao Xia  * a backing image.
193553a7e87SWenchao Xia  *
19443526ec8SWenchao Xia  * @p_info will be set only on success. On error, store error in @errp.
19543526ec8SWenchao Xia  */
19643526ec8SWenchao Xia void bdrv_query_image_info(BlockDriverState *bs,
19743526ec8SWenchao Xia                            ImageInfo **p_info,
19843526ec8SWenchao Xia                            Error **errp)
199f364ec65SWenchao Xia {
20052bf1e72SMarkus Armbruster     int64_t size;
20143526ec8SWenchao Xia     const char *backing_filename;
202f364ec65SWenchao Xia     BlockDriverInfo bdi;
20343526ec8SWenchao Xia     int ret;
20443526ec8SWenchao Xia     Error *err = NULL;
20552bf1e72SMarkus Armbruster     ImageInfo *info;
206f364ec65SWenchao Xia 
20752bf1e72SMarkus Armbruster     size = bdrv_getlength(bs);
20852bf1e72SMarkus Armbruster     if (size < 0) {
20952bf1e72SMarkus Armbruster         error_setg_errno(errp, -size, "Can't get size of device '%s'",
21052bf1e72SMarkus Armbruster                          bdrv_get_device_name(bs));
21152bf1e72SMarkus Armbruster         return;
21252bf1e72SMarkus Armbruster     }
213f364ec65SWenchao Xia 
21452bf1e72SMarkus Armbruster     info = g_new0(ImageInfo, 1);
21543526ec8SWenchao Xia     info->filename        = g_strdup(bs->filename);
216f364ec65SWenchao Xia     info->format          = g_strdup(bdrv_get_format_name(bs));
21752bf1e72SMarkus Armbruster     info->virtual_size    = size;
218f364ec65SWenchao Xia     info->actual_size     = bdrv_get_allocated_file_size(bs);
219f364ec65SWenchao Xia     info->has_actual_size = info->actual_size >= 0;
220f364ec65SWenchao Xia     if (bdrv_is_encrypted(bs)) {
221f364ec65SWenchao Xia         info->encrypted = true;
222f364ec65SWenchao Xia         info->has_encrypted = true;
223f364ec65SWenchao Xia     }
224f364ec65SWenchao Xia     if (bdrv_get_info(bs, &bdi) >= 0) {
225f364ec65SWenchao Xia         if (bdi.cluster_size != 0) {
226f364ec65SWenchao Xia             info->cluster_size = bdi.cluster_size;
227f364ec65SWenchao Xia             info->has_cluster_size = true;
228f364ec65SWenchao Xia         }
229f364ec65SWenchao Xia         info->dirty_flag = bdi.is_dirty;
230f364ec65SWenchao Xia         info->has_dirty_flag = true;
231f364ec65SWenchao Xia     }
232eae041feSMax Reitz     info->format_specific     = bdrv_get_specific_info(bs);
233eae041feSMax Reitz     info->has_format_specific = info->format_specific != NULL;
234eae041feSMax Reitz 
23543526ec8SWenchao Xia     backing_filename = bs->backing_file;
236f364ec65SWenchao Xia     if (backing_filename[0] != '\0') {
2379a29e18fSJeff Cody         char *backing_filename2 = g_malloc0(PATH_MAX);
238f364ec65SWenchao Xia         info->backing_filename = g_strdup(backing_filename);
239f364ec65SWenchao Xia         info->has_backing_filename = true;
2409a29e18fSJeff Cody         bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err);
2419f07429eSMax Reitz         if (err) {
2429f07429eSMax Reitz             error_propagate(errp, err);
2439f07429eSMax Reitz             qapi_free_ImageInfo(info);
244564d64bdSJeff Cody             g_free(backing_filename2);
2459f07429eSMax Reitz             return;
2469f07429eSMax Reitz         }
247f364ec65SWenchao Xia 
248f364ec65SWenchao Xia         if (strcmp(backing_filename, backing_filename2) != 0) {
249f364ec65SWenchao Xia             info->full_backing_filename =
250f364ec65SWenchao Xia                         g_strdup(backing_filename2);
251f364ec65SWenchao Xia             info->has_full_backing_filename = true;
252f364ec65SWenchao Xia         }
253f364ec65SWenchao Xia 
254f364ec65SWenchao Xia         if (bs->backing_format[0]) {
255f364ec65SWenchao Xia             info->backing_filename_format = g_strdup(bs->backing_format);
256f364ec65SWenchao Xia             info->has_backing_filename_format = true;
257f364ec65SWenchao Xia         }
258564d64bdSJeff Cody         g_free(backing_filename2);
259f364ec65SWenchao Xia     }
26043526ec8SWenchao Xia 
26143526ec8SWenchao Xia     ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err);
26243526ec8SWenchao Xia     switch (ret) {
26343526ec8SWenchao Xia     case 0:
26443526ec8SWenchao Xia         if (info->snapshots) {
26543526ec8SWenchao Xia             info->has_snapshots = true;
26643526ec8SWenchao Xia         }
26743526ec8SWenchao Xia         break;
26843526ec8SWenchao Xia     /* recoverable error */
26943526ec8SWenchao Xia     case -ENOMEDIUM:
27043526ec8SWenchao Xia     case -ENOTSUP:
27143526ec8SWenchao Xia         error_free(err);
27243526ec8SWenchao Xia         break;
27343526ec8SWenchao Xia     default:
27443526ec8SWenchao Xia         error_propagate(errp, err);
27543526ec8SWenchao Xia         qapi_free_ImageInfo(info);
27643526ec8SWenchao Xia         return;
27743526ec8SWenchao Xia     }
27843526ec8SWenchao Xia 
27943526ec8SWenchao Xia     *p_info = info;
280f364ec65SWenchao Xia }
281f364ec65SWenchao Xia 
282553a7e87SWenchao Xia /* @p_info will be set only on success. */
283d829a211SMarkus Armbruster static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
284553a7e87SWenchao Xia                             Error **errp)
285f364ec65SWenchao Xia {
286f364ec65SWenchao Xia     BlockInfo *info = g_malloc0(sizeof(*info));
287d829a211SMarkus Armbruster     BlockDriverState *bs = blk_bs(blk);
288d829a211SMarkus Armbruster     info->device = g_strdup(blk_name(blk));
289f364ec65SWenchao Xia     info->type = g_strdup("unknown");
290a7f53e26SMarkus Armbruster     info->locked = blk_dev_is_medium_locked(blk);
291a7f53e26SMarkus Armbruster     info->removable = blk_dev_has_removable_media(blk);
292f364ec65SWenchao Xia 
293a7f53e26SMarkus Armbruster     if (blk_dev_has_removable_media(blk)) {
294f364ec65SWenchao Xia         info->has_tray_open = true;
295a7f53e26SMarkus Armbruster         info->tray_open = blk_dev_is_tray_open(blk);
296f364ec65SWenchao Xia     }
297f364ec65SWenchao Xia 
298f364ec65SWenchao Xia     if (bdrv_iostatus_is_enabled(bs)) {
299f364ec65SWenchao Xia         info->has_io_status = true;
300f364ec65SWenchao Xia         info->io_status = bs->iostatus;
301f364ec65SWenchao Xia     }
302f364ec65SWenchao Xia 
30321b56835SFam Zheng     if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
30421b56835SFam Zheng         info->has_dirty_bitmaps = true;
30521b56835SFam Zheng         info->dirty_bitmaps = bdrv_query_dirty_bitmaps(bs);
30621b56835SFam Zheng     }
30721b56835SFam Zheng 
308f364ec65SWenchao Xia     if (bs->drv) {
309f364ec65SWenchao Xia         info->has_inserted = true;
310*d5a8ee60SAlberto Garcia         info->inserted = bdrv_block_device_info(bs, errp);
311*d5a8ee60SAlberto Garcia         if (info->inserted == NULL) {
312553a7e87SWenchao Xia             goto err;
313f364ec65SWenchao Xia         }
314553a7e87SWenchao Xia     }
315553a7e87SWenchao Xia 
316553a7e87SWenchao Xia     *p_info = info;
317553a7e87SWenchao Xia     return;
318553a7e87SWenchao Xia 
319553a7e87SWenchao Xia  err:
320553a7e87SWenchao Xia     qapi_free_BlockInfo(info);
321f364ec65SWenchao Xia }
322f364ec65SWenchao Xia 
323f71eaa74SFam Zheng static BlockStats *bdrv_query_stats(const BlockDriverState *bs,
324f71eaa74SFam Zheng                                     bool query_backing)
325f364ec65SWenchao Xia {
326f364ec65SWenchao Xia     BlockStats *s;
327f364ec65SWenchao Xia 
328f364ec65SWenchao Xia     s = g_malloc0(sizeof(*s));
329f364ec65SWenchao Xia 
330bfb197e0SMarkus Armbruster     if (bdrv_get_device_name(bs)[0]) {
331f364ec65SWenchao Xia         s->has_device = true;
332bfb197e0SMarkus Armbruster         s->device = g_strdup(bdrv_get_device_name(bs));
333f364ec65SWenchao Xia     }
334f364ec65SWenchao Xia 
3354875a779SFam Zheng     if (bdrv_get_node_name(bs)[0]) {
3364875a779SFam Zheng         s->has_node_name = true;
3374875a779SFam Zheng         s->node_name = g_strdup(bdrv_get_node_name(bs));
3384875a779SFam Zheng     }
3394875a779SFam Zheng 
340f364ec65SWenchao Xia     s->stats = g_malloc0(sizeof(*s->stats));
34128298fd3SBenoît Canet     s->stats->rd_bytes = bs->stats.nr_bytes[BLOCK_ACCT_READ];
34228298fd3SBenoît Canet     s->stats->wr_bytes = bs->stats.nr_bytes[BLOCK_ACCT_WRITE];
34328298fd3SBenoît Canet     s->stats->rd_operations = bs->stats.nr_ops[BLOCK_ACCT_READ];
34428298fd3SBenoît Canet     s->stats->wr_operations = bs->stats.nr_ops[BLOCK_ACCT_WRITE];
345f4564d53SPeter Lieven     s->stats->rd_merged = bs->stats.merged[BLOCK_ACCT_READ];
346f4564d53SPeter Lieven     s->stats->wr_merged = bs->stats.merged[BLOCK_ACCT_WRITE];
3470ddd0ad9SBenoît Canet     s->stats->wr_highest_offset =
3480ddd0ad9SBenoît Canet         bs->stats.wr_highest_sector * BDRV_SECTOR_SIZE;
34928298fd3SBenoît Canet     s->stats->flush_operations = bs->stats.nr_ops[BLOCK_ACCT_FLUSH];
35028298fd3SBenoît Canet     s->stats->wr_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_WRITE];
35128298fd3SBenoît Canet     s->stats->rd_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_READ];
35228298fd3SBenoît Canet     s->stats->flush_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_FLUSH];
353f364ec65SWenchao Xia 
354f364ec65SWenchao Xia     if (bs->file) {
355f364ec65SWenchao Xia         s->has_parent = true;
356f71eaa74SFam Zheng         s->parent = bdrv_query_stats(bs->file, query_backing);
357f364ec65SWenchao Xia     }
358f364ec65SWenchao Xia 
359f71eaa74SFam Zheng     if (query_backing && bs->backing_hd) {
360c8059b97SFam Zheng         s->has_backing = true;
361f71eaa74SFam Zheng         s->backing = bdrv_query_stats(bs->backing_hd, query_backing);
362c8059b97SFam Zheng     }
363c8059b97SFam Zheng 
364f364ec65SWenchao Xia     return s;
365f364ec65SWenchao Xia }
366f364ec65SWenchao Xia 
367f364ec65SWenchao Xia BlockInfoList *qmp_query_block(Error **errp)
368f364ec65SWenchao Xia {
369f364ec65SWenchao Xia     BlockInfoList *head = NULL, **p_next = &head;
370d829a211SMarkus Armbruster     BlockBackend *blk;
371553a7e87SWenchao Xia     Error *local_err = NULL;
372f364ec65SWenchao Xia 
373d829a211SMarkus Armbruster     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
374f364ec65SWenchao Xia         BlockInfoList *info = g_malloc0(sizeof(*info));
375d829a211SMarkus Armbruster         bdrv_query_info(blk, &info->value, &local_err);
37684d18f06SMarkus Armbruster         if (local_err) {
377553a7e87SWenchao Xia             error_propagate(errp, local_err);
378553a7e87SWenchao Xia             goto err;
379553a7e87SWenchao Xia         }
380f364ec65SWenchao Xia 
381f364ec65SWenchao Xia         *p_next = info;
382f364ec65SWenchao Xia         p_next = &info->next;
383f364ec65SWenchao Xia     }
384f364ec65SWenchao Xia 
385f364ec65SWenchao Xia     return head;
386553a7e87SWenchao Xia 
387553a7e87SWenchao Xia  err:
388553a7e87SWenchao Xia     qapi_free_BlockInfoList(head);
389553a7e87SWenchao Xia     return NULL;
390f364ec65SWenchao Xia }
391f364ec65SWenchao Xia 
392f71eaa74SFam Zheng BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
393f71eaa74SFam Zheng                                      bool query_nodes,
394f71eaa74SFam Zheng                                      Error **errp)
395f364ec65SWenchao Xia {
396f364ec65SWenchao Xia     BlockStatsList *head = NULL, **p_next = &head;
397f364ec65SWenchao Xia     BlockDriverState *bs = NULL;
398f364ec65SWenchao Xia 
399f71eaa74SFam Zheng     /* Just to be safe if query_nodes is not always initialized */
400f71eaa74SFam Zheng     query_nodes = has_query_nodes && query_nodes;
401f71eaa74SFam Zheng 
402f71eaa74SFam Zheng     while ((bs = query_nodes ? bdrv_next_node(bs) : bdrv_next(bs))) {
403f364ec65SWenchao Xia         BlockStatsList *info = g_malloc0(sizeof(*info));
40413344f3aSStefan Hajnoczi         AioContext *ctx = bdrv_get_aio_context(bs);
40513344f3aSStefan Hajnoczi 
40613344f3aSStefan Hajnoczi         aio_context_acquire(ctx);
407f71eaa74SFam Zheng         info->value = bdrv_query_stats(bs, !query_nodes);
40813344f3aSStefan Hajnoczi         aio_context_release(ctx);
409f364ec65SWenchao Xia 
410f364ec65SWenchao Xia         *p_next = info;
411f364ec65SWenchao Xia         p_next = &info->next;
412f364ec65SWenchao Xia     }
413f364ec65SWenchao Xia 
414f364ec65SWenchao Xia     return head;
415f364ec65SWenchao Xia }
416f364ec65SWenchao Xia 
417f364ec65SWenchao Xia #define NB_SUFFIXES 4
418f364ec65SWenchao Xia 
419f364ec65SWenchao Xia static char *get_human_readable_size(char *buf, int buf_size, int64_t size)
420f364ec65SWenchao Xia {
4212c20fa2cSStefan Weil     static const char suffixes[NB_SUFFIXES] = {'K', 'M', 'G', 'T'};
422f364ec65SWenchao Xia     int64_t base;
423f364ec65SWenchao Xia     int i;
424f364ec65SWenchao Xia 
425f364ec65SWenchao Xia     if (size <= 999) {
426f364ec65SWenchao Xia         snprintf(buf, buf_size, "%" PRId64, size);
427f364ec65SWenchao Xia     } else {
428f364ec65SWenchao Xia         base = 1024;
429f364ec65SWenchao Xia         for (i = 0; i < NB_SUFFIXES; i++) {
430f364ec65SWenchao Xia             if (size < (10 * base)) {
431f364ec65SWenchao Xia                 snprintf(buf, buf_size, "%0.1f%c",
432f364ec65SWenchao Xia                          (double)size / base,
433f364ec65SWenchao Xia                          suffixes[i]);
434f364ec65SWenchao Xia                 break;
435f364ec65SWenchao Xia             } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
436f364ec65SWenchao Xia                 snprintf(buf, buf_size, "%" PRId64 "%c",
437f364ec65SWenchao Xia                          ((size + (base >> 1)) / base),
438f364ec65SWenchao Xia                          suffixes[i]);
439f364ec65SWenchao Xia                 break;
440f364ec65SWenchao Xia             }
441f364ec65SWenchao Xia             base = base * 1024;
442f364ec65SWenchao Xia         }
443f364ec65SWenchao Xia     }
444f364ec65SWenchao Xia     return buf;
445f364ec65SWenchao Xia }
446f364ec65SWenchao Xia 
4475b917044SWenchao Xia void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
4485b917044SWenchao Xia                         QEMUSnapshotInfo *sn)
449f364ec65SWenchao Xia {
450f364ec65SWenchao Xia     char buf1[128], date_buf[128], clock_buf[128];
451f364ec65SWenchao Xia     struct tm tm;
452f364ec65SWenchao Xia     time_t ti;
453f364ec65SWenchao Xia     int64_t secs;
454f364ec65SWenchao Xia 
455f364ec65SWenchao Xia     if (!sn) {
4565b917044SWenchao Xia         func_fprintf(f,
457f364ec65SWenchao Xia                      "%-10s%-20s%7s%20s%15s",
458f364ec65SWenchao Xia                      "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
459f364ec65SWenchao Xia     } else {
460f364ec65SWenchao Xia         ti = sn->date_sec;
461f364ec65SWenchao Xia         localtime_r(&ti, &tm);
462f364ec65SWenchao Xia         strftime(date_buf, sizeof(date_buf),
463f364ec65SWenchao Xia                  "%Y-%m-%d %H:%M:%S", &tm);
464f364ec65SWenchao Xia         secs = sn->vm_clock_nsec / 1000000000;
465f364ec65SWenchao Xia         snprintf(clock_buf, sizeof(clock_buf),
466f364ec65SWenchao Xia                  "%02d:%02d:%02d.%03d",
467f364ec65SWenchao Xia                  (int)(secs / 3600),
468f364ec65SWenchao Xia                  (int)((secs / 60) % 60),
469f364ec65SWenchao Xia                  (int)(secs % 60),
470f364ec65SWenchao Xia                  (int)((sn->vm_clock_nsec / 1000000) % 1000));
4715b917044SWenchao Xia         func_fprintf(f,
472f364ec65SWenchao Xia                      "%-10s%-20s%7s%20s%15s",
473f364ec65SWenchao Xia                      sn->id_str, sn->name,
4745b917044SWenchao Xia                      get_human_readable_size(buf1, sizeof(buf1),
4755b917044SWenchao Xia                                              sn->vm_state_size),
476f364ec65SWenchao Xia                      date_buf,
477f364ec65SWenchao Xia                      clock_buf);
478f364ec65SWenchao Xia     }
479f364ec65SWenchao Xia }
480f364ec65SWenchao Xia 
481a8d8ecb7SMax Reitz static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
482a8d8ecb7SMax Reitz                        QDict *dict);
483a8d8ecb7SMax Reitz static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
484a8d8ecb7SMax Reitz                        QList *list);
485a8d8ecb7SMax Reitz 
486a8d8ecb7SMax Reitz static void dump_qobject(fprintf_function func_fprintf, void *f,
487a8d8ecb7SMax Reitz                          int comp_indent, QObject *obj)
488a8d8ecb7SMax Reitz {
489a8d8ecb7SMax Reitz     switch (qobject_type(obj)) {
490a8d8ecb7SMax Reitz         case QTYPE_QINT: {
491a8d8ecb7SMax Reitz             QInt *value = qobject_to_qint(obj);
492a8d8ecb7SMax Reitz             func_fprintf(f, "%" PRId64, qint_get_int(value));
493a8d8ecb7SMax Reitz             break;
494a8d8ecb7SMax Reitz         }
495a8d8ecb7SMax Reitz         case QTYPE_QSTRING: {
496a8d8ecb7SMax Reitz             QString *value = qobject_to_qstring(obj);
497a8d8ecb7SMax Reitz             func_fprintf(f, "%s", qstring_get_str(value));
498a8d8ecb7SMax Reitz             break;
499a8d8ecb7SMax Reitz         }
500a8d8ecb7SMax Reitz         case QTYPE_QDICT: {
501a8d8ecb7SMax Reitz             QDict *value = qobject_to_qdict(obj);
502a8d8ecb7SMax Reitz             dump_qdict(func_fprintf, f, comp_indent, value);
503a8d8ecb7SMax Reitz             break;
504a8d8ecb7SMax Reitz         }
505a8d8ecb7SMax Reitz         case QTYPE_QLIST: {
506a8d8ecb7SMax Reitz             QList *value = qobject_to_qlist(obj);
507a8d8ecb7SMax Reitz             dump_qlist(func_fprintf, f, comp_indent, value);
508a8d8ecb7SMax Reitz             break;
509a8d8ecb7SMax Reitz         }
510a8d8ecb7SMax Reitz         case QTYPE_QFLOAT: {
511a8d8ecb7SMax Reitz             QFloat *value = qobject_to_qfloat(obj);
512a8d8ecb7SMax Reitz             func_fprintf(f, "%g", qfloat_get_double(value));
513a8d8ecb7SMax Reitz             break;
514a8d8ecb7SMax Reitz         }
515a8d8ecb7SMax Reitz         case QTYPE_QBOOL: {
516a8d8ecb7SMax Reitz             QBool *value = qobject_to_qbool(obj);
517a8d8ecb7SMax Reitz             func_fprintf(f, "%s", qbool_get_int(value) ? "true" : "false");
518a8d8ecb7SMax Reitz             break;
519a8d8ecb7SMax Reitz         }
520a8d8ecb7SMax Reitz         case QTYPE_QERROR: {
521a8d8ecb7SMax Reitz             QString *value = qerror_human((QError *)obj);
522a8d8ecb7SMax Reitz             func_fprintf(f, "%s", qstring_get_str(value));
523f25391c2SMarkus Armbruster             QDECREF(value);
524a8d8ecb7SMax Reitz             break;
525a8d8ecb7SMax Reitz         }
526a8d8ecb7SMax Reitz         case QTYPE_NONE:
527a8d8ecb7SMax Reitz             break;
528a8d8ecb7SMax Reitz         case QTYPE_MAX:
529a8d8ecb7SMax Reitz         default:
530a8d8ecb7SMax Reitz             abort();
531a8d8ecb7SMax Reitz     }
532a8d8ecb7SMax Reitz }
533a8d8ecb7SMax Reitz 
534a8d8ecb7SMax Reitz static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
535a8d8ecb7SMax Reitz                        QList *list)
536a8d8ecb7SMax Reitz {
537a8d8ecb7SMax Reitz     const QListEntry *entry;
538a8d8ecb7SMax Reitz     int i = 0;
539a8d8ecb7SMax Reitz 
540a8d8ecb7SMax Reitz     for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
541a8d8ecb7SMax Reitz         qtype_code type = qobject_type(entry->value);
542a8d8ecb7SMax Reitz         bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
543a8d8ecb7SMax Reitz         const char *format = composite ? "%*s[%i]:\n" : "%*s[%i]: ";
544a8d8ecb7SMax Reitz 
545a8d8ecb7SMax Reitz         func_fprintf(f, format, indentation * 4, "", i);
546a8d8ecb7SMax Reitz         dump_qobject(func_fprintf, f, indentation + 1, entry->value);
547a8d8ecb7SMax Reitz         if (!composite) {
548a8d8ecb7SMax Reitz             func_fprintf(f, "\n");
549a8d8ecb7SMax Reitz         }
550a8d8ecb7SMax Reitz     }
551a8d8ecb7SMax Reitz }
552a8d8ecb7SMax Reitz 
553a8d8ecb7SMax Reitz static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
554a8d8ecb7SMax Reitz                        QDict *dict)
555a8d8ecb7SMax Reitz {
556a8d8ecb7SMax Reitz     const QDictEntry *entry;
557a8d8ecb7SMax Reitz 
558a8d8ecb7SMax Reitz     for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) {
559a8d8ecb7SMax Reitz         qtype_code type = qobject_type(entry->value);
560a8d8ecb7SMax Reitz         bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
561a8d8ecb7SMax Reitz         const char *format = composite ? "%*s%s:\n" : "%*s%s: ";
562a8d8ecb7SMax Reitz         char key[strlen(entry->key) + 1];
563a8d8ecb7SMax Reitz         int i;
564a8d8ecb7SMax Reitz 
565a8d8ecb7SMax Reitz         /* replace dashes with spaces in key (variable) names */
566a8d8ecb7SMax Reitz         for (i = 0; entry->key[i]; i++) {
567a8d8ecb7SMax Reitz             key[i] = entry->key[i] == '-' ? ' ' : entry->key[i];
568a8d8ecb7SMax Reitz         }
569a8d8ecb7SMax Reitz         key[i] = 0;
570a8d8ecb7SMax Reitz 
571a8d8ecb7SMax Reitz         func_fprintf(f, format, indentation * 4, "", key);
572a8d8ecb7SMax Reitz         dump_qobject(func_fprintf, f, indentation + 1, entry->value);
573a8d8ecb7SMax Reitz         if (!composite) {
574a8d8ecb7SMax Reitz             func_fprintf(f, "\n");
575a8d8ecb7SMax Reitz         }
576a8d8ecb7SMax Reitz     }
577a8d8ecb7SMax Reitz }
578a8d8ecb7SMax Reitz 
579a8d8ecb7SMax Reitz void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
580a8d8ecb7SMax Reitz                                    ImageInfoSpecific *info_spec)
581a8d8ecb7SMax Reitz {
582a8d8ecb7SMax Reitz     QmpOutputVisitor *ov = qmp_output_visitor_new();
583a8d8ecb7SMax Reitz     QObject *obj, *data;
584a8d8ecb7SMax Reitz 
585a8d8ecb7SMax Reitz     visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
58635d0d40aSMax Reitz                                  &error_abort);
587a8d8ecb7SMax Reitz     obj = qmp_output_get_qobject(ov);
588a8d8ecb7SMax Reitz     assert(qobject_type(obj) == QTYPE_QDICT);
589a8d8ecb7SMax Reitz     data = qdict_get(qobject_to_qdict(obj), "data");
590a8d8ecb7SMax Reitz     dump_qobject(func_fprintf, f, 1, data);
591a8d8ecb7SMax Reitz     qmp_output_visitor_cleanup(ov);
592a8d8ecb7SMax Reitz }
593a8d8ecb7SMax Reitz 
5945b917044SWenchao Xia void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
5955b917044SWenchao Xia                           ImageInfo *info)
596f364ec65SWenchao Xia {
597f364ec65SWenchao Xia     char size_buf[128], dsize_buf[128];
598f364ec65SWenchao Xia     if (!info->has_actual_size) {
599f364ec65SWenchao Xia         snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
600f364ec65SWenchao Xia     } else {
601f364ec65SWenchao Xia         get_human_readable_size(dsize_buf, sizeof(dsize_buf),
602f364ec65SWenchao Xia                                 info->actual_size);
603f364ec65SWenchao Xia     }
604f364ec65SWenchao Xia     get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size);
6055b917044SWenchao Xia     func_fprintf(f,
6065b917044SWenchao Xia                  "image: %s\n"
607f364ec65SWenchao Xia                  "file format: %s\n"
608f364ec65SWenchao Xia                  "virtual size: %s (%" PRId64 " bytes)\n"
609f364ec65SWenchao Xia                  "disk size: %s\n",
610f364ec65SWenchao Xia                  info->filename, info->format, size_buf,
611f364ec65SWenchao Xia                  info->virtual_size,
612f364ec65SWenchao Xia                  dsize_buf);
613f364ec65SWenchao Xia 
614f364ec65SWenchao Xia     if (info->has_encrypted && info->encrypted) {
6155b917044SWenchao Xia         func_fprintf(f, "encrypted: yes\n");
616f364ec65SWenchao Xia     }
617f364ec65SWenchao Xia 
618f364ec65SWenchao Xia     if (info->has_cluster_size) {
6195b917044SWenchao Xia         func_fprintf(f, "cluster_size: %" PRId64 "\n",
6205b917044SWenchao Xia                        info->cluster_size);
621f364ec65SWenchao Xia     }
622f364ec65SWenchao Xia 
623f364ec65SWenchao Xia     if (info->has_dirty_flag && info->dirty_flag) {
6245b917044SWenchao Xia         func_fprintf(f, "cleanly shut down: no\n");
625f364ec65SWenchao Xia     }
626f364ec65SWenchao Xia 
627f364ec65SWenchao Xia     if (info->has_backing_filename) {
6285b917044SWenchao Xia         func_fprintf(f, "backing file: %s", info->backing_filename);
629f364ec65SWenchao Xia         if (info->has_full_backing_filename) {
6305b917044SWenchao Xia             func_fprintf(f, " (actual path: %s)", info->full_backing_filename);
631f364ec65SWenchao Xia         }
6325b917044SWenchao Xia         func_fprintf(f, "\n");
633f364ec65SWenchao Xia         if (info->has_backing_filename_format) {
6345b917044SWenchao Xia             func_fprintf(f, "backing file format: %s\n",
6355b917044SWenchao Xia                          info->backing_filename_format);
636f364ec65SWenchao Xia         }
637f364ec65SWenchao Xia     }
638f364ec65SWenchao Xia 
639f364ec65SWenchao Xia     if (info->has_snapshots) {
640f364ec65SWenchao Xia         SnapshotInfoList *elem;
641f364ec65SWenchao Xia 
6425b917044SWenchao Xia         func_fprintf(f, "Snapshot list:\n");
6435b917044SWenchao Xia         bdrv_snapshot_dump(func_fprintf, f, NULL);
6445b917044SWenchao Xia         func_fprintf(f, "\n");
645f364ec65SWenchao Xia 
646f364ec65SWenchao Xia         /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but
647f364ec65SWenchao Xia          * we convert to the block layer's native QEMUSnapshotInfo for now.
648f364ec65SWenchao Xia          */
649f364ec65SWenchao Xia         for (elem = info->snapshots; elem; elem = elem->next) {
650f364ec65SWenchao Xia             QEMUSnapshotInfo sn = {
651f364ec65SWenchao Xia                 .vm_state_size = elem->value->vm_state_size,
652f364ec65SWenchao Xia                 .date_sec = elem->value->date_sec,
653f364ec65SWenchao Xia                 .date_nsec = elem->value->date_nsec,
654f364ec65SWenchao Xia                 .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL +
655f364ec65SWenchao Xia                                  elem->value->vm_clock_nsec,
656f364ec65SWenchao Xia             };
657f364ec65SWenchao Xia 
658f364ec65SWenchao Xia             pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id);
659f364ec65SWenchao Xia             pstrcpy(sn.name, sizeof(sn.name), elem->value->name);
6605b917044SWenchao Xia             bdrv_snapshot_dump(func_fprintf, f, &sn);
6615b917044SWenchao Xia             func_fprintf(f, "\n");
662f364ec65SWenchao Xia         }
663f364ec65SWenchao Xia     }
664a8d8ecb7SMax Reitz 
665a8d8ecb7SMax Reitz     if (info->has_format_specific) {
666a8d8ecb7SMax Reitz         func_fprintf(f, "Format specific information:\n");
667a8d8ecb7SMax Reitz         bdrv_image_info_specific_dump(func_fprintf, f, info->format_specific);
668a8d8ecb7SMax Reitz     }
669f364ec65SWenchao Xia }
670