1 /* 2 * Block layer qmp and info dump related functions 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "block/qapi.h" 26 #include "block/block_int.h" 27 #include "qmp-commands.h" 28 29 /* 30 * Returns 0 on success, with *p_list either set to describe snapshot 31 * information, or NULL because there are no snapshots. Returns -errno on 32 * error, with *p_list untouched. 33 */ 34 int bdrv_query_snapshot_info_list(BlockDriverState *bs, 35 SnapshotInfoList **p_list, 36 Error **errp) 37 { 38 int i, sn_count; 39 QEMUSnapshotInfo *sn_tab = NULL; 40 SnapshotInfoList *info_list, *cur_item = NULL, *head = NULL; 41 SnapshotInfo *info; 42 43 sn_count = bdrv_snapshot_list(bs, &sn_tab); 44 if (sn_count < 0) { 45 const char *dev = bdrv_get_device_name(bs); 46 switch (sn_count) { 47 case -ENOMEDIUM: 48 error_setg(errp, "Device '%s' is not inserted", dev); 49 break; 50 case -ENOTSUP: 51 error_setg(errp, 52 "Device '%s' does not support internal snapshots", 53 dev); 54 break; 55 default: 56 error_setg_errno(errp, -sn_count, 57 "Can't list snapshots of device '%s'", dev); 58 break; 59 } 60 return sn_count; 61 } 62 63 for (i = 0; i < sn_count; i++) { 64 info = g_new0(SnapshotInfo, 1); 65 info->id = g_strdup(sn_tab[i].id_str); 66 info->name = g_strdup(sn_tab[i].name); 67 info->vm_state_size = sn_tab[i].vm_state_size; 68 info->date_sec = sn_tab[i].date_sec; 69 info->date_nsec = sn_tab[i].date_nsec; 70 info->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; 71 info->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; 72 73 info_list = g_new0(SnapshotInfoList, 1); 74 info_list->value = info; 75 76 /* XXX: waiting for the qapi to support qemu-queue.h types */ 77 if (!cur_item) { 78 head = cur_item = info_list; 79 } else { 80 cur_item->next = info_list; 81 cur_item = info_list; 82 } 83 84 } 85 86 g_free(sn_tab); 87 *p_list = head; 88 return 0; 89 } 90 91 /** 92 * bdrv_query_image_info: 93 * @bs: block device to examine 94 * @p_info: location to store image information 95 * @errp: location to store error information 96 * 97 * Store "flat" image information in @p_info. 98 * 99 * "Flat" means it does *not* query backing image information, 100 * i.e. (*pinfo)->has_backing_image will be set to false and 101 * (*pinfo)->backing_image to NULL even when the image does in fact have 102 * a backing image. 103 * 104 * @p_info will be set only on success. On error, store error in @errp. 105 */ 106 void bdrv_query_image_info(BlockDriverState *bs, 107 ImageInfo **p_info, 108 Error **errp) 109 { 110 uint64_t total_sectors; 111 const char *backing_filename; 112 char backing_filename2[1024]; 113 BlockDriverInfo bdi; 114 int ret; 115 Error *err = NULL; 116 ImageInfo *info = g_new0(ImageInfo, 1); 117 118 bdrv_get_geometry(bs, &total_sectors); 119 120 info->filename = g_strdup(bs->filename); 121 info->format = g_strdup(bdrv_get_format_name(bs)); 122 info->virtual_size = total_sectors * 512; 123 info->actual_size = bdrv_get_allocated_file_size(bs); 124 info->has_actual_size = info->actual_size >= 0; 125 if (bdrv_is_encrypted(bs)) { 126 info->encrypted = true; 127 info->has_encrypted = true; 128 } 129 if (bdrv_get_info(bs, &bdi) >= 0) { 130 if (bdi.cluster_size != 0) { 131 info->cluster_size = bdi.cluster_size; 132 info->has_cluster_size = true; 133 } 134 info->dirty_flag = bdi.is_dirty; 135 info->has_dirty_flag = true; 136 } 137 backing_filename = bs->backing_file; 138 if (backing_filename[0] != '\0') { 139 info->backing_filename = g_strdup(backing_filename); 140 info->has_backing_filename = true; 141 bdrv_get_full_backing_filename(bs, backing_filename2, 142 sizeof(backing_filename2)); 143 144 if (strcmp(backing_filename, backing_filename2) != 0) { 145 info->full_backing_filename = 146 g_strdup(backing_filename2); 147 info->has_full_backing_filename = true; 148 } 149 150 if (bs->backing_format[0]) { 151 info->backing_filename_format = g_strdup(bs->backing_format); 152 info->has_backing_filename_format = true; 153 } 154 } 155 156 ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err); 157 switch (ret) { 158 case 0: 159 if (info->snapshots) { 160 info->has_snapshots = true; 161 } 162 break; 163 /* recoverable error */ 164 case -ENOMEDIUM: 165 case -ENOTSUP: 166 error_free(err); 167 break; 168 default: 169 error_propagate(errp, err); 170 qapi_free_ImageInfo(info); 171 return; 172 } 173 174 *p_info = info; 175 } 176 177 /* @p_info will be set only on success. */ 178 void bdrv_query_info(BlockDriverState *bs, 179 BlockInfo **p_info, 180 Error **errp) 181 { 182 BlockInfo *info = g_malloc0(sizeof(*info)); 183 BlockDriverState *bs0; 184 ImageInfo **p_image_info; 185 Error *local_err = NULL; 186 info->device = g_strdup(bs->device_name); 187 info->type = g_strdup("unknown"); 188 info->locked = bdrv_dev_is_medium_locked(bs); 189 info->removable = bdrv_dev_has_removable_media(bs); 190 191 if (bdrv_dev_has_removable_media(bs)) { 192 info->has_tray_open = true; 193 info->tray_open = bdrv_dev_is_tray_open(bs); 194 } 195 196 if (bdrv_iostatus_is_enabled(bs)) { 197 info->has_io_status = true; 198 info->io_status = bs->iostatus; 199 } 200 201 if (bs->dirty_bitmap) { 202 info->has_dirty = true; 203 info->dirty = g_malloc0(sizeof(*info->dirty)); 204 info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE; 205 info->dirty->granularity = 206 ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap)); 207 } 208 209 if (bs->drv) { 210 info->has_inserted = true; 211 info->inserted = g_malloc0(sizeof(*info->inserted)); 212 info->inserted->file = g_strdup(bs->filename); 213 info->inserted->ro = bs->read_only; 214 info->inserted->drv = g_strdup(bs->drv->format_name); 215 info->inserted->encrypted = bs->encrypted; 216 info->inserted->encryption_key_missing = bdrv_key_required(bs); 217 218 if (bs->backing_file[0]) { 219 info->inserted->has_backing_file = true; 220 info->inserted->backing_file = g_strdup(bs->backing_file); 221 } 222 223 info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs); 224 225 if (bs->io_limits_enabled) { 226 ThrottleConfig cfg; 227 throttle_get_config(&bs->throttle_state, &cfg); 228 info->inserted->bps = cfg.buckets[THROTTLE_BPS_TOTAL].avg; 229 info->inserted->bps_rd = cfg.buckets[THROTTLE_BPS_READ].avg; 230 info->inserted->bps_wr = cfg.buckets[THROTTLE_BPS_WRITE].avg; 231 232 info->inserted->iops = cfg.buckets[THROTTLE_OPS_TOTAL].avg; 233 info->inserted->iops_rd = cfg.buckets[THROTTLE_OPS_READ].avg; 234 info->inserted->iops_wr = cfg.buckets[THROTTLE_OPS_WRITE].avg; 235 236 info->inserted->has_bps_max = 237 cfg.buckets[THROTTLE_BPS_TOTAL].max; 238 info->inserted->bps_max = 239 cfg.buckets[THROTTLE_BPS_TOTAL].max; 240 info->inserted->has_bps_rd_max = 241 cfg.buckets[THROTTLE_BPS_READ].max; 242 info->inserted->bps_rd_max = 243 cfg.buckets[THROTTLE_BPS_READ].max; 244 info->inserted->has_bps_wr_max = 245 cfg.buckets[THROTTLE_BPS_WRITE].max; 246 info->inserted->bps_wr_max = 247 cfg.buckets[THROTTLE_BPS_WRITE].max; 248 249 info->inserted->has_iops_max = 250 cfg.buckets[THROTTLE_OPS_TOTAL].max; 251 info->inserted->iops_max = 252 cfg.buckets[THROTTLE_OPS_TOTAL].max; 253 info->inserted->has_iops_rd_max = 254 cfg.buckets[THROTTLE_OPS_READ].max; 255 info->inserted->iops_rd_max = 256 cfg.buckets[THROTTLE_OPS_READ].max; 257 info->inserted->has_iops_wr_max = 258 cfg.buckets[THROTTLE_OPS_WRITE].max; 259 info->inserted->iops_wr_max = 260 cfg.buckets[THROTTLE_OPS_WRITE].max; 261 262 info->inserted->has_iops_size = cfg.op_size; 263 info->inserted->iops_size = cfg.op_size; 264 } 265 266 bs0 = bs; 267 p_image_info = &info->inserted->image; 268 while (1) { 269 bdrv_query_image_info(bs0, p_image_info, &local_err); 270 if (error_is_set(&local_err)) { 271 error_propagate(errp, local_err); 272 goto err; 273 } 274 if (bs0->drv && bs0->backing_hd) { 275 bs0 = bs0->backing_hd; 276 (*p_image_info)->has_backing_image = true; 277 p_image_info = &((*p_image_info)->backing_image); 278 } else { 279 break; 280 } 281 } 282 } 283 284 *p_info = info; 285 return; 286 287 err: 288 qapi_free_BlockInfo(info); 289 } 290 291 BlockStats *bdrv_query_stats(const BlockDriverState *bs) 292 { 293 BlockStats *s; 294 295 s = g_malloc0(sizeof(*s)); 296 297 if (bs->device_name[0]) { 298 s->has_device = true; 299 s->device = g_strdup(bs->device_name); 300 } 301 302 s->stats = g_malloc0(sizeof(*s->stats)); 303 s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ]; 304 s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE]; 305 s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ]; 306 s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE]; 307 s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE; 308 s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH]; 309 s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE]; 310 s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ]; 311 s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH]; 312 313 if (bs->file) { 314 s->has_parent = true; 315 s->parent = bdrv_query_stats(bs->file); 316 } 317 318 return s; 319 } 320 321 BlockInfoList *qmp_query_block(Error **errp) 322 { 323 BlockInfoList *head = NULL, **p_next = &head; 324 BlockDriverState *bs = NULL; 325 Error *local_err = NULL; 326 327 while ((bs = bdrv_next(bs))) { 328 BlockInfoList *info = g_malloc0(sizeof(*info)); 329 bdrv_query_info(bs, &info->value, &local_err); 330 if (error_is_set(&local_err)) { 331 error_propagate(errp, local_err); 332 goto err; 333 } 334 335 *p_next = info; 336 p_next = &info->next; 337 } 338 339 return head; 340 341 err: 342 qapi_free_BlockInfoList(head); 343 return NULL; 344 } 345 346 BlockStatsList *qmp_query_blockstats(Error **errp) 347 { 348 BlockStatsList *head = NULL, **p_next = &head; 349 BlockDriverState *bs = NULL; 350 351 while ((bs = bdrv_next(bs))) { 352 BlockStatsList *info = g_malloc0(sizeof(*info)); 353 info->value = bdrv_query_stats(bs); 354 355 *p_next = info; 356 p_next = &info->next; 357 } 358 359 return head; 360 } 361 362 #define NB_SUFFIXES 4 363 364 static char *get_human_readable_size(char *buf, int buf_size, int64_t size) 365 { 366 static const char suffixes[NB_SUFFIXES] = "KMGT"; 367 int64_t base; 368 int i; 369 370 if (size <= 999) { 371 snprintf(buf, buf_size, "%" PRId64, size); 372 } else { 373 base = 1024; 374 for (i = 0; i < NB_SUFFIXES; i++) { 375 if (size < (10 * base)) { 376 snprintf(buf, buf_size, "%0.1f%c", 377 (double)size / base, 378 suffixes[i]); 379 break; 380 } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { 381 snprintf(buf, buf_size, "%" PRId64 "%c", 382 ((size + (base >> 1)) / base), 383 suffixes[i]); 384 break; 385 } 386 base = base * 1024; 387 } 388 } 389 return buf; 390 } 391 392 void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, 393 QEMUSnapshotInfo *sn) 394 { 395 char buf1[128], date_buf[128], clock_buf[128]; 396 struct tm tm; 397 time_t ti; 398 int64_t secs; 399 400 if (!sn) { 401 func_fprintf(f, 402 "%-10s%-20s%7s%20s%15s", 403 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); 404 } else { 405 ti = sn->date_sec; 406 localtime_r(&ti, &tm); 407 strftime(date_buf, sizeof(date_buf), 408 "%Y-%m-%d %H:%M:%S", &tm); 409 secs = sn->vm_clock_nsec / 1000000000; 410 snprintf(clock_buf, sizeof(clock_buf), 411 "%02d:%02d:%02d.%03d", 412 (int)(secs / 3600), 413 (int)((secs / 60) % 60), 414 (int)(secs % 60), 415 (int)((sn->vm_clock_nsec / 1000000) % 1000)); 416 func_fprintf(f, 417 "%-10s%-20s%7s%20s%15s", 418 sn->id_str, sn->name, 419 get_human_readable_size(buf1, sizeof(buf1), 420 sn->vm_state_size), 421 date_buf, 422 clock_buf); 423 } 424 } 425 426 void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, 427 ImageInfo *info) 428 { 429 char size_buf[128], dsize_buf[128]; 430 if (!info->has_actual_size) { 431 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); 432 } else { 433 get_human_readable_size(dsize_buf, sizeof(dsize_buf), 434 info->actual_size); 435 } 436 get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size); 437 func_fprintf(f, 438 "image: %s\n" 439 "file format: %s\n" 440 "virtual size: %s (%" PRId64 " bytes)\n" 441 "disk size: %s\n", 442 info->filename, info->format, size_buf, 443 info->virtual_size, 444 dsize_buf); 445 446 if (info->has_encrypted && info->encrypted) { 447 func_fprintf(f, "encrypted: yes\n"); 448 } 449 450 if (info->has_cluster_size) { 451 func_fprintf(f, "cluster_size: %" PRId64 "\n", 452 info->cluster_size); 453 } 454 455 if (info->has_dirty_flag && info->dirty_flag) { 456 func_fprintf(f, "cleanly shut down: no\n"); 457 } 458 459 if (info->has_backing_filename) { 460 func_fprintf(f, "backing file: %s", info->backing_filename); 461 if (info->has_full_backing_filename) { 462 func_fprintf(f, " (actual path: %s)", info->full_backing_filename); 463 } 464 func_fprintf(f, "\n"); 465 if (info->has_backing_filename_format) { 466 func_fprintf(f, "backing file format: %s\n", 467 info->backing_filename_format); 468 } 469 } 470 471 if (info->has_snapshots) { 472 SnapshotInfoList *elem; 473 474 func_fprintf(f, "Snapshot list:\n"); 475 bdrv_snapshot_dump(func_fprintf, f, NULL); 476 func_fprintf(f, "\n"); 477 478 /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but 479 * we convert to the block layer's native QEMUSnapshotInfo for now. 480 */ 481 for (elem = info->snapshots; elem; elem = elem->next) { 482 QEMUSnapshotInfo sn = { 483 .vm_state_size = elem->value->vm_state_size, 484 .date_sec = elem->value->date_sec, 485 .date_nsec = elem->value->date_nsec, 486 .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL + 487 elem->value->vm_clock_nsec, 488 }; 489 490 pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); 491 pstrcpy(sn.name, sizeof(sn.name), elem->value->name); 492 bdrv_snapshot_dump(func_fprintf, f, &sn); 493 func_fprintf(f, "\n"); 494 } 495 } 496 } 497