1 /* 2 * Command line utility to exercise the QEMU I/O path. 3 * 4 * Copyright (C) 2009-2016 Red Hat, Inc. 5 * Copyright (c) 2003-2005 Silicon Graphics, Inc. 6 * 7 * This work is licensed under the terms of the GNU GPL, version 2 or later. 8 * See the COPYING file in the top-level directory. 9 */ 10 11 #include "qemu/osdep.h" 12 #include "qapi/error.h" 13 #include "qemu-io.h" 14 #include "sysemu/block-backend.h" 15 #include "block/block.h" 16 #include "block/block_int.h" /* for info_f() */ 17 #include "block/qapi.h" 18 #include "qemu/error-report.h" 19 #include "qemu/main-loop.h" 20 #include "qemu/timer.h" 21 #include "sysemu/block-backend.h" 22 #include "qemu/cutils.h" 23 24 #define CMD_NOFILE_OK 0x01 25 26 bool qemuio_misalign; 27 28 static cmdinfo_t *cmdtab; 29 static int ncmds; 30 31 static int compare_cmdname(const void *a, const void *b) 32 { 33 return strcmp(((const cmdinfo_t *)a)->name, 34 ((const cmdinfo_t *)b)->name); 35 } 36 37 void qemuio_add_command(const cmdinfo_t *ci) 38 { 39 cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds); 40 cmdtab[ncmds - 1] = *ci; 41 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname); 42 } 43 44 int qemuio_command_usage(const cmdinfo_t *ci) 45 { 46 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline); 47 return 0; 48 } 49 50 static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct) 51 { 52 if (ct->flags & CMD_FLAG_GLOBAL) { 53 return 1; 54 } 55 if (!(ct->flags & CMD_NOFILE_OK) && !blk) { 56 fprintf(stderr, "no file open, try 'help open'\n"); 57 return 0; 58 } 59 return 1; 60 } 61 62 static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc, 63 char **argv) 64 { 65 char *cmd = argv[0]; 66 67 if (!init_check_command(blk, ct)) { 68 return 0; 69 } 70 71 if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) { 72 if (ct->argmax == -1) { 73 fprintf(stderr, 74 "bad argument count %d to %s, expected at least %d arguments\n", 75 argc-1, cmd, ct->argmin); 76 } else if (ct->argmin == ct->argmax) { 77 fprintf(stderr, 78 "bad argument count %d to %s, expected %d arguments\n", 79 argc-1, cmd, ct->argmin); 80 } else { 81 fprintf(stderr, 82 "bad argument count %d to %s, expected between %d and %d arguments\n", 83 argc-1, cmd, ct->argmin, ct->argmax); 84 } 85 return 0; 86 } 87 optind = 0; 88 return ct->cfunc(blk, argc, argv); 89 } 90 91 static const cmdinfo_t *find_command(const char *cmd) 92 { 93 cmdinfo_t *ct; 94 95 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) { 96 if (strcmp(ct->name, cmd) == 0 || 97 (ct->altname && strcmp(ct->altname, cmd) == 0)) 98 { 99 return (const cmdinfo_t *)ct; 100 } 101 } 102 return NULL; 103 } 104 105 /* Invoke fn() for commands with a matching prefix */ 106 void qemuio_complete_command(const char *input, 107 void (*fn)(const char *cmd, void *opaque), 108 void *opaque) 109 { 110 cmdinfo_t *ct; 111 size_t input_len = strlen(input); 112 113 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) { 114 if (strncmp(input, ct->name, input_len) == 0) { 115 fn(ct->name, opaque); 116 } 117 } 118 } 119 120 static char **breakline(char *input, int *count) 121 { 122 int c = 0; 123 char *p; 124 char **rval = g_new0(char *, 1); 125 126 while (rval && (p = qemu_strsep(&input, " ")) != NULL) { 127 if (!*p) { 128 continue; 129 } 130 c++; 131 rval = g_renew(char *, rval, (c + 1)); 132 rval[c - 1] = p; 133 rval[c] = NULL; 134 } 135 *count = c; 136 return rval; 137 } 138 139 static int64_t cvtnum(const char *s) 140 { 141 char *end; 142 int64_t ret; 143 144 ret = qemu_strtosz_suffix(s, &end, QEMU_STRTOSZ_DEFSUFFIX_B); 145 if (*end != '\0') { 146 /* Detritus at the end of the string */ 147 return -EINVAL; 148 } 149 return ret; 150 } 151 152 static void print_cvtnum_err(int64_t rc, const char *arg) 153 { 154 switch (rc) { 155 case -EINVAL: 156 printf("Parsing error: non-numeric argument," 157 " or extraneous/unrecognized suffix -- %s\n", arg); 158 break; 159 case -ERANGE: 160 printf("Parsing error: argument too large -- %s\n", arg); 161 break; 162 default: 163 printf("Parsing error: %s\n", arg); 164 } 165 } 166 167 #define EXABYTES(x) ((long long)(x) << 60) 168 #define PETABYTES(x) ((long long)(x) << 50) 169 #define TERABYTES(x) ((long long)(x) << 40) 170 #define GIGABYTES(x) ((long long)(x) << 30) 171 #define MEGABYTES(x) ((long long)(x) << 20) 172 #define KILOBYTES(x) ((long long)(x) << 10) 173 174 #define TO_EXABYTES(x) ((x) / EXABYTES(1)) 175 #define TO_PETABYTES(x) ((x) / PETABYTES(1)) 176 #define TO_TERABYTES(x) ((x) / TERABYTES(1)) 177 #define TO_GIGABYTES(x) ((x) / GIGABYTES(1)) 178 #define TO_MEGABYTES(x) ((x) / MEGABYTES(1)) 179 #define TO_KILOBYTES(x) ((x) / KILOBYTES(1)) 180 181 static void cvtstr(double value, char *str, size_t size) 182 { 183 char *trim; 184 const char *suffix; 185 186 if (value >= EXABYTES(1)) { 187 suffix = " EiB"; 188 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value)); 189 } else if (value >= PETABYTES(1)) { 190 suffix = " PiB"; 191 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value)); 192 } else if (value >= TERABYTES(1)) { 193 suffix = " TiB"; 194 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value)); 195 } else if (value >= GIGABYTES(1)) { 196 suffix = " GiB"; 197 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value)); 198 } else if (value >= MEGABYTES(1)) { 199 suffix = " MiB"; 200 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value)); 201 } else if (value >= KILOBYTES(1)) { 202 suffix = " KiB"; 203 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value)); 204 } else { 205 suffix = " bytes"; 206 snprintf(str, size - 6, "%f", value); 207 } 208 209 trim = strstr(str, ".000"); 210 if (trim) { 211 strcpy(trim, suffix); 212 } else { 213 strcat(str, suffix); 214 } 215 } 216 217 218 219 static struct timeval tsub(struct timeval t1, struct timeval t2) 220 { 221 t1.tv_usec -= t2.tv_usec; 222 if (t1.tv_usec < 0) { 223 t1.tv_usec += 1000000; 224 t1.tv_sec--; 225 } 226 t1.tv_sec -= t2.tv_sec; 227 return t1; 228 } 229 230 static double tdiv(double value, struct timeval tv) 231 { 232 return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0)); 233 } 234 235 #define HOURS(sec) ((sec) / (60 * 60)) 236 #define MINUTES(sec) (((sec) % (60 * 60)) / 60) 237 #define SECONDS(sec) ((sec) % 60) 238 239 enum { 240 DEFAULT_TIME = 0x0, 241 TERSE_FIXED_TIME = 0x1, 242 VERBOSE_FIXED_TIME = 0x2, 243 }; 244 245 static void timestr(struct timeval *tv, char *ts, size_t size, int format) 246 { 247 double usec = (double)tv->tv_usec / 1000000.0; 248 249 if (format & TERSE_FIXED_TIME) { 250 if (!HOURS(tv->tv_sec)) { 251 snprintf(ts, size, "%u:%02u.%02u", 252 (unsigned int) MINUTES(tv->tv_sec), 253 (unsigned int) SECONDS(tv->tv_sec), 254 (unsigned int) (usec * 100)); 255 return; 256 } 257 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */ 258 } 259 260 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) { 261 snprintf(ts, size, "%u:%02u:%02u.%02u", 262 (unsigned int) HOURS(tv->tv_sec), 263 (unsigned int) MINUTES(tv->tv_sec), 264 (unsigned int) SECONDS(tv->tv_sec), 265 (unsigned int) (usec * 100)); 266 } else { 267 snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000)); 268 } 269 } 270 271 /* 272 * Parse the pattern argument to various sub-commands. 273 * 274 * Because the pattern is used as an argument to memset it must evaluate 275 * to an unsigned integer that fits into a single byte. 276 */ 277 static int parse_pattern(const char *arg) 278 { 279 char *endptr = NULL; 280 long pattern; 281 282 pattern = strtol(arg, &endptr, 0); 283 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') { 284 printf("%s is not a valid pattern byte\n", arg); 285 return -1; 286 } 287 288 return pattern; 289 } 290 291 /* 292 * Memory allocation helpers. 293 * 294 * Make sure memory is aligned by default, or purposefully misaligned if 295 * that is specified on the command line. 296 */ 297 298 #define MISALIGN_OFFSET 16 299 static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern) 300 { 301 void *buf; 302 303 if (qemuio_misalign) { 304 len += MISALIGN_OFFSET; 305 } 306 buf = blk_blockalign(blk, len); 307 memset(buf, pattern, len); 308 if (qemuio_misalign) { 309 buf += MISALIGN_OFFSET; 310 } 311 return buf; 312 } 313 314 static void qemu_io_free(void *p) 315 { 316 if (qemuio_misalign) { 317 p -= MISALIGN_OFFSET; 318 } 319 qemu_vfree(p); 320 } 321 322 static void dump_buffer(const void *buffer, int64_t offset, int64_t len) 323 { 324 uint64_t i; 325 int j; 326 const uint8_t *p; 327 328 for (i = 0, p = buffer; i < len; i += 16) { 329 const uint8_t *s = p; 330 331 printf("%08" PRIx64 ": ", offset + i); 332 for (j = 0; j < 16 && i + j < len; j++, p++) { 333 printf("%02x ", *p); 334 } 335 printf(" "); 336 for (j = 0; j < 16 && i + j < len; j++, s++) { 337 if (isalnum(*s)) { 338 printf("%c", *s); 339 } else { 340 printf("."); 341 } 342 } 343 printf("\n"); 344 } 345 } 346 347 static void print_report(const char *op, struct timeval *t, int64_t offset, 348 int64_t count, int64_t total, int cnt, bool Cflag) 349 { 350 char s1[64], s2[64], ts[64]; 351 352 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); 353 if (!Cflag) { 354 cvtstr((double)total, s1, sizeof(s1)); 355 cvtstr(tdiv((double)total, *t), s2, sizeof(s2)); 356 printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n", 357 op, total, count, offset); 358 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n", 359 s1, cnt, ts, s2, tdiv((double)cnt, *t)); 360 } else {/* bytes,ops,time,bytes/sec,ops/sec */ 361 printf("%"PRId64",%d,%s,%.3f,%.3f\n", 362 total, cnt, ts, 363 tdiv((double)total, *t), 364 tdiv((double)cnt, *t)); 365 } 366 } 367 368 /* 369 * Parse multiple length statements for vectored I/O, and construct an I/O 370 * vector matching it. 371 */ 372 static void * 373 create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov, 374 int pattern) 375 { 376 size_t *sizes = g_new0(size_t, nr_iov); 377 size_t count = 0; 378 void *buf = NULL; 379 void *p; 380 int i; 381 382 for (i = 0; i < nr_iov; i++) { 383 char *arg = argv[i]; 384 int64_t len; 385 386 len = cvtnum(arg); 387 if (len < 0) { 388 print_cvtnum_err(len, arg); 389 goto fail; 390 } 391 392 if (len > SIZE_MAX) { 393 printf("Argument '%s' exceeds maximum size %llu\n", arg, 394 (unsigned long long)SIZE_MAX); 395 goto fail; 396 } 397 398 sizes[i] = len; 399 count += len; 400 } 401 402 qemu_iovec_init(qiov, nr_iov); 403 404 buf = p = qemu_io_alloc(blk, count, pattern); 405 406 for (i = 0; i < nr_iov; i++) { 407 qemu_iovec_add(qiov, p, sizes[i]); 408 p += sizes[i]; 409 } 410 411 fail: 412 g_free(sizes); 413 return buf; 414 } 415 416 static int do_pread(BlockBackend *blk, char *buf, int64_t offset, 417 int64_t count, int64_t *total) 418 { 419 if (count > INT_MAX) { 420 return -ERANGE; 421 } 422 423 *total = blk_pread(blk, offset, (uint8_t *)buf, count); 424 if (*total < 0) { 425 return *total; 426 } 427 return 1; 428 } 429 430 static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset, 431 int64_t count, int flags, int64_t *total) 432 { 433 if (count > INT_MAX) { 434 return -ERANGE; 435 } 436 437 *total = blk_pwrite(blk, offset, (uint8_t *)buf, count, flags); 438 if (*total < 0) { 439 return *total; 440 } 441 return 1; 442 } 443 444 typedef struct { 445 BlockBackend *blk; 446 int64_t offset; 447 int64_t count; 448 int64_t *total; 449 int flags; 450 int ret; 451 bool done; 452 } CoWriteZeroes; 453 454 static void coroutine_fn co_pwrite_zeroes_entry(void *opaque) 455 { 456 CoWriteZeroes *data = opaque; 457 458 data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->count, 459 data->flags); 460 data->done = true; 461 if (data->ret < 0) { 462 *data->total = data->ret; 463 return; 464 } 465 466 *data->total = data->count; 467 } 468 469 static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset, 470 int64_t count, int flags, int64_t *total) 471 { 472 Coroutine *co; 473 CoWriteZeroes data = { 474 .blk = blk, 475 .offset = offset, 476 .count = count, 477 .total = total, 478 .flags = flags, 479 .done = false, 480 }; 481 482 if (count > INT_MAX) { 483 return -ERANGE; 484 } 485 486 co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data); 487 qemu_coroutine_enter(co); 488 while (!data.done) { 489 aio_poll(blk_get_aio_context(blk), true); 490 } 491 if (data.ret < 0) { 492 return data.ret; 493 } else { 494 return 1; 495 } 496 } 497 498 static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset, 499 int64_t count, int64_t *total) 500 { 501 int ret; 502 503 if (count >> 9 > BDRV_REQUEST_MAX_SECTORS) { 504 return -ERANGE; 505 } 506 507 ret = blk_pwrite_compressed(blk, offset, buf, count); 508 if (ret < 0) { 509 return ret; 510 } 511 *total = count; 512 return 1; 513 } 514 515 static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset, 516 int64_t count, int64_t *total) 517 { 518 if (count > INT_MAX) { 519 return -ERANGE; 520 } 521 522 *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count); 523 if (*total < 0) { 524 return *total; 525 } 526 return 1; 527 } 528 529 static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset, 530 int64_t count, int64_t *total) 531 { 532 if (count > INT_MAX) { 533 return -ERANGE; 534 } 535 536 *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count); 537 if (*total < 0) { 538 return *total; 539 } 540 return 1; 541 } 542 543 #define NOT_DONE 0x7fffffff 544 static void aio_rw_done(void *opaque, int ret) 545 { 546 *(int *)opaque = ret; 547 } 548 549 static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov, 550 int64_t offset, int *total) 551 { 552 int async_ret = NOT_DONE; 553 554 blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret); 555 while (async_ret == NOT_DONE) { 556 main_loop_wait(false); 557 } 558 559 *total = qiov->size; 560 return async_ret < 0 ? async_ret : 1; 561 } 562 563 static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov, 564 int64_t offset, int flags, int *total) 565 { 566 int async_ret = NOT_DONE; 567 568 blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret); 569 while (async_ret == NOT_DONE) { 570 main_loop_wait(false); 571 } 572 573 *total = qiov->size; 574 return async_ret < 0 ? async_ret : 1; 575 } 576 577 static void read_help(void) 578 { 579 printf( 580 "\n" 581 " reads a range of bytes from the given offset\n" 582 "\n" 583 " Example:\n" 584 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 585 "\n" 586 " Reads a segment of the currently open file, optionally dumping it to the\n" 587 " standard output stream (with -v option) for subsequent inspection.\n" 588 " -b, -- read from the VM state rather than the virtual disk\n" 589 " -C, -- report statistics in a machine parsable format\n" 590 " -l, -- length for pattern verification (only with -P)\n" 591 " -p, -- ignored for backwards compatibility\n" 592 " -P, -- use a pattern to verify read data\n" 593 " -q, -- quiet mode, do not show I/O statistics\n" 594 " -s, -- start offset for pattern verification (only with -P)\n" 595 " -v, -- dump buffer to standard output\n" 596 "\n"); 597 } 598 599 static int read_f(BlockBackend *blk, int argc, char **argv); 600 601 static const cmdinfo_t read_cmd = { 602 .name = "read", 603 .altname = "r", 604 .cfunc = read_f, 605 .argmin = 2, 606 .argmax = -1, 607 .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len", 608 .oneline = "reads a number of bytes at a specified offset", 609 .help = read_help, 610 }; 611 612 static int read_f(BlockBackend *blk, int argc, char **argv) 613 { 614 struct timeval t1, t2; 615 bool Cflag = false, qflag = false, vflag = false; 616 bool Pflag = false, sflag = false, lflag = false, bflag = false; 617 int c, cnt; 618 char *buf; 619 int64_t offset; 620 int64_t count; 621 /* Some compilers get confused and warn if this is not initialized. */ 622 int64_t total = 0; 623 int pattern = 0; 624 int64_t pattern_offset = 0, pattern_count = 0; 625 626 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) { 627 switch (c) { 628 case 'b': 629 bflag = true; 630 break; 631 case 'C': 632 Cflag = true; 633 break; 634 case 'l': 635 lflag = true; 636 pattern_count = cvtnum(optarg); 637 if (pattern_count < 0) { 638 print_cvtnum_err(pattern_count, optarg); 639 return 0; 640 } 641 break; 642 case 'p': 643 /* Ignored for backwards compatibility */ 644 break; 645 case 'P': 646 Pflag = true; 647 pattern = parse_pattern(optarg); 648 if (pattern < 0) { 649 return 0; 650 } 651 break; 652 case 'q': 653 qflag = true; 654 break; 655 case 's': 656 sflag = true; 657 pattern_offset = cvtnum(optarg); 658 if (pattern_offset < 0) { 659 print_cvtnum_err(pattern_offset, optarg); 660 return 0; 661 } 662 break; 663 case 'v': 664 vflag = true; 665 break; 666 default: 667 return qemuio_command_usage(&read_cmd); 668 } 669 } 670 671 if (optind != argc - 2) { 672 return qemuio_command_usage(&read_cmd); 673 } 674 675 offset = cvtnum(argv[optind]); 676 if (offset < 0) { 677 print_cvtnum_err(offset, argv[optind]); 678 return 0; 679 } 680 681 optind++; 682 count = cvtnum(argv[optind]); 683 if (count < 0) { 684 print_cvtnum_err(count, argv[optind]); 685 return 0; 686 } else if (count > SIZE_MAX) { 687 printf("length cannot exceed %" PRIu64 ", given %s\n", 688 (uint64_t) SIZE_MAX, argv[optind]); 689 return 0; 690 } 691 692 if (!Pflag && (lflag || sflag)) { 693 return qemuio_command_usage(&read_cmd); 694 } 695 696 if (!lflag) { 697 pattern_count = count - pattern_offset; 698 } 699 700 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 701 printf("pattern verification range exceeds end of read data\n"); 702 return 0; 703 } 704 705 if (bflag) { 706 if (offset & 0x1ff) { 707 printf("offset %" PRId64 " is not sector aligned\n", 708 offset); 709 return 0; 710 } 711 if (count & 0x1ff) { 712 printf("count %"PRId64" is not sector aligned\n", 713 count); 714 return 0; 715 } 716 } 717 718 buf = qemu_io_alloc(blk, count, 0xab); 719 720 gettimeofday(&t1, NULL); 721 if (bflag) { 722 cnt = do_load_vmstate(blk, buf, offset, count, &total); 723 } else { 724 cnt = do_pread(blk, buf, offset, count, &total); 725 } 726 gettimeofday(&t2, NULL); 727 728 if (cnt < 0) { 729 printf("read failed: %s\n", strerror(-cnt)); 730 goto out; 731 } 732 733 if (Pflag) { 734 void *cmp_buf = g_malloc(pattern_count); 735 memset(cmp_buf, pattern, pattern_count); 736 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 737 printf("Pattern verification failed at offset %" 738 PRId64 ", %"PRId64" bytes\n", 739 offset + pattern_offset, pattern_count); 740 } 741 g_free(cmp_buf); 742 } 743 744 if (qflag) { 745 goto out; 746 } 747 748 if (vflag) { 749 dump_buffer(buf, offset, count); 750 } 751 752 /* Finally, report back -- -C gives a parsable format */ 753 t2 = tsub(t2, t1); 754 print_report("read", &t2, offset, count, total, cnt, Cflag); 755 756 out: 757 qemu_io_free(buf); 758 759 return 0; 760 } 761 762 static void readv_help(void) 763 { 764 printf( 765 "\n" 766 " reads a range of bytes from the given offset into multiple buffers\n" 767 "\n" 768 " Example:\n" 769 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 770 "\n" 771 " Reads a segment of the currently open file, optionally dumping it to the\n" 772 " standard output stream (with -v option) for subsequent inspection.\n" 773 " Uses multiple iovec buffers if more than one byte range is specified.\n" 774 " -C, -- report statistics in a machine parsable format\n" 775 " -P, -- use a pattern to verify read data\n" 776 " -v, -- dump buffer to standard output\n" 777 " -q, -- quiet mode, do not show I/O statistics\n" 778 "\n"); 779 } 780 781 static int readv_f(BlockBackend *blk, int argc, char **argv); 782 783 static const cmdinfo_t readv_cmd = { 784 .name = "readv", 785 .cfunc = readv_f, 786 .argmin = 2, 787 .argmax = -1, 788 .args = "[-Cqv] [-P pattern] off len [len..]", 789 .oneline = "reads a number of bytes at a specified offset", 790 .help = readv_help, 791 }; 792 793 static int readv_f(BlockBackend *blk, int argc, char **argv) 794 { 795 struct timeval t1, t2; 796 bool Cflag = false, qflag = false, vflag = false; 797 int c, cnt; 798 char *buf; 799 int64_t offset; 800 /* Some compilers get confused and warn if this is not initialized. */ 801 int total = 0; 802 int nr_iov; 803 QEMUIOVector qiov; 804 int pattern = 0; 805 bool Pflag = false; 806 807 while ((c = getopt(argc, argv, "CP:qv")) != -1) { 808 switch (c) { 809 case 'C': 810 Cflag = true; 811 break; 812 case 'P': 813 Pflag = true; 814 pattern = parse_pattern(optarg); 815 if (pattern < 0) { 816 return 0; 817 } 818 break; 819 case 'q': 820 qflag = true; 821 break; 822 case 'v': 823 vflag = true; 824 break; 825 default: 826 return qemuio_command_usage(&readv_cmd); 827 } 828 } 829 830 if (optind > argc - 2) { 831 return qemuio_command_usage(&readv_cmd); 832 } 833 834 835 offset = cvtnum(argv[optind]); 836 if (offset < 0) { 837 print_cvtnum_err(offset, argv[optind]); 838 return 0; 839 } 840 optind++; 841 842 nr_iov = argc - optind; 843 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab); 844 if (buf == NULL) { 845 return 0; 846 } 847 848 gettimeofday(&t1, NULL); 849 cnt = do_aio_readv(blk, &qiov, offset, &total); 850 gettimeofday(&t2, NULL); 851 852 if (cnt < 0) { 853 printf("readv failed: %s\n", strerror(-cnt)); 854 goto out; 855 } 856 857 if (Pflag) { 858 void *cmp_buf = g_malloc(qiov.size); 859 memset(cmp_buf, pattern, qiov.size); 860 if (memcmp(buf, cmp_buf, qiov.size)) { 861 printf("Pattern verification failed at offset %" 862 PRId64 ", %zd bytes\n", offset, qiov.size); 863 } 864 g_free(cmp_buf); 865 } 866 867 if (qflag) { 868 goto out; 869 } 870 871 if (vflag) { 872 dump_buffer(buf, offset, qiov.size); 873 } 874 875 /* Finally, report back -- -C gives a parsable format */ 876 t2 = tsub(t2, t1); 877 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 878 879 out: 880 qemu_iovec_destroy(&qiov); 881 qemu_io_free(buf); 882 return 0; 883 } 884 885 static void write_help(void) 886 { 887 printf( 888 "\n" 889 " writes a range of bytes from the given offset\n" 890 "\n" 891 " Example:\n" 892 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 893 "\n" 894 " Writes into a segment of the currently open file, using a buffer\n" 895 " filled with a set pattern (0xcdcdcdcd).\n" 896 " -b, -- write to the VM state rather than the virtual disk\n" 897 " -c, -- write compressed data with blk_write_compressed\n" 898 " -f, -- use Force Unit Access semantics\n" 899 " -p, -- ignored for backwards compatibility\n" 900 " -P, -- use different pattern to fill file\n" 901 " -C, -- report statistics in a machine parsable format\n" 902 " -q, -- quiet mode, do not show I/O statistics\n" 903 " -u, -- with -z, allow unmapping\n" 904 " -z, -- write zeroes using blk_co_pwrite_zeroes\n" 905 "\n"); 906 } 907 908 static int write_f(BlockBackend *blk, int argc, char **argv); 909 910 static const cmdinfo_t write_cmd = { 911 .name = "write", 912 .altname = "w", 913 .cfunc = write_f, 914 .argmin = 2, 915 .argmax = -1, 916 .args = "[-bcCfquz] [-P pattern] off len", 917 .oneline = "writes a number of bytes at a specified offset", 918 .help = write_help, 919 }; 920 921 static int write_f(BlockBackend *blk, int argc, char **argv) 922 { 923 struct timeval t1, t2; 924 bool Cflag = false, qflag = false, bflag = false; 925 bool Pflag = false, zflag = false, cflag = false; 926 int flags = 0; 927 int c, cnt; 928 char *buf = NULL; 929 int64_t offset; 930 int64_t count; 931 /* Some compilers get confused and warn if this is not initialized. */ 932 int64_t total = 0; 933 int pattern = 0xcd; 934 935 while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) { 936 switch (c) { 937 case 'b': 938 bflag = true; 939 break; 940 case 'c': 941 cflag = true; 942 break; 943 case 'C': 944 Cflag = true; 945 break; 946 case 'f': 947 flags |= BDRV_REQ_FUA; 948 break; 949 case 'p': 950 /* Ignored for backwards compatibility */ 951 break; 952 case 'P': 953 Pflag = true; 954 pattern = parse_pattern(optarg); 955 if (pattern < 0) { 956 return 0; 957 } 958 break; 959 case 'q': 960 qflag = true; 961 break; 962 case 'u': 963 flags |= BDRV_REQ_MAY_UNMAP; 964 break; 965 case 'z': 966 zflag = true; 967 break; 968 default: 969 return qemuio_command_usage(&write_cmd); 970 } 971 } 972 973 if (optind != argc - 2) { 974 return qemuio_command_usage(&write_cmd); 975 } 976 977 if (bflag && zflag) { 978 printf("-b and -z cannot be specified at the same time\n"); 979 return 0; 980 } 981 982 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) { 983 printf("-f and -b or -c cannot be specified at the same time\n"); 984 return 0; 985 } 986 987 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) { 988 printf("-u requires -z to be specified\n"); 989 return 0; 990 } 991 992 if (zflag && Pflag) { 993 printf("-z and -P cannot be specified at the same time\n"); 994 return 0; 995 } 996 997 offset = cvtnum(argv[optind]); 998 if (offset < 0) { 999 print_cvtnum_err(offset, argv[optind]); 1000 return 0; 1001 } 1002 1003 optind++; 1004 count = cvtnum(argv[optind]); 1005 if (count < 0) { 1006 print_cvtnum_err(count, argv[optind]); 1007 return 0; 1008 } else if (count > SIZE_MAX) { 1009 printf("length cannot exceed %" PRIu64 ", given %s\n", 1010 (uint64_t) SIZE_MAX, argv[optind]); 1011 return 0; 1012 } 1013 1014 if (bflag || cflag) { 1015 if (offset & 0x1ff) { 1016 printf("offset %" PRId64 " is not sector aligned\n", 1017 offset); 1018 return 0; 1019 } 1020 1021 if (count & 0x1ff) { 1022 printf("count %"PRId64" is not sector aligned\n", 1023 count); 1024 return 0; 1025 } 1026 } 1027 1028 if (!zflag) { 1029 buf = qemu_io_alloc(blk, count, pattern); 1030 } 1031 1032 gettimeofday(&t1, NULL); 1033 if (bflag) { 1034 cnt = do_save_vmstate(blk, buf, offset, count, &total); 1035 } else if (zflag) { 1036 cnt = do_co_pwrite_zeroes(blk, offset, count, flags, &total); 1037 } else if (cflag) { 1038 cnt = do_write_compressed(blk, buf, offset, count, &total); 1039 } else { 1040 cnt = do_pwrite(blk, buf, offset, count, flags, &total); 1041 } 1042 gettimeofday(&t2, NULL); 1043 1044 if (cnt < 0) { 1045 printf("write failed: %s\n", strerror(-cnt)); 1046 goto out; 1047 } 1048 1049 if (qflag) { 1050 goto out; 1051 } 1052 1053 /* Finally, report back -- -C gives a parsable format */ 1054 t2 = tsub(t2, t1); 1055 print_report("wrote", &t2, offset, count, total, cnt, Cflag); 1056 1057 out: 1058 if (!zflag) { 1059 qemu_io_free(buf); 1060 } 1061 1062 return 0; 1063 } 1064 1065 static void 1066 writev_help(void) 1067 { 1068 printf( 1069 "\n" 1070 " writes a range of bytes from the given offset source from multiple buffers\n" 1071 "\n" 1072 " Example:\n" 1073 " 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1074 "\n" 1075 " Writes into a segment of the currently open file, using a buffer\n" 1076 " filled with a set pattern (0xcdcdcdcd).\n" 1077 " -P, -- use different pattern to fill file\n" 1078 " -C, -- report statistics in a machine parsable format\n" 1079 " -f, -- use Force Unit Access semantics\n" 1080 " -q, -- quiet mode, do not show I/O statistics\n" 1081 "\n"); 1082 } 1083 1084 static int writev_f(BlockBackend *blk, int argc, char **argv); 1085 1086 static const cmdinfo_t writev_cmd = { 1087 .name = "writev", 1088 .cfunc = writev_f, 1089 .argmin = 2, 1090 .argmax = -1, 1091 .args = "[-Cfq] [-P pattern] off len [len..]", 1092 .oneline = "writes a number of bytes at a specified offset", 1093 .help = writev_help, 1094 }; 1095 1096 static int writev_f(BlockBackend *blk, int argc, char **argv) 1097 { 1098 struct timeval t1, t2; 1099 bool Cflag = false, qflag = false; 1100 int flags = 0; 1101 int c, cnt; 1102 char *buf; 1103 int64_t offset; 1104 /* Some compilers get confused and warn if this is not initialized. */ 1105 int total = 0; 1106 int nr_iov; 1107 int pattern = 0xcd; 1108 QEMUIOVector qiov; 1109 1110 while ((c = getopt(argc, argv, "CfqP:")) != -1) { 1111 switch (c) { 1112 case 'C': 1113 Cflag = true; 1114 break; 1115 case 'f': 1116 flags |= BDRV_REQ_FUA; 1117 break; 1118 case 'q': 1119 qflag = true; 1120 break; 1121 case 'P': 1122 pattern = parse_pattern(optarg); 1123 if (pattern < 0) { 1124 return 0; 1125 } 1126 break; 1127 default: 1128 return qemuio_command_usage(&writev_cmd); 1129 } 1130 } 1131 1132 if (optind > argc - 2) { 1133 return qemuio_command_usage(&writev_cmd); 1134 } 1135 1136 offset = cvtnum(argv[optind]); 1137 if (offset < 0) { 1138 print_cvtnum_err(offset, argv[optind]); 1139 return 0; 1140 } 1141 optind++; 1142 1143 nr_iov = argc - optind; 1144 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern); 1145 if (buf == NULL) { 1146 return 0; 1147 } 1148 1149 gettimeofday(&t1, NULL); 1150 cnt = do_aio_writev(blk, &qiov, offset, flags, &total); 1151 gettimeofday(&t2, NULL); 1152 1153 if (cnt < 0) { 1154 printf("writev failed: %s\n", strerror(-cnt)); 1155 goto out; 1156 } 1157 1158 if (qflag) { 1159 goto out; 1160 } 1161 1162 /* Finally, report back -- -C gives a parsable format */ 1163 t2 = tsub(t2, t1); 1164 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 1165 out: 1166 qemu_iovec_destroy(&qiov); 1167 qemu_io_free(buf); 1168 return 0; 1169 } 1170 1171 struct aio_ctx { 1172 BlockBackend *blk; 1173 QEMUIOVector qiov; 1174 int64_t offset; 1175 char *buf; 1176 bool qflag; 1177 bool vflag; 1178 bool Cflag; 1179 bool Pflag; 1180 bool zflag; 1181 BlockAcctCookie acct; 1182 int pattern; 1183 struct timeval t1; 1184 }; 1185 1186 static void aio_write_done(void *opaque, int ret) 1187 { 1188 struct aio_ctx *ctx = opaque; 1189 struct timeval t2; 1190 1191 gettimeofday(&t2, NULL); 1192 1193 1194 if (ret < 0) { 1195 printf("aio_write failed: %s\n", strerror(-ret)); 1196 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct); 1197 goto out; 1198 } 1199 1200 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct); 1201 1202 if (ctx->qflag) { 1203 goto out; 1204 } 1205 1206 /* Finally, report back -- -C gives a parsable format */ 1207 t2 = tsub(t2, ctx->t1); 1208 print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1209 ctx->qiov.size, 1, ctx->Cflag); 1210 out: 1211 if (!ctx->zflag) { 1212 qemu_io_free(ctx->buf); 1213 qemu_iovec_destroy(&ctx->qiov); 1214 } 1215 g_free(ctx); 1216 } 1217 1218 static void aio_read_done(void *opaque, int ret) 1219 { 1220 struct aio_ctx *ctx = opaque; 1221 struct timeval t2; 1222 1223 gettimeofday(&t2, NULL); 1224 1225 if (ret < 0) { 1226 printf("readv failed: %s\n", strerror(-ret)); 1227 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct); 1228 goto out; 1229 } 1230 1231 if (ctx->Pflag) { 1232 void *cmp_buf = g_malloc(ctx->qiov.size); 1233 1234 memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1235 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 1236 printf("Pattern verification failed at offset %" 1237 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size); 1238 } 1239 g_free(cmp_buf); 1240 } 1241 1242 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct); 1243 1244 if (ctx->qflag) { 1245 goto out; 1246 } 1247 1248 if (ctx->vflag) { 1249 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1250 } 1251 1252 /* Finally, report back -- -C gives a parsable format */ 1253 t2 = tsub(t2, ctx->t1); 1254 print_report("read", &t2, ctx->offset, ctx->qiov.size, 1255 ctx->qiov.size, 1, ctx->Cflag); 1256 out: 1257 qemu_io_free(ctx->buf); 1258 qemu_iovec_destroy(&ctx->qiov); 1259 g_free(ctx); 1260 } 1261 1262 static void aio_read_help(void) 1263 { 1264 printf( 1265 "\n" 1266 " asynchronously reads a range of bytes from the given offset\n" 1267 "\n" 1268 " Example:\n" 1269 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 1270 "\n" 1271 " Reads a segment of the currently open file, optionally dumping it to the\n" 1272 " standard output stream (with -v option) for subsequent inspection.\n" 1273 " The read is performed asynchronously and the aio_flush command must be\n" 1274 " used to ensure all outstanding aio requests have been completed.\n" 1275 " -C, -- report statistics in a machine parsable format\n" 1276 " -P, -- use a pattern to verify read data\n" 1277 " -i, -- treat request as invalid, for exercising stats\n" 1278 " -v, -- dump buffer to standard output\n" 1279 " -q, -- quiet mode, do not show I/O statistics\n" 1280 "\n"); 1281 } 1282 1283 static int aio_read_f(BlockBackend *blk, int argc, char **argv); 1284 1285 static const cmdinfo_t aio_read_cmd = { 1286 .name = "aio_read", 1287 .cfunc = aio_read_f, 1288 .argmin = 2, 1289 .argmax = -1, 1290 .args = "[-Ciqv] [-P pattern] off len [len..]", 1291 .oneline = "asynchronously reads a number of bytes", 1292 .help = aio_read_help, 1293 }; 1294 1295 static int aio_read_f(BlockBackend *blk, int argc, char **argv) 1296 { 1297 int nr_iov, c; 1298 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1299 1300 ctx->blk = blk; 1301 while ((c = getopt(argc, argv, "CP:iqv")) != -1) { 1302 switch (c) { 1303 case 'C': 1304 ctx->Cflag = true; 1305 break; 1306 case 'P': 1307 ctx->Pflag = true; 1308 ctx->pattern = parse_pattern(optarg); 1309 if (ctx->pattern < 0) { 1310 g_free(ctx); 1311 return 0; 1312 } 1313 break; 1314 case 'i': 1315 printf("injecting invalid read request\n"); 1316 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ); 1317 g_free(ctx); 1318 return 0; 1319 case 'q': 1320 ctx->qflag = true; 1321 break; 1322 case 'v': 1323 ctx->vflag = true; 1324 break; 1325 default: 1326 g_free(ctx); 1327 return qemuio_command_usage(&aio_read_cmd); 1328 } 1329 } 1330 1331 if (optind > argc - 2) { 1332 g_free(ctx); 1333 return qemuio_command_usage(&aio_read_cmd); 1334 } 1335 1336 ctx->offset = cvtnum(argv[optind]); 1337 if (ctx->offset < 0) { 1338 print_cvtnum_err(ctx->offset, argv[optind]); 1339 g_free(ctx); 1340 return 0; 1341 } 1342 optind++; 1343 1344 nr_iov = argc - optind; 1345 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab); 1346 if (ctx->buf == NULL) { 1347 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ); 1348 g_free(ctx); 1349 return 0; 1350 } 1351 1352 gettimeofday(&ctx->t1, NULL); 1353 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, 1354 BLOCK_ACCT_READ); 1355 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx); 1356 return 0; 1357 } 1358 1359 static void aio_write_help(void) 1360 { 1361 printf( 1362 "\n" 1363 " asynchronously writes a range of bytes from the given offset source\n" 1364 " from multiple buffers\n" 1365 "\n" 1366 " Example:\n" 1367 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1368 "\n" 1369 " Writes into a segment of the currently open file, using a buffer\n" 1370 " filled with a set pattern (0xcdcdcdcd).\n" 1371 " The write is performed asynchronously and the aio_flush command must be\n" 1372 " used to ensure all outstanding aio requests have been completed.\n" 1373 " -P, -- use different pattern to fill file\n" 1374 " -C, -- report statistics in a machine parsable format\n" 1375 " -f, -- use Force Unit Access semantics\n" 1376 " -i, -- treat request as invalid, for exercising stats\n" 1377 " -q, -- quiet mode, do not show I/O statistics\n" 1378 " -u, -- with -z, allow unmapping\n" 1379 " -z, -- write zeroes using blk_aio_pwrite_zeroes\n" 1380 "\n"); 1381 } 1382 1383 static int aio_write_f(BlockBackend *blk, int argc, char **argv); 1384 1385 static const cmdinfo_t aio_write_cmd = { 1386 .name = "aio_write", 1387 .cfunc = aio_write_f, 1388 .argmin = 2, 1389 .argmax = -1, 1390 .args = "[-Cfiquz] [-P pattern] off len [len..]", 1391 .oneline = "asynchronously writes a number of bytes", 1392 .help = aio_write_help, 1393 }; 1394 1395 static int aio_write_f(BlockBackend *blk, int argc, char **argv) 1396 { 1397 int nr_iov, c; 1398 int pattern = 0xcd; 1399 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1400 int flags = 0; 1401 1402 ctx->blk = blk; 1403 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) { 1404 switch (c) { 1405 case 'C': 1406 ctx->Cflag = true; 1407 break; 1408 case 'f': 1409 flags |= BDRV_REQ_FUA; 1410 break; 1411 case 'q': 1412 ctx->qflag = true; 1413 break; 1414 case 'u': 1415 flags |= BDRV_REQ_MAY_UNMAP; 1416 break; 1417 case 'P': 1418 pattern = parse_pattern(optarg); 1419 if (pattern < 0) { 1420 g_free(ctx); 1421 return 0; 1422 } 1423 break; 1424 case 'i': 1425 printf("injecting invalid write request\n"); 1426 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE); 1427 g_free(ctx); 1428 return 0; 1429 case 'z': 1430 ctx->zflag = true; 1431 break; 1432 default: 1433 g_free(ctx); 1434 return qemuio_command_usage(&aio_write_cmd); 1435 } 1436 } 1437 1438 if (optind > argc - 2) { 1439 g_free(ctx); 1440 return qemuio_command_usage(&aio_write_cmd); 1441 } 1442 1443 if (ctx->zflag && optind != argc - 2) { 1444 printf("-z supports only a single length parameter\n"); 1445 g_free(ctx); 1446 return 0; 1447 } 1448 1449 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) { 1450 printf("-u requires -z to be specified\n"); 1451 g_free(ctx); 1452 return 0; 1453 } 1454 1455 if (ctx->zflag && ctx->Pflag) { 1456 printf("-z and -P cannot be specified at the same time\n"); 1457 g_free(ctx); 1458 return 0; 1459 } 1460 1461 ctx->offset = cvtnum(argv[optind]); 1462 if (ctx->offset < 0) { 1463 print_cvtnum_err(ctx->offset, argv[optind]); 1464 g_free(ctx); 1465 return 0; 1466 } 1467 optind++; 1468 1469 if (ctx->zflag) { 1470 int64_t count = cvtnum(argv[optind]); 1471 if (count < 0) { 1472 print_cvtnum_err(count, argv[optind]); 1473 g_free(ctx); 1474 return 0; 1475 } 1476 1477 ctx->qiov.size = count; 1478 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done, 1479 ctx); 1480 } else { 1481 nr_iov = argc - optind; 1482 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 1483 pattern); 1484 if (ctx->buf == NULL) { 1485 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE); 1486 g_free(ctx); 1487 return 0; 1488 } 1489 1490 gettimeofday(&ctx->t1, NULL); 1491 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, 1492 BLOCK_ACCT_WRITE); 1493 1494 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done, 1495 ctx); 1496 } 1497 return 0; 1498 } 1499 1500 static int aio_flush_f(BlockBackend *blk, int argc, char **argv) 1501 { 1502 BlockAcctCookie cookie; 1503 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH); 1504 blk_drain_all(); 1505 block_acct_done(blk_get_stats(blk), &cookie); 1506 return 0; 1507 } 1508 1509 static const cmdinfo_t aio_flush_cmd = { 1510 .name = "aio_flush", 1511 .cfunc = aio_flush_f, 1512 .oneline = "completes all outstanding aio requests" 1513 }; 1514 1515 static int flush_f(BlockBackend *blk, int argc, char **argv) 1516 { 1517 blk_flush(blk); 1518 return 0; 1519 } 1520 1521 static const cmdinfo_t flush_cmd = { 1522 .name = "flush", 1523 .altname = "f", 1524 .cfunc = flush_f, 1525 .oneline = "flush all in-core file state to disk", 1526 }; 1527 1528 static int truncate_f(BlockBackend *blk, int argc, char **argv) 1529 { 1530 int64_t offset; 1531 int ret; 1532 1533 offset = cvtnum(argv[1]); 1534 if (offset < 0) { 1535 print_cvtnum_err(offset, argv[1]); 1536 return 0; 1537 } 1538 1539 ret = blk_truncate(blk, offset); 1540 if (ret < 0) { 1541 printf("truncate: %s\n", strerror(-ret)); 1542 return 0; 1543 } 1544 1545 return 0; 1546 } 1547 1548 static const cmdinfo_t truncate_cmd = { 1549 .name = "truncate", 1550 .altname = "t", 1551 .cfunc = truncate_f, 1552 .argmin = 1, 1553 .argmax = 1, 1554 .args = "off", 1555 .oneline = "truncates the current file at the given offset", 1556 }; 1557 1558 static int length_f(BlockBackend *blk, int argc, char **argv) 1559 { 1560 int64_t size; 1561 char s1[64]; 1562 1563 size = blk_getlength(blk); 1564 if (size < 0) { 1565 printf("getlength: %s\n", strerror(-size)); 1566 return 0; 1567 } 1568 1569 cvtstr(size, s1, sizeof(s1)); 1570 printf("%s\n", s1); 1571 return 0; 1572 } 1573 1574 1575 static const cmdinfo_t length_cmd = { 1576 .name = "length", 1577 .altname = "l", 1578 .cfunc = length_f, 1579 .oneline = "gets the length of the current file", 1580 }; 1581 1582 1583 static int info_f(BlockBackend *blk, int argc, char **argv) 1584 { 1585 BlockDriverState *bs = blk_bs(blk); 1586 BlockDriverInfo bdi; 1587 ImageInfoSpecific *spec_info; 1588 char s1[64], s2[64]; 1589 int ret; 1590 1591 if (bs->drv && bs->drv->format_name) { 1592 printf("format name: %s\n", bs->drv->format_name); 1593 } 1594 if (bs->drv && bs->drv->protocol_name) { 1595 printf("format name: %s\n", bs->drv->protocol_name); 1596 } 1597 1598 ret = bdrv_get_info(bs, &bdi); 1599 if (ret) { 1600 return 0; 1601 } 1602 1603 cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1604 cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1605 1606 printf("cluster size: %s\n", s1); 1607 printf("vm state offset: %s\n", s2); 1608 1609 spec_info = bdrv_get_specific_info(bs); 1610 if (spec_info) { 1611 printf("Format specific information:\n"); 1612 bdrv_image_info_specific_dump(fprintf, stdout, spec_info); 1613 qapi_free_ImageInfoSpecific(spec_info); 1614 } 1615 1616 return 0; 1617 } 1618 1619 1620 1621 static const cmdinfo_t info_cmd = { 1622 .name = "info", 1623 .altname = "i", 1624 .cfunc = info_f, 1625 .oneline = "prints information about the current file", 1626 }; 1627 1628 static void discard_help(void) 1629 { 1630 printf( 1631 "\n" 1632 " discards a range of bytes from the given offset\n" 1633 "\n" 1634 " Example:\n" 1635 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n" 1636 "\n" 1637 " Discards a segment of the currently open file.\n" 1638 " -C, -- report statistics in a machine parsable format\n" 1639 " -q, -- quiet mode, do not show I/O statistics\n" 1640 "\n"); 1641 } 1642 1643 static int discard_f(BlockBackend *blk, int argc, char **argv); 1644 1645 static const cmdinfo_t discard_cmd = { 1646 .name = "discard", 1647 .altname = "d", 1648 .cfunc = discard_f, 1649 .argmin = 2, 1650 .argmax = -1, 1651 .args = "[-Cq] off len", 1652 .oneline = "discards a number of bytes at a specified offset", 1653 .help = discard_help, 1654 }; 1655 1656 static int discard_f(BlockBackend *blk, int argc, char **argv) 1657 { 1658 struct timeval t1, t2; 1659 bool Cflag = false, qflag = false; 1660 int c, ret; 1661 int64_t offset, count; 1662 1663 while ((c = getopt(argc, argv, "Cq")) != -1) { 1664 switch (c) { 1665 case 'C': 1666 Cflag = true; 1667 break; 1668 case 'q': 1669 qflag = true; 1670 break; 1671 default: 1672 return qemuio_command_usage(&discard_cmd); 1673 } 1674 } 1675 1676 if (optind != argc - 2) { 1677 return qemuio_command_usage(&discard_cmd); 1678 } 1679 1680 offset = cvtnum(argv[optind]); 1681 if (offset < 0) { 1682 print_cvtnum_err(offset, argv[optind]); 1683 return 0; 1684 } 1685 1686 optind++; 1687 count = cvtnum(argv[optind]); 1688 if (count < 0) { 1689 print_cvtnum_err(count, argv[optind]); 1690 return 0; 1691 } else if (count >> BDRV_SECTOR_BITS > BDRV_REQUEST_MAX_SECTORS) { 1692 printf("length cannot exceed %"PRIu64", given %s\n", 1693 (uint64_t)BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS, 1694 argv[optind]); 1695 return 0; 1696 } 1697 1698 gettimeofday(&t1, NULL); 1699 ret = blk_pdiscard(blk, offset, count); 1700 gettimeofday(&t2, NULL); 1701 1702 if (ret < 0) { 1703 printf("discard failed: %s\n", strerror(-ret)); 1704 goto out; 1705 } 1706 1707 /* Finally, report back -- -C gives a parsable format */ 1708 if (!qflag) { 1709 t2 = tsub(t2, t1); 1710 print_report("discard", &t2, offset, count, count, 1, Cflag); 1711 } 1712 1713 out: 1714 return 0; 1715 } 1716 1717 static int alloc_f(BlockBackend *blk, int argc, char **argv) 1718 { 1719 BlockDriverState *bs = blk_bs(blk); 1720 int64_t offset, sector_num, nb_sectors, remaining; 1721 char s1[64]; 1722 int num, ret; 1723 int64_t sum_alloc; 1724 1725 offset = cvtnum(argv[1]); 1726 if (offset < 0) { 1727 print_cvtnum_err(offset, argv[1]); 1728 return 0; 1729 } else if (offset & 0x1ff) { 1730 printf("offset %" PRId64 " is not sector aligned\n", 1731 offset); 1732 return 0; 1733 } 1734 1735 if (argc == 3) { 1736 nb_sectors = cvtnum(argv[2]); 1737 if (nb_sectors < 0) { 1738 print_cvtnum_err(nb_sectors, argv[2]); 1739 return 0; 1740 } else if (nb_sectors > INT_MAX) { 1741 printf("length argument cannot exceed %d, given %s\n", 1742 INT_MAX, argv[2]); 1743 return 0; 1744 } 1745 } else { 1746 nb_sectors = 1; 1747 } 1748 1749 remaining = nb_sectors; 1750 sum_alloc = 0; 1751 sector_num = offset >> 9; 1752 while (remaining) { 1753 ret = bdrv_is_allocated(bs, sector_num, remaining, &num); 1754 if (ret < 0) { 1755 printf("is_allocated failed: %s\n", strerror(-ret)); 1756 return 0; 1757 } 1758 sector_num += num; 1759 remaining -= num; 1760 if (ret) { 1761 sum_alloc += num; 1762 } 1763 if (num == 0) { 1764 nb_sectors -= remaining; 1765 remaining = 0; 1766 } 1767 } 1768 1769 cvtstr(offset, s1, sizeof(s1)); 1770 1771 printf("%"PRId64"/%"PRId64" sectors allocated at offset %s\n", 1772 sum_alloc, nb_sectors, s1); 1773 return 0; 1774 } 1775 1776 static const cmdinfo_t alloc_cmd = { 1777 .name = "alloc", 1778 .altname = "a", 1779 .argmin = 1, 1780 .argmax = 2, 1781 .cfunc = alloc_f, 1782 .args = "off [sectors]", 1783 .oneline = "checks if a sector is present in the file", 1784 }; 1785 1786 1787 static int map_is_allocated(BlockDriverState *bs, int64_t sector_num, 1788 int64_t nb_sectors, int64_t *pnum) 1789 { 1790 int num, num_checked; 1791 int ret, firstret; 1792 1793 num_checked = MIN(nb_sectors, INT_MAX); 1794 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num); 1795 if (ret < 0) { 1796 return ret; 1797 } 1798 1799 firstret = ret; 1800 *pnum = num; 1801 1802 while (nb_sectors > 0 && ret == firstret) { 1803 sector_num += num; 1804 nb_sectors -= num; 1805 1806 num_checked = MIN(nb_sectors, INT_MAX); 1807 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num); 1808 if (ret == firstret && num) { 1809 *pnum += num; 1810 } else { 1811 break; 1812 } 1813 } 1814 1815 return firstret; 1816 } 1817 1818 static int map_f(BlockBackend *blk, int argc, char **argv) 1819 { 1820 int64_t offset; 1821 int64_t nb_sectors, total_sectors; 1822 char s1[64]; 1823 int64_t num; 1824 int ret; 1825 const char *retstr; 1826 1827 offset = 0; 1828 total_sectors = blk_nb_sectors(blk); 1829 if (total_sectors < 0) { 1830 error_report("Failed to query image length: %s", 1831 strerror(-total_sectors)); 1832 return 0; 1833 } 1834 1835 nb_sectors = total_sectors; 1836 1837 do { 1838 ret = map_is_allocated(blk_bs(blk), offset, nb_sectors, &num); 1839 if (ret < 0) { 1840 error_report("Failed to get allocation status: %s", strerror(-ret)); 1841 return 0; 1842 } else if (!num) { 1843 error_report("Unexpected end of image"); 1844 return 0; 1845 } 1846 1847 retstr = ret ? " allocated" : "not allocated"; 1848 cvtstr(offset << 9ULL, s1, sizeof(s1)); 1849 printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s " 1850 "at offset %s (%d)\n", 1851 offset << 9ULL, num, nb_sectors, retstr, s1, ret); 1852 1853 offset += num; 1854 nb_sectors -= num; 1855 } while (offset < total_sectors); 1856 1857 return 0; 1858 } 1859 1860 static const cmdinfo_t map_cmd = { 1861 .name = "map", 1862 .argmin = 0, 1863 .argmax = 0, 1864 .cfunc = map_f, 1865 .args = "", 1866 .oneline = "prints the allocated areas of a file", 1867 }; 1868 1869 static void reopen_help(void) 1870 { 1871 printf( 1872 "\n" 1873 " Changes the open options of an already opened image\n" 1874 "\n" 1875 " Example:\n" 1876 " 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n" 1877 "\n" 1878 " -r, -- Reopen the image read-only\n" 1879 " -c, -- Change the cache mode to the given value\n" 1880 " -o, -- Changes block driver options (cf. 'open' command)\n" 1881 "\n"); 1882 } 1883 1884 static int reopen_f(BlockBackend *blk, int argc, char **argv); 1885 1886 static QemuOptsList reopen_opts = { 1887 .name = "reopen", 1888 .merge_lists = true, 1889 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head), 1890 .desc = { 1891 /* no elements => accept any params */ 1892 { /* end of list */ } 1893 }, 1894 }; 1895 1896 static const cmdinfo_t reopen_cmd = { 1897 .name = "reopen", 1898 .argmin = 0, 1899 .argmax = -1, 1900 .cfunc = reopen_f, 1901 .args = "[-r] [-c cache] [-o options]", 1902 .oneline = "reopens an image with new options", 1903 .help = reopen_help, 1904 }; 1905 1906 static int reopen_f(BlockBackend *blk, int argc, char **argv) 1907 { 1908 BlockDriverState *bs = blk_bs(blk); 1909 QemuOpts *qopts; 1910 QDict *opts; 1911 int c; 1912 int flags = bs->open_flags; 1913 bool writethrough = !blk_enable_write_cache(blk); 1914 1915 BlockReopenQueue *brq; 1916 Error *local_err = NULL; 1917 1918 while ((c = getopt(argc, argv, "c:o:r")) != -1) { 1919 switch (c) { 1920 case 'c': 1921 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) { 1922 error_report("Invalid cache option: %s", optarg); 1923 return 0; 1924 } 1925 break; 1926 case 'o': 1927 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) { 1928 qemu_opts_reset(&reopen_opts); 1929 return 0; 1930 } 1931 break; 1932 case 'r': 1933 flags &= ~BDRV_O_RDWR; 1934 break; 1935 default: 1936 qemu_opts_reset(&reopen_opts); 1937 return qemuio_command_usage(&reopen_cmd); 1938 } 1939 } 1940 1941 if (optind != argc) { 1942 qemu_opts_reset(&reopen_opts); 1943 return qemuio_command_usage(&reopen_cmd); 1944 } 1945 1946 if (writethrough != blk_enable_write_cache(blk) && 1947 blk_get_attached_dev(blk)) 1948 { 1949 error_report("Cannot change cache.writeback: Device attached"); 1950 qemu_opts_reset(&reopen_opts); 1951 return 0; 1952 } 1953 1954 qopts = qemu_opts_find(&reopen_opts, NULL); 1955 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL; 1956 qemu_opts_reset(&reopen_opts); 1957 1958 brq = bdrv_reopen_queue(NULL, bs, opts, flags); 1959 bdrv_reopen_multiple(brq, &local_err); 1960 if (local_err) { 1961 error_report_err(local_err); 1962 } else { 1963 blk_set_enable_write_cache(blk, !writethrough); 1964 } 1965 1966 return 0; 1967 } 1968 1969 static int break_f(BlockBackend *blk, int argc, char **argv) 1970 { 1971 int ret; 1972 1973 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]); 1974 if (ret < 0) { 1975 printf("Could not set breakpoint: %s\n", strerror(-ret)); 1976 } 1977 1978 return 0; 1979 } 1980 1981 static int remove_break_f(BlockBackend *blk, int argc, char **argv) 1982 { 1983 int ret; 1984 1985 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]); 1986 if (ret < 0) { 1987 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret)); 1988 } 1989 1990 return 0; 1991 } 1992 1993 static const cmdinfo_t break_cmd = { 1994 .name = "break", 1995 .argmin = 2, 1996 .argmax = 2, 1997 .cfunc = break_f, 1998 .args = "event tag", 1999 .oneline = "sets a breakpoint on event and tags the stopped " 2000 "request as tag", 2001 }; 2002 2003 static const cmdinfo_t remove_break_cmd = { 2004 .name = "remove_break", 2005 .argmin = 1, 2006 .argmax = 1, 2007 .cfunc = remove_break_f, 2008 .args = "tag", 2009 .oneline = "remove a breakpoint by tag", 2010 }; 2011 2012 static int resume_f(BlockBackend *blk, int argc, char **argv) 2013 { 2014 int ret; 2015 2016 ret = bdrv_debug_resume(blk_bs(blk), argv[1]); 2017 if (ret < 0) { 2018 printf("Could not resume request: %s\n", strerror(-ret)); 2019 } 2020 2021 return 0; 2022 } 2023 2024 static const cmdinfo_t resume_cmd = { 2025 .name = "resume", 2026 .argmin = 1, 2027 .argmax = 1, 2028 .cfunc = resume_f, 2029 .args = "tag", 2030 .oneline = "resumes the request tagged as tag", 2031 }; 2032 2033 static int wait_break_f(BlockBackend *blk, int argc, char **argv) 2034 { 2035 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) { 2036 aio_poll(blk_get_aio_context(blk), true); 2037 } 2038 2039 return 0; 2040 } 2041 2042 static const cmdinfo_t wait_break_cmd = { 2043 .name = "wait_break", 2044 .argmin = 1, 2045 .argmax = 1, 2046 .cfunc = wait_break_f, 2047 .args = "tag", 2048 .oneline = "waits for the suspension of a request", 2049 }; 2050 2051 static int abort_f(BlockBackend *blk, int argc, char **argv) 2052 { 2053 abort(); 2054 } 2055 2056 static const cmdinfo_t abort_cmd = { 2057 .name = "abort", 2058 .cfunc = abort_f, 2059 .flags = CMD_NOFILE_OK, 2060 .oneline = "simulate a program crash using abort(3)", 2061 }; 2062 2063 static void sigraise_help(void) 2064 { 2065 printf( 2066 "\n" 2067 " raises the given signal\n" 2068 "\n" 2069 " Example:\n" 2070 " 'sigraise %i' - raises SIGTERM\n" 2071 "\n" 2072 " Invokes raise(signal), where \"signal\" is the mandatory integer argument\n" 2073 " given to sigraise.\n" 2074 "\n", SIGTERM); 2075 } 2076 2077 static int sigraise_f(BlockBackend *blk, int argc, char **argv); 2078 2079 static const cmdinfo_t sigraise_cmd = { 2080 .name = "sigraise", 2081 .cfunc = sigraise_f, 2082 .argmin = 1, 2083 .argmax = 1, 2084 .flags = CMD_NOFILE_OK, 2085 .args = "signal", 2086 .oneline = "raises a signal", 2087 .help = sigraise_help, 2088 }; 2089 2090 static int sigraise_f(BlockBackend *blk, int argc, char **argv) 2091 { 2092 int64_t sig = cvtnum(argv[1]); 2093 if (sig < 0) { 2094 print_cvtnum_err(sig, argv[1]); 2095 return 0; 2096 } else if (sig > NSIG) { 2097 printf("signal argument '%s' is too large to be a valid signal\n", 2098 argv[1]); 2099 return 0; 2100 } 2101 2102 /* Using raise() to kill this process does not necessarily flush all open 2103 * streams. At least stdout and stderr (although the latter should be 2104 * non-buffered anyway) should be flushed, though. */ 2105 fflush(stdout); 2106 fflush(stderr); 2107 2108 raise(sig); 2109 return 0; 2110 } 2111 2112 static void sleep_cb(void *opaque) 2113 { 2114 bool *expired = opaque; 2115 *expired = true; 2116 } 2117 2118 static int sleep_f(BlockBackend *blk, int argc, char **argv) 2119 { 2120 char *endptr; 2121 long ms; 2122 struct QEMUTimer *timer; 2123 bool expired = false; 2124 2125 ms = strtol(argv[1], &endptr, 0); 2126 if (ms < 0 || *endptr != '\0') { 2127 printf("%s is not a valid number\n", argv[1]); 2128 return 0; 2129 } 2130 2131 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired); 2132 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms); 2133 2134 while (!expired) { 2135 main_loop_wait(false); 2136 } 2137 2138 timer_free(timer); 2139 2140 return 0; 2141 } 2142 2143 static const cmdinfo_t sleep_cmd = { 2144 .name = "sleep", 2145 .argmin = 1, 2146 .argmax = 1, 2147 .cfunc = sleep_f, 2148 .flags = CMD_NOFILE_OK, 2149 .oneline = "waits for the given value in milliseconds", 2150 }; 2151 2152 static void help_oneline(const char *cmd, const cmdinfo_t *ct) 2153 { 2154 if (cmd) { 2155 printf("%s ", cmd); 2156 } else { 2157 printf("%s ", ct->name); 2158 if (ct->altname) { 2159 printf("(or %s) ", ct->altname); 2160 } 2161 } 2162 2163 if (ct->args) { 2164 printf("%s ", ct->args); 2165 } 2166 printf("-- %s\n", ct->oneline); 2167 } 2168 2169 static void help_onecmd(const char *cmd, const cmdinfo_t *ct) 2170 { 2171 help_oneline(cmd, ct); 2172 if (ct->help) { 2173 ct->help(); 2174 } 2175 } 2176 2177 static void help_all(void) 2178 { 2179 const cmdinfo_t *ct; 2180 2181 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) { 2182 help_oneline(ct->name, ct); 2183 } 2184 printf("\nUse 'help commandname' for extended help.\n"); 2185 } 2186 2187 static int help_f(BlockBackend *blk, int argc, char **argv) 2188 { 2189 const cmdinfo_t *ct; 2190 2191 if (argc == 1) { 2192 help_all(); 2193 return 0; 2194 } 2195 2196 ct = find_command(argv[1]); 2197 if (ct == NULL) { 2198 printf("command %s not found\n", argv[1]); 2199 return 0; 2200 } 2201 2202 help_onecmd(argv[1], ct); 2203 return 0; 2204 } 2205 2206 static const cmdinfo_t help_cmd = { 2207 .name = "help", 2208 .altname = "?", 2209 .cfunc = help_f, 2210 .argmin = 0, 2211 .argmax = 1, 2212 .flags = CMD_FLAG_GLOBAL, 2213 .args = "[command]", 2214 .oneline = "help for one or all commands", 2215 }; 2216 2217 bool qemuio_command(BlockBackend *blk, const char *cmd) 2218 { 2219 char *input; 2220 const cmdinfo_t *ct; 2221 char **v; 2222 int c; 2223 bool done = false; 2224 2225 input = g_strdup(cmd); 2226 v = breakline(input, &c); 2227 if (c) { 2228 ct = find_command(v[0]); 2229 if (ct) { 2230 done = command(blk, ct, c, v); 2231 } else { 2232 fprintf(stderr, "command \"%s\" not found\n", v[0]); 2233 } 2234 } 2235 g_free(input); 2236 g_free(v); 2237 2238 return done; 2239 } 2240 2241 static void __attribute((constructor)) init_qemuio_commands(void) 2242 { 2243 /* initialize commands */ 2244 qemuio_add_command(&help_cmd); 2245 qemuio_add_command(&read_cmd); 2246 qemuio_add_command(&readv_cmd); 2247 qemuio_add_command(&write_cmd); 2248 qemuio_add_command(&writev_cmd); 2249 qemuio_add_command(&aio_read_cmd); 2250 qemuio_add_command(&aio_write_cmd); 2251 qemuio_add_command(&aio_flush_cmd); 2252 qemuio_add_command(&flush_cmd); 2253 qemuio_add_command(&truncate_cmd); 2254 qemuio_add_command(&length_cmd); 2255 qemuio_add_command(&info_cmd); 2256 qemuio_add_command(&discard_cmd); 2257 qemuio_add_command(&alloc_cmd); 2258 qemuio_add_command(&map_cmd); 2259 qemuio_add_command(&reopen_cmd); 2260 qemuio_add_command(&break_cmd); 2261 qemuio_add_command(&remove_break_cmd); 2262 qemuio_add_command(&resume_cmd); 2263 qemuio_add_command(&wait_break_cmd); 2264 qemuio_add_command(&abort_cmd); 2265 qemuio_add_command(&sleep_cmd); 2266 qemuio_add_command(&sigraise_cmd); 2267 } 2268