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 info->inserted->bps = 227 bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]; 228 info->inserted->bps_rd = 229 bs->io_limits.bps[BLOCK_IO_LIMIT_READ]; 230 info->inserted->bps_wr = 231 bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE]; 232 info->inserted->iops = 233 bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]; 234 info->inserted->iops_rd = 235 bs->io_limits.iops[BLOCK_IO_LIMIT_READ]; 236 info->inserted->iops_wr = 237 bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE]; 238 } 239 240 bs0 = bs; 241 p_image_info = &info->inserted->image; 242 while (1) { 243 bdrv_query_image_info(bs0, p_image_info, &local_err); 244 if (error_is_set(&local_err)) { 245 error_propagate(errp, local_err); 246 goto err; 247 } 248 if (bs0->drv && bs0->backing_hd) { 249 bs0 = bs0->backing_hd; 250 (*p_image_info)->has_backing_image = true; 251 p_image_info = &((*p_image_info)->backing_image); 252 } else { 253 break; 254 } 255 } 256 } 257 258 *p_info = info; 259 return; 260 261 err: 262 qapi_free_BlockInfo(info); 263 } 264 265 BlockStats *bdrv_query_stats(const BlockDriverState *bs) 266 { 267 BlockStats *s; 268 269 s = g_malloc0(sizeof(*s)); 270 271 if (bs->device_name[0]) { 272 s->has_device = true; 273 s->device = g_strdup(bs->device_name); 274 } 275 276 s->stats = g_malloc0(sizeof(*s->stats)); 277 s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ]; 278 s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE]; 279 s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ]; 280 s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE]; 281 s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE; 282 s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH]; 283 s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE]; 284 s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ]; 285 s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH]; 286 287 if (bs->file) { 288 s->has_parent = true; 289 s->parent = bdrv_query_stats(bs->file); 290 } 291 292 return s; 293 } 294 295 BlockInfoList *qmp_query_block(Error **errp) 296 { 297 BlockInfoList *head = NULL, **p_next = &head; 298 BlockDriverState *bs = NULL; 299 Error *local_err = NULL; 300 301 while ((bs = bdrv_next(bs))) { 302 BlockInfoList *info = g_malloc0(sizeof(*info)); 303 bdrv_query_info(bs, &info->value, &local_err); 304 if (error_is_set(&local_err)) { 305 error_propagate(errp, local_err); 306 goto err; 307 } 308 309 *p_next = info; 310 p_next = &info->next; 311 } 312 313 return head; 314 315 err: 316 qapi_free_BlockInfoList(head); 317 return NULL; 318 } 319 320 BlockStatsList *qmp_query_blockstats(Error **errp) 321 { 322 BlockStatsList *head = NULL, **p_next = &head; 323 BlockDriverState *bs = NULL; 324 325 while ((bs = bdrv_next(bs))) { 326 BlockStatsList *info = g_malloc0(sizeof(*info)); 327 info->value = bdrv_query_stats(bs); 328 329 *p_next = info; 330 p_next = &info->next; 331 } 332 333 return head; 334 } 335 336 #define NB_SUFFIXES 4 337 338 static char *get_human_readable_size(char *buf, int buf_size, int64_t size) 339 { 340 static const char suffixes[NB_SUFFIXES] = "KMGT"; 341 int64_t base; 342 int i; 343 344 if (size <= 999) { 345 snprintf(buf, buf_size, "%" PRId64, size); 346 } else { 347 base = 1024; 348 for (i = 0; i < NB_SUFFIXES; i++) { 349 if (size < (10 * base)) { 350 snprintf(buf, buf_size, "%0.1f%c", 351 (double)size / base, 352 suffixes[i]); 353 break; 354 } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { 355 snprintf(buf, buf_size, "%" PRId64 "%c", 356 ((size + (base >> 1)) / base), 357 suffixes[i]); 358 break; 359 } 360 base = base * 1024; 361 } 362 } 363 return buf; 364 } 365 366 void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, 367 QEMUSnapshotInfo *sn) 368 { 369 char buf1[128], date_buf[128], clock_buf[128]; 370 struct tm tm; 371 time_t ti; 372 int64_t secs; 373 374 if (!sn) { 375 func_fprintf(f, 376 "%-10s%-20s%7s%20s%15s", 377 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); 378 } else { 379 ti = sn->date_sec; 380 localtime_r(&ti, &tm); 381 strftime(date_buf, sizeof(date_buf), 382 "%Y-%m-%d %H:%M:%S", &tm); 383 secs = sn->vm_clock_nsec / 1000000000; 384 snprintf(clock_buf, sizeof(clock_buf), 385 "%02d:%02d:%02d.%03d", 386 (int)(secs / 3600), 387 (int)((secs / 60) % 60), 388 (int)(secs % 60), 389 (int)((sn->vm_clock_nsec / 1000000) % 1000)); 390 func_fprintf(f, 391 "%-10s%-20s%7s%20s%15s", 392 sn->id_str, sn->name, 393 get_human_readable_size(buf1, sizeof(buf1), 394 sn->vm_state_size), 395 date_buf, 396 clock_buf); 397 } 398 } 399 400 void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, 401 ImageInfo *info) 402 { 403 char size_buf[128], dsize_buf[128]; 404 if (!info->has_actual_size) { 405 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); 406 } else { 407 get_human_readable_size(dsize_buf, sizeof(dsize_buf), 408 info->actual_size); 409 } 410 get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size); 411 func_fprintf(f, 412 "image: %s\n" 413 "file format: %s\n" 414 "virtual size: %s (%" PRId64 " bytes)\n" 415 "disk size: %s\n", 416 info->filename, info->format, size_buf, 417 info->virtual_size, 418 dsize_buf); 419 420 if (info->has_encrypted && info->encrypted) { 421 func_fprintf(f, "encrypted: yes\n"); 422 } 423 424 if (info->has_cluster_size) { 425 func_fprintf(f, "cluster_size: %" PRId64 "\n", 426 info->cluster_size); 427 } 428 429 if (info->has_dirty_flag && info->dirty_flag) { 430 func_fprintf(f, "cleanly shut down: no\n"); 431 } 432 433 if (info->has_backing_filename) { 434 func_fprintf(f, "backing file: %s", info->backing_filename); 435 if (info->has_full_backing_filename) { 436 func_fprintf(f, " (actual path: %s)", info->full_backing_filename); 437 } 438 func_fprintf(f, "\n"); 439 if (info->has_backing_filename_format) { 440 func_fprintf(f, "backing file format: %s\n", 441 info->backing_filename_format); 442 } 443 } 444 445 if (info->has_snapshots) { 446 SnapshotInfoList *elem; 447 448 func_fprintf(f, "Snapshot list:\n"); 449 bdrv_snapshot_dump(func_fprintf, f, NULL); 450 func_fprintf(f, "\n"); 451 452 /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but 453 * we convert to the block layer's native QEMUSnapshotInfo for now. 454 */ 455 for (elem = info->snapshots; elem; elem = elem->next) { 456 QEMUSnapshotInfo sn = { 457 .vm_state_size = elem->value->vm_state_size, 458 .date_sec = elem->value->date_sec, 459 .date_nsec = elem->value->date_nsec, 460 .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL + 461 elem->value->vm_clock_nsec, 462 }; 463 464 pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); 465 pstrcpy(sn.name, sizeof(sn.name), elem->value->name); 466 bdrv_snapshot_dump(func_fprintf, f, &sn); 467 func_fprintf(f, "\n"); 468 } 469 } 470 } 471