1 /* 2 * Command line utility to exercise the QEMU I/O path. 3 * 4 * Copyright (C) 2009 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 #include <sys/time.h> 11 #include <sys/types.h> 12 #include <stdarg.h> 13 #include <stdio.h> 14 #include <getopt.h> 15 #include <libgen.h> 16 17 #include "qemu-common.h" 18 #include "qemu/main-loop.h" 19 #include "block/block_int.h" 20 #include "cmd.h" 21 #include "trace/control.h" 22 23 #define VERSION "0.0.1" 24 25 #define CMD_NOFILE_OK 0x01 26 27 char *progname; 28 static BlockDriverState *bs; 29 30 static int misalign; 31 32 /* 33 * Parse the pattern argument to various sub-commands. 34 * 35 * Because the pattern is used as an argument to memset it must evaluate 36 * to an unsigned integer that fits into a single byte. 37 */ 38 static int parse_pattern(const char *arg) 39 { 40 char *endptr = NULL; 41 long pattern; 42 43 pattern = strtol(arg, &endptr, 0); 44 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') { 45 printf("%s is not a valid pattern byte\n", arg); 46 return -1; 47 } 48 49 return pattern; 50 } 51 52 /* 53 * Memory allocation helpers. 54 * 55 * Make sure memory is aligned by default, or purposefully misaligned if 56 * that is specified on the command line. 57 */ 58 59 #define MISALIGN_OFFSET 16 60 static void *qemu_io_alloc(size_t len, int pattern) 61 { 62 void *buf; 63 64 if (misalign) { 65 len += MISALIGN_OFFSET; 66 } 67 buf = qemu_blockalign(bs, len); 68 memset(buf, pattern, len); 69 if (misalign) { 70 buf += MISALIGN_OFFSET; 71 } 72 return buf; 73 } 74 75 static void qemu_io_free(void *p) 76 { 77 if (misalign) { 78 p -= MISALIGN_OFFSET; 79 } 80 qemu_vfree(p); 81 } 82 83 static void dump_buffer(const void *buffer, int64_t offset, int len) 84 { 85 int i, j; 86 const uint8_t *p; 87 88 for (i = 0, p = buffer; i < len; i += 16) { 89 const uint8_t *s = p; 90 91 printf("%08" PRIx64 ": ", offset + i); 92 for (j = 0; j < 16 && i + j < len; j++, p++) { 93 printf("%02x ", *p); 94 } 95 printf(" "); 96 for (j = 0; j < 16 && i + j < len; j++, s++) { 97 if (isalnum(*s)) { 98 printf("%c", *s); 99 } else { 100 printf("."); 101 } 102 } 103 printf("\n"); 104 } 105 } 106 107 static void print_report(const char *op, struct timeval *t, int64_t offset, 108 int count, int total, int cnt, int Cflag) 109 { 110 char s1[64], s2[64], ts[64]; 111 112 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); 113 if (!Cflag) { 114 cvtstr((double)total, s1, sizeof(s1)); 115 cvtstr(tdiv((double)total, *t), s2, sizeof(s2)); 116 printf("%s %d/%d bytes at offset %" PRId64 "\n", 117 op, total, count, offset); 118 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n", 119 s1, cnt, ts, s2, tdiv((double)cnt, *t)); 120 } else {/* bytes,ops,time,bytes/sec,ops/sec */ 121 printf("%d,%d,%s,%.3f,%.3f\n", 122 total, cnt, ts, 123 tdiv((double)total, *t), 124 tdiv((double)cnt, *t)); 125 } 126 } 127 128 /* 129 * Parse multiple length statements for vectored I/O, and construct an I/O 130 * vector matching it. 131 */ 132 static void * 133 create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern) 134 { 135 size_t *sizes = g_new0(size_t, nr_iov); 136 size_t count = 0; 137 void *buf = NULL; 138 void *p; 139 int i; 140 141 for (i = 0; i < nr_iov; i++) { 142 char *arg = argv[i]; 143 int64_t len; 144 145 len = cvtnum(arg); 146 if (len < 0) { 147 printf("non-numeric length argument -- %s\n", arg); 148 goto fail; 149 } 150 151 /* should be SIZE_T_MAX, but that doesn't exist */ 152 if (len > INT_MAX) { 153 printf("too large length argument -- %s\n", arg); 154 goto fail; 155 } 156 157 if (len & 0x1ff) { 158 printf("length argument %" PRId64 159 " is not sector aligned\n", len); 160 goto fail; 161 } 162 163 sizes[i] = len; 164 count += len; 165 } 166 167 qemu_iovec_init(qiov, nr_iov); 168 169 buf = p = qemu_io_alloc(count, pattern); 170 171 for (i = 0; i < nr_iov; i++) { 172 qemu_iovec_add(qiov, p, sizes[i]); 173 p += sizes[i]; 174 } 175 176 fail: 177 g_free(sizes); 178 return buf; 179 } 180 181 static int do_read(char *buf, int64_t offset, int count, int *total) 182 { 183 int ret; 184 185 ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9); 186 if (ret < 0) { 187 return ret; 188 } 189 *total = count; 190 return 1; 191 } 192 193 static int do_write(char *buf, int64_t offset, int count, int *total) 194 { 195 int ret; 196 197 ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9); 198 if (ret < 0) { 199 return ret; 200 } 201 *total = count; 202 return 1; 203 } 204 205 static int do_pread(char *buf, int64_t offset, int count, int *total) 206 { 207 *total = bdrv_pread(bs, offset, (uint8_t *)buf, count); 208 if (*total < 0) { 209 return *total; 210 } 211 return 1; 212 } 213 214 static int do_pwrite(char *buf, int64_t offset, int count, int *total) 215 { 216 *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count); 217 if (*total < 0) { 218 return *total; 219 } 220 return 1; 221 } 222 223 typedef struct { 224 int64_t offset; 225 int count; 226 int *total; 227 int ret; 228 bool done; 229 } CoWriteZeroes; 230 231 static void coroutine_fn co_write_zeroes_entry(void *opaque) 232 { 233 CoWriteZeroes *data = opaque; 234 235 data->ret = bdrv_co_write_zeroes(bs, data->offset / BDRV_SECTOR_SIZE, 236 data->count / BDRV_SECTOR_SIZE); 237 data->done = true; 238 if (data->ret < 0) { 239 *data->total = data->ret; 240 return; 241 } 242 243 *data->total = data->count; 244 } 245 246 static int do_co_write_zeroes(int64_t offset, int count, int *total) 247 { 248 Coroutine *co; 249 CoWriteZeroes data = { 250 .offset = offset, 251 .count = count, 252 .total = total, 253 .done = false, 254 }; 255 256 co = qemu_coroutine_create(co_write_zeroes_entry); 257 qemu_coroutine_enter(co, &data); 258 while (!data.done) { 259 qemu_aio_wait(); 260 } 261 if (data.ret < 0) { 262 return data.ret; 263 } else { 264 return 1; 265 } 266 } 267 268 static int do_write_compressed(char *buf, int64_t offset, int count, int *total) 269 { 270 int ret; 271 272 ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9); 273 if (ret < 0) { 274 return ret; 275 } 276 *total = count; 277 return 1; 278 } 279 280 static int do_load_vmstate(char *buf, int64_t offset, int count, int *total) 281 { 282 *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count); 283 if (*total < 0) { 284 return *total; 285 } 286 return 1; 287 } 288 289 static int do_save_vmstate(char *buf, int64_t offset, int count, int *total) 290 { 291 *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count); 292 if (*total < 0) { 293 return *total; 294 } 295 return 1; 296 } 297 298 #define NOT_DONE 0x7fffffff 299 static void aio_rw_done(void *opaque, int ret) 300 { 301 *(int *)opaque = ret; 302 } 303 304 static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total) 305 { 306 int async_ret = NOT_DONE; 307 308 bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, 309 aio_rw_done, &async_ret); 310 while (async_ret == NOT_DONE) { 311 main_loop_wait(false); 312 } 313 314 *total = qiov->size; 315 return async_ret < 0 ? async_ret : 1; 316 } 317 318 static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) 319 { 320 int async_ret = NOT_DONE; 321 322 bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, 323 aio_rw_done, &async_ret); 324 while (async_ret == NOT_DONE) { 325 main_loop_wait(false); 326 } 327 328 *total = qiov->size; 329 return async_ret < 0 ? async_ret : 1; 330 } 331 332 struct multiwrite_async_ret { 333 int num_done; 334 int error; 335 }; 336 337 static void multiwrite_cb(void *opaque, int ret) 338 { 339 struct multiwrite_async_ret *async_ret = opaque; 340 341 async_ret->num_done++; 342 if (ret < 0) { 343 async_ret->error = ret; 344 } 345 } 346 347 static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total) 348 { 349 int i, ret; 350 struct multiwrite_async_ret async_ret = { 351 .num_done = 0, 352 .error = 0, 353 }; 354 355 *total = 0; 356 for (i = 0; i < num_reqs; i++) { 357 reqs[i].cb = multiwrite_cb; 358 reqs[i].opaque = &async_ret; 359 *total += reqs[i].qiov->size; 360 } 361 362 ret = bdrv_aio_multiwrite(bs, reqs, num_reqs); 363 if (ret < 0) { 364 return ret; 365 } 366 367 while (async_ret.num_done < num_reqs) { 368 main_loop_wait(false); 369 } 370 371 return async_ret.error < 0 ? async_ret.error : 1; 372 } 373 374 static void read_help(void) 375 { 376 printf( 377 "\n" 378 " reads a range of bytes from the given offset\n" 379 "\n" 380 " Example:\n" 381 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 382 "\n" 383 " Reads a segment of the currently open file, optionally dumping it to the\n" 384 " standard output stream (with -v option) for subsequent inspection.\n" 385 " -b, -- read from the VM state rather than the virtual disk\n" 386 " -C, -- report statistics in a machine parsable format\n" 387 " -l, -- length for pattern verification (only with -P)\n" 388 " -p, -- use bdrv_pread to read the file\n" 389 " -P, -- use a pattern to verify read data\n" 390 " -q, -- quiet mode, do not show I/O statistics\n" 391 " -s, -- start offset for pattern verification (only with -P)\n" 392 " -v, -- dump buffer to standard output\n" 393 "\n"); 394 } 395 396 static int read_f(int argc, char **argv); 397 398 static const cmdinfo_t read_cmd = { 399 .name = "read", 400 .altname = "r", 401 .cfunc = read_f, 402 .argmin = 2, 403 .argmax = -1, 404 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", 405 .oneline = "reads a number of bytes at a specified offset", 406 .help = read_help, 407 }; 408 409 static int read_f(int argc, char **argv) 410 { 411 struct timeval t1, t2; 412 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 413 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; 414 int c, cnt; 415 char *buf; 416 int64_t offset; 417 int count; 418 /* Some compilers get confused and warn if this is not initialized. */ 419 int total = 0; 420 int pattern = 0, pattern_offset = 0, pattern_count = 0; 421 422 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { 423 switch (c) { 424 case 'b': 425 bflag = 1; 426 break; 427 case 'C': 428 Cflag = 1; 429 break; 430 case 'l': 431 lflag = 1; 432 pattern_count = cvtnum(optarg); 433 if (pattern_count < 0) { 434 printf("non-numeric length argument -- %s\n", optarg); 435 return 0; 436 } 437 break; 438 case 'p': 439 pflag = 1; 440 break; 441 case 'P': 442 Pflag = 1; 443 pattern = parse_pattern(optarg); 444 if (pattern < 0) { 445 return 0; 446 } 447 break; 448 case 'q': 449 qflag = 1; 450 break; 451 case 's': 452 sflag = 1; 453 pattern_offset = cvtnum(optarg); 454 if (pattern_offset < 0) { 455 printf("non-numeric length argument -- %s\n", optarg); 456 return 0; 457 } 458 break; 459 case 'v': 460 vflag = 1; 461 break; 462 default: 463 return command_usage(&read_cmd); 464 } 465 } 466 467 if (optind != argc - 2) { 468 return command_usage(&read_cmd); 469 } 470 471 if (bflag && pflag) { 472 printf("-b and -p cannot be specified at the same time\n"); 473 return 0; 474 } 475 476 offset = cvtnum(argv[optind]); 477 if (offset < 0) { 478 printf("non-numeric length argument -- %s\n", argv[optind]); 479 return 0; 480 } 481 482 optind++; 483 count = cvtnum(argv[optind]); 484 if (count < 0) { 485 printf("non-numeric length argument -- %s\n", argv[optind]); 486 return 0; 487 } 488 489 if (!Pflag && (lflag || sflag)) { 490 return command_usage(&read_cmd); 491 } 492 493 if (!lflag) { 494 pattern_count = count - pattern_offset; 495 } 496 497 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 498 printf("pattern verification range exceeds end of read data\n"); 499 return 0; 500 } 501 502 if (!pflag) { 503 if (offset & 0x1ff) { 504 printf("offset %" PRId64 " is not sector aligned\n", 505 offset); 506 return 0; 507 } 508 if (count & 0x1ff) { 509 printf("count %d is not sector aligned\n", 510 count); 511 return 0; 512 } 513 } 514 515 buf = qemu_io_alloc(count, 0xab); 516 517 gettimeofday(&t1, NULL); 518 if (pflag) { 519 cnt = do_pread(buf, offset, count, &total); 520 } else if (bflag) { 521 cnt = do_load_vmstate(buf, offset, count, &total); 522 } else { 523 cnt = do_read(buf, offset, count, &total); 524 } 525 gettimeofday(&t2, NULL); 526 527 if (cnt < 0) { 528 printf("read failed: %s\n", strerror(-cnt)); 529 goto out; 530 } 531 532 if (Pflag) { 533 void *cmp_buf = g_malloc(pattern_count); 534 memset(cmp_buf, pattern, pattern_count); 535 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 536 printf("Pattern verification failed at offset %" 537 PRId64 ", %d bytes\n", 538 offset + pattern_offset, pattern_count); 539 } 540 g_free(cmp_buf); 541 } 542 543 if (qflag) { 544 goto out; 545 } 546 547 if (vflag) { 548 dump_buffer(buf, offset, count); 549 } 550 551 /* Finally, report back -- -C gives a parsable format */ 552 t2 = tsub(t2, t1); 553 print_report("read", &t2, offset, count, total, cnt, Cflag); 554 555 out: 556 qemu_io_free(buf); 557 558 return 0; 559 } 560 561 static void readv_help(void) 562 { 563 printf( 564 "\n" 565 " reads a range of bytes from the given offset into multiple buffers\n" 566 "\n" 567 " Example:\n" 568 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 569 "\n" 570 " Reads a segment of the currently open file, optionally dumping it to the\n" 571 " standard output stream (with -v option) for subsequent inspection.\n" 572 " Uses multiple iovec buffers if more than one byte range is specified.\n" 573 " -C, -- report statistics in a machine parsable format\n" 574 " -P, -- use a pattern to verify read data\n" 575 " -v, -- dump buffer to standard output\n" 576 " -q, -- quiet mode, do not show I/O statistics\n" 577 "\n"); 578 } 579 580 static int readv_f(int argc, char **argv); 581 582 static const cmdinfo_t readv_cmd = { 583 .name = "readv", 584 .cfunc = readv_f, 585 .argmin = 2, 586 .argmax = -1, 587 .args = "[-Cqv] [-P pattern ] off len [len..]", 588 .oneline = "reads a number of bytes at a specified offset", 589 .help = readv_help, 590 }; 591 592 static int readv_f(int argc, char **argv) 593 { 594 struct timeval t1, t2; 595 int Cflag = 0, qflag = 0, vflag = 0; 596 int c, cnt; 597 char *buf; 598 int64_t offset; 599 /* Some compilers get confused and warn if this is not initialized. */ 600 int total = 0; 601 int nr_iov; 602 QEMUIOVector qiov; 603 int pattern = 0; 604 int Pflag = 0; 605 606 while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 607 switch (c) { 608 case 'C': 609 Cflag = 1; 610 break; 611 case 'P': 612 Pflag = 1; 613 pattern = parse_pattern(optarg); 614 if (pattern < 0) { 615 return 0; 616 } 617 break; 618 case 'q': 619 qflag = 1; 620 break; 621 case 'v': 622 vflag = 1; 623 break; 624 default: 625 return command_usage(&readv_cmd); 626 } 627 } 628 629 if (optind > argc - 2) { 630 return command_usage(&readv_cmd); 631 } 632 633 634 offset = cvtnum(argv[optind]); 635 if (offset < 0) { 636 printf("non-numeric length argument -- %s\n", argv[optind]); 637 return 0; 638 } 639 optind++; 640 641 if (offset & 0x1ff) { 642 printf("offset %" PRId64 " is not sector aligned\n", 643 offset); 644 return 0; 645 } 646 647 nr_iov = argc - optind; 648 buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); 649 if (buf == NULL) { 650 return 0; 651 } 652 653 gettimeofday(&t1, NULL); 654 cnt = do_aio_readv(&qiov, offset, &total); 655 gettimeofday(&t2, NULL); 656 657 if (cnt < 0) { 658 printf("readv failed: %s\n", strerror(-cnt)); 659 goto out; 660 } 661 662 if (Pflag) { 663 void *cmp_buf = g_malloc(qiov.size); 664 memset(cmp_buf, pattern, qiov.size); 665 if (memcmp(buf, cmp_buf, qiov.size)) { 666 printf("Pattern verification failed at offset %" 667 PRId64 ", %zd bytes\n", offset, qiov.size); 668 } 669 g_free(cmp_buf); 670 } 671 672 if (qflag) { 673 goto out; 674 } 675 676 if (vflag) { 677 dump_buffer(buf, offset, qiov.size); 678 } 679 680 /* Finally, report back -- -C gives a parsable format */ 681 t2 = tsub(t2, t1); 682 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 683 684 out: 685 qemu_iovec_destroy(&qiov); 686 qemu_io_free(buf); 687 return 0; 688 } 689 690 static void write_help(void) 691 { 692 printf( 693 "\n" 694 " writes a range of bytes from the given offset\n" 695 "\n" 696 " Example:\n" 697 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 698 "\n" 699 " Writes into a segment of the currently open file, using a buffer\n" 700 " filled with a set pattern (0xcdcdcdcd).\n" 701 " -b, -- write to the VM state rather than the virtual disk\n" 702 " -c, -- write compressed data with bdrv_write_compressed\n" 703 " -p, -- use bdrv_pwrite to write the file\n" 704 " -P, -- use different pattern to fill file\n" 705 " -C, -- report statistics in a machine parsable format\n" 706 " -q, -- quiet mode, do not show I/O statistics\n" 707 " -z, -- write zeroes using bdrv_co_write_zeroes\n" 708 "\n"); 709 } 710 711 static int write_f(int argc, char **argv); 712 713 static const cmdinfo_t write_cmd = { 714 .name = "write", 715 .altname = "w", 716 .cfunc = write_f, 717 .argmin = 2, 718 .argmax = -1, 719 .args = "[-bcCpqz] [-P pattern ] off len", 720 .oneline = "writes a number of bytes at a specified offset", 721 .help = write_help, 722 }; 723 724 static int write_f(int argc, char **argv) 725 { 726 struct timeval t1, t2; 727 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0; 728 int cflag = 0; 729 int c, cnt; 730 char *buf = NULL; 731 int64_t offset; 732 int count; 733 /* Some compilers get confused and warn if this is not initialized. */ 734 int total = 0; 735 int pattern = 0xcd; 736 737 while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) { 738 switch (c) { 739 case 'b': 740 bflag = 1; 741 break; 742 case 'c': 743 cflag = 1; 744 break; 745 case 'C': 746 Cflag = 1; 747 break; 748 case 'p': 749 pflag = 1; 750 break; 751 case 'P': 752 Pflag = 1; 753 pattern = parse_pattern(optarg); 754 if (pattern < 0) { 755 return 0; 756 } 757 break; 758 case 'q': 759 qflag = 1; 760 break; 761 case 'z': 762 zflag = 1; 763 break; 764 default: 765 return command_usage(&write_cmd); 766 } 767 } 768 769 if (optind != argc - 2) { 770 return command_usage(&write_cmd); 771 } 772 773 if (bflag + pflag + zflag > 1) { 774 printf("-b, -p, or -z cannot be specified at the same time\n"); 775 return 0; 776 } 777 778 if (zflag && Pflag) { 779 printf("-z and -P cannot be specified at the same time\n"); 780 return 0; 781 } 782 783 offset = cvtnum(argv[optind]); 784 if (offset < 0) { 785 printf("non-numeric length argument -- %s\n", argv[optind]); 786 return 0; 787 } 788 789 optind++; 790 count = cvtnum(argv[optind]); 791 if (count < 0) { 792 printf("non-numeric length argument -- %s\n", argv[optind]); 793 return 0; 794 } 795 796 if (!pflag) { 797 if (offset & 0x1ff) { 798 printf("offset %" PRId64 " is not sector aligned\n", 799 offset); 800 return 0; 801 } 802 803 if (count & 0x1ff) { 804 printf("count %d is not sector aligned\n", 805 count); 806 return 0; 807 } 808 } 809 810 if (!zflag) { 811 buf = qemu_io_alloc(count, pattern); 812 } 813 814 gettimeofday(&t1, NULL); 815 if (pflag) { 816 cnt = do_pwrite(buf, offset, count, &total); 817 } else if (bflag) { 818 cnt = do_save_vmstate(buf, offset, count, &total); 819 } else if (zflag) { 820 cnt = do_co_write_zeroes(offset, count, &total); 821 } else if (cflag) { 822 cnt = do_write_compressed(buf, offset, count, &total); 823 } else { 824 cnt = do_write(buf, offset, count, &total); 825 } 826 gettimeofday(&t2, NULL); 827 828 if (cnt < 0) { 829 printf("write failed: %s\n", strerror(-cnt)); 830 goto out; 831 } 832 833 if (qflag) { 834 goto out; 835 } 836 837 /* Finally, report back -- -C gives a parsable format */ 838 t2 = tsub(t2, t1); 839 print_report("wrote", &t2, offset, count, total, cnt, Cflag); 840 841 out: 842 if (!zflag) { 843 qemu_io_free(buf); 844 } 845 846 return 0; 847 } 848 849 static void 850 writev_help(void) 851 { 852 printf( 853 "\n" 854 " writes a range of bytes from the given offset source from multiple buffers\n" 855 "\n" 856 " Example:\n" 857 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 858 "\n" 859 " Writes into a segment of the currently open file, using a buffer\n" 860 " filled with a set pattern (0xcdcdcdcd).\n" 861 " -P, -- use different pattern to fill file\n" 862 " -C, -- report statistics in a machine parsable format\n" 863 " -q, -- quiet mode, do not show I/O statistics\n" 864 "\n"); 865 } 866 867 static int writev_f(int argc, char **argv); 868 869 static const cmdinfo_t writev_cmd = { 870 .name = "writev", 871 .cfunc = writev_f, 872 .argmin = 2, 873 .argmax = -1, 874 .args = "[-Cq] [-P pattern ] off len [len..]", 875 .oneline = "writes a number of bytes at a specified offset", 876 .help = writev_help, 877 }; 878 879 static int writev_f(int argc, char **argv) 880 { 881 struct timeval t1, t2; 882 int Cflag = 0, qflag = 0; 883 int c, cnt; 884 char *buf; 885 int64_t offset; 886 /* Some compilers get confused and warn if this is not initialized. */ 887 int total = 0; 888 int nr_iov; 889 int pattern = 0xcd; 890 QEMUIOVector qiov; 891 892 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 893 switch (c) { 894 case 'C': 895 Cflag = 1; 896 break; 897 case 'q': 898 qflag = 1; 899 break; 900 case 'P': 901 pattern = parse_pattern(optarg); 902 if (pattern < 0) { 903 return 0; 904 } 905 break; 906 default: 907 return command_usage(&writev_cmd); 908 } 909 } 910 911 if (optind > argc - 2) { 912 return command_usage(&writev_cmd); 913 } 914 915 offset = cvtnum(argv[optind]); 916 if (offset < 0) { 917 printf("non-numeric length argument -- %s\n", argv[optind]); 918 return 0; 919 } 920 optind++; 921 922 if (offset & 0x1ff) { 923 printf("offset %" PRId64 " is not sector aligned\n", 924 offset); 925 return 0; 926 } 927 928 nr_iov = argc - optind; 929 buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); 930 if (buf == NULL) { 931 return 0; 932 } 933 934 gettimeofday(&t1, NULL); 935 cnt = do_aio_writev(&qiov, offset, &total); 936 gettimeofday(&t2, NULL); 937 938 if (cnt < 0) { 939 printf("writev failed: %s\n", strerror(-cnt)); 940 goto out; 941 } 942 943 if (qflag) { 944 goto out; 945 } 946 947 /* Finally, report back -- -C gives a parsable format */ 948 t2 = tsub(t2, t1); 949 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 950 out: 951 qemu_iovec_destroy(&qiov); 952 qemu_io_free(buf); 953 return 0; 954 } 955 956 static void multiwrite_help(void) 957 { 958 printf( 959 "\n" 960 " writes a range of bytes from the given offset source from multiple buffers,\n" 961 " in a batch of requests that may be merged by qemu\n" 962 "\n" 963 " Example:\n" 964 " 'multiwrite 512 1k 1k ; 4k 1k'\n" 965 " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n" 966 "\n" 967 " Writes into a segment of the currently open file, using a buffer\n" 968 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n" 969 " by one for each request contained in the multiwrite command.\n" 970 " -P, -- use different pattern to fill file\n" 971 " -C, -- report statistics in a machine parsable format\n" 972 " -q, -- quiet mode, do not show I/O statistics\n" 973 "\n"); 974 } 975 976 static int multiwrite_f(int argc, char **argv); 977 978 static const cmdinfo_t multiwrite_cmd = { 979 .name = "multiwrite", 980 .cfunc = multiwrite_f, 981 .argmin = 2, 982 .argmax = -1, 983 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]", 984 .oneline = "issues multiple write requests at once", 985 .help = multiwrite_help, 986 }; 987 988 static int multiwrite_f(int argc, char **argv) 989 { 990 struct timeval t1, t2; 991 int Cflag = 0, qflag = 0; 992 int c, cnt; 993 char **buf; 994 int64_t offset, first_offset = 0; 995 /* Some compilers get confused and warn if this is not initialized. */ 996 int total = 0; 997 int nr_iov; 998 int nr_reqs; 999 int pattern = 0xcd; 1000 QEMUIOVector *qiovs; 1001 int i; 1002 BlockRequest *reqs; 1003 1004 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 1005 switch (c) { 1006 case 'C': 1007 Cflag = 1; 1008 break; 1009 case 'q': 1010 qflag = 1; 1011 break; 1012 case 'P': 1013 pattern = parse_pattern(optarg); 1014 if (pattern < 0) { 1015 return 0; 1016 } 1017 break; 1018 default: 1019 return command_usage(&writev_cmd); 1020 } 1021 } 1022 1023 if (optind > argc - 2) { 1024 return command_usage(&writev_cmd); 1025 } 1026 1027 nr_reqs = 1; 1028 for (i = optind; i < argc; i++) { 1029 if (!strcmp(argv[i], ";")) { 1030 nr_reqs++; 1031 } 1032 } 1033 1034 reqs = g_malloc0(nr_reqs * sizeof(*reqs)); 1035 buf = g_malloc0(nr_reqs * sizeof(*buf)); 1036 qiovs = g_malloc(nr_reqs * sizeof(*qiovs)); 1037 1038 for (i = 0; i < nr_reqs && optind < argc; i++) { 1039 int j; 1040 1041 /* Read the offset of the request */ 1042 offset = cvtnum(argv[optind]); 1043 if (offset < 0) { 1044 printf("non-numeric offset argument -- %s\n", argv[optind]); 1045 goto out; 1046 } 1047 optind++; 1048 1049 if (offset & 0x1ff) { 1050 printf("offset %lld is not sector aligned\n", 1051 (long long)offset); 1052 goto out; 1053 } 1054 1055 if (i == 0) { 1056 first_offset = offset; 1057 } 1058 1059 /* Read lengths for qiov entries */ 1060 for (j = optind; j < argc; j++) { 1061 if (!strcmp(argv[j], ";")) { 1062 break; 1063 } 1064 } 1065 1066 nr_iov = j - optind; 1067 1068 /* Build request */ 1069 buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern); 1070 if (buf[i] == NULL) { 1071 goto out; 1072 } 1073 1074 reqs[i].qiov = &qiovs[i]; 1075 reqs[i].sector = offset >> 9; 1076 reqs[i].nb_sectors = reqs[i].qiov->size >> 9; 1077 1078 optind = j + 1; 1079 1080 pattern++; 1081 } 1082 1083 /* If there were empty requests at the end, ignore them */ 1084 nr_reqs = i; 1085 1086 gettimeofday(&t1, NULL); 1087 cnt = do_aio_multiwrite(reqs, nr_reqs, &total); 1088 gettimeofday(&t2, NULL); 1089 1090 if (cnt < 0) { 1091 printf("aio_multiwrite failed: %s\n", strerror(-cnt)); 1092 goto out; 1093 } 1094 1095 if (qflag) { 1096 goto out; 1097 } 1098 1099 /* Finally, report back -- -C gives a parsable format */ 1100 t2 = tsub(t2, t1); 1101 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); 1102 out: 1103 for (i = 0; i < nr_reqs; i++) { 1104 qemu_io_free(buf[i]); 1105 if (reqs[i].qiov != NULL) { 1106 qemu_iovec_destroy(&qiovs[i]); 1107 } 1108 } 1109 g_free(buf); 1110 g_free(reqs); 1111 g_free(qiovs); 1112 return 0; 1113 } 1114 1115 struct aio_ctx { 1116 QEMUIOVector qiov; 1117 int64_t offset; 1118 char *buf; 1119 int qflag; 1120 int vflag; 1121 int Cflag; 1122 int Pflag; 1123 int pattern; 1124 struct timeval t1; 1125 }; 1126 1127 static void aio_write_done(void *opaque, int ret) 1128 { 1129 struct aio_ctx *ctx = opaque; 1130 struct timeval t2; 1131 1132 gettimeofday(&t2, NULL); 1133 1134 1135 if (ret < 0) { 1136 printf("aio_write failed: %s\n", strerror(-ret)); 1137 goto out; 1138 } 1139 1140 if (ctx->qflag) { 1141 goto out; 1142 } 1143 1144 /* Finally, report back -- -C gives a parsable format */ 1145 t2 = tsub(t2, ctx->t1); 1146 print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1147 ctx->qiov.size, 1, ctx->Cflag); 1148 out: 1149 qemu_io_free(ctx->buf); 1150 qemu_iovec_destroy(&ctx->qiov); 1151 g_free(ctx); 1152 } 1153 1154 static void aio_read_done(void *opaque, int ret) 1155 { 1156 struct aio_ctx *ctx = opaque; 1157 struct timeval t2; 1158 1159 gettimeofday(&t2, NULL); 1160 1161 if (ret < 0) { 1162 printf("readv failed: %s\n", strerror(-ret)); 1163 goto out; 1164 } 1165 1166 if (ctx->Pflag) { 1167 void *cmp_buf = g_malloc(ctx->qiov.size); 1168 1169 memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1170 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 1171 printf("Pattern verification failed at offset %" 1172 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size); 1173 } 1174 g_free(cmp_buf); 1175 } 1176 1177 if (ctx->qflag) { 1178 goto out; 1179 } 1180 1181 if (ctx->vflag) { 1182 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1183 } 1184 1185 /* Finally, report back -- -C gives a parsable format */ 1186 t2 = tsub(t2, ctx->t1); 1187 print_report("read", &t2, ctx->offset, ctx->qiov.size, 1188 ctx->qiov.size, 1, ctx->Cflag); 1189 out: 1190 qemu_io_free(ctx->buf); 1191 qemu_iovec_destroy(&ctx->qiov); 1192 g_free(ctx); 1193 } 1194 1195 static void aio_read_help(void) 1196 { 1197 printf( 1198 "\n" 1199 " asynchronously reads a range of bytes from the given offset\n" 1200 "\n" 1201 " Example:\n" 1202 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 1203 "\n" 1204 " Reads a segment of the currently open file, optionally dumping it to the\n" 1205 " standard output stream (with -v option) for subsequent inspection.\n" 1206 " The read is performed asynchronously and the aio_flush command must be\n" 1207 " used to ensure all outstanding aio requests have been completed.\n" 1208 " -C, -- report statistics in a machine parsable format\n" 1209 " -P, -- use a pattern to verify read data\n" 1210 " -v, -- dump buffer to standard output\n" 1211 " -q, -- quiet mode, do not show I/O statistics\n" 1212 "\n"); 1213 } 1214 1215 static int aio_read_f(int argc, char **argv); 1216 1217 static const cmdinfo_t aio_read_cmd = { 1218 .name = "aio_read", 1219 .cfunc = aio_read_f, 1220 .argmin = 2, 1221 .argmax = -1, 1222 .args = "[-Cqv] [-P pattern ] off len [len..]", 1223 .oneline = "asynchronously reads a number of bytes", 1224 .help = aio_read_help, 1225 }; 1226 1227 static int aio_read_f(int argc, char **argv) 1228 { 1229 int nr_iov, c; 1230 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1231 1232 while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 1233 switch (c) { 1234 case 'C': 1235 ctx->Cflag = 1; 1236 break; 1237 case 'P': 1238 ctx->Pflag = 1; 1239 ctx->pattern = parse_pattern(optarg); 1240 if (ctx->pattern < 0) { 1241 g_free(ctx); 1242 return 0; 1243 } 1244 break; 1245 case 'q': 1246 ctx->qflag = 1; 1247 break; 1248 case 'v': 1249 ctx->vflag = 1; 1250 break; 1251 default: 1252 g_free(ctx); 1253 return command_usage(&aio_read_cmd); 1254 } 1255 } 1256 1257 if (optind > argc - 2) { 1258 g_free(ctx); 1259 return command_usage(&aio_read_cmd); 1260 } 1261 1262 ctx->offset = cvtnum(argv[optind]); 1263 if (ctx->offset < 0) { 1264 printf("non-numeric length argument -- %s\n", argv[optind]); 1265 g_free(ctx); 1266 return 0; 1267 } 1268 optind++; 1269 1270 if (ctx->offset & 0x1ff) { 1271 printf("offset %" PRId64 " is not sector aligned\n", 1272 ctx->offset); 1273 g_free(ctx); 1274 return 0; 1275 } 1276 1277 nr_iov = argc - optind; 1278 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); 1279 if (ctx->buf == NULL) { 1280 g_free(ctx); 1281 return 0; 1282 } 1283 1284 gettimeofday(&ctx->t1, NULL); 1285 bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 1286 ctx->qiov.size >> 9, aio_read_done, ctx); 1287 return 0; 1288 } 1289 1290 static void aio_write_help(void) 1291 { 1292 printf( 1293 "\n" 1294 " asynchronously writes a range of bytes from the given offset source\n" 1295 " from multiple buffers\n" 1296 "\n" 1297 " Example:\n" 1298 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1299 "\n" 1300 " Writes into a segment of the currently open file, using a buffer\n" 1301 " filled with a set pattern (0xcdcdcdcd).\n" 1302 " The write is performed asynchronously and the aio_flush command must be\n" 1303 " used to ensure all outstanding aio requests have been completed.\n" 1304 " -P, -- use different pattern to fill file\n" 1305 " -C, -- report statistics in a machine parsable format\n" 1306 " -q, -- quiet mode, do not show I/O statistics\n" 1307 "\n"); 1308 } 1309 1310 static int aio_write_f(int argc, char **argv); 1311 1312 static const cmdinfo_t aio_write_cmd = { 1313 .name = "aio_write", 1314 .cfunc = aio_write_f, 1315 .argmin = 2, 1316 .argmax = -1, 1317 .args = "[-Cq] [-P pattern ] off len [len..]", 1318 .oneline = "asynchronously writes a number of bytes", 1319 .help = aio_write_help, 1320 }; 1321 1322 static int aio_write_f(int argc, char **argv) 1323 { 1324 int nr_iov, c; 1325 int pattern = 0xcd; 1326 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1327 1328 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 1329 switch (c) { 1330 case 'C': 1331 ctx->Cflag = 1; 1332 break; 1333 case 'q': 1334 ctx->qflag = 1; 1335 break; 1336 case 'P': 1337 pattern = parse_pattern(optarg); 1338 if (pattern < 0) { 1339 g_free(ctx); 1340 return 0; 1341 } 1342 break; 1343 default: 1344 g_free(ctx); 1345 return command_usage(&aio_write_cmd); 1346 } 1347 } 1348 1349 if (optind > argc - 2) { 1350 g_free(ctx); 1351 return command_usage(&aio_write_cmd); 1352 } 1353 1354 ctx->offset = cvtnum(argv[optind]); 1355 if (ctx->offset < 0) { 1356 printf("non-numeric length argument -- %s\n", argv[optind]); 1357 g_free(ctx); 1358 return 0; 1359 } 1360 optind++; 1361 1362 if (ctx->offset & 0x1ff) { 1363 printf("offset %" PRId64 " is not sector aligned\n", 1364 ctx->offset); 1365 g_free(ctx); 1366 return 0; 1367 } 1368 1369 nr_iov = argc - optind; 1370 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); 1371 if (ctx->buf == NULL) { 1372 g_free(ctx); 1373 return 0; 1374 } 1375 1376 gettimeofday(&ctx->t1, NULL); 1377 bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 1378 ctx->qiov.size >> 9, aio_write_done, ctx); 1379 return 0; 1380 } 1381 1382 static int aio_flush_f(int argc, char **argv) 1383 { 1384 bdrv_drain_all(); 1385 return 0; 1386 } 1387 1388 static const cmdinfo_t aio_flush_cmd = { 1389 .name = "aio_flush", 1390 .cfunc = aio_flush_f, 1391 .oneline = "completes all outstanding aio requests" 1392 }; 1393 1394 static int flush_f(int argc, char **argv) 1395 { 1396 bdrv_flush(bs); 1397 return 0; 1398 } 1399 1400 static const cmdinfo_t flush_cmd = { 1401 .name = "flush", 1402 .altname = "f", 1403 .cfunc = flush_f, 1404 .oneline = "flush all in-core file state to disk", 1405 }; 1406 1407 static int truncate_f(int argc, char **argv) 1408 { 1409 int64_t offset; 1410 int ret; 1411 1412 offset = cvtnum(argv[1]); 1413 if (offset < 0) { 1414 printf("non-numeric truncate argument -- %s\n", argv[1]); 1415 return 0; 1416 } 1417 1418 ret = bdrv_truncate(bs, offset); 1419 if (ret < 0) { 1420 printf("truncate: %s\n", strerror(-ret)); 1421 return 0; 1422 } 1423 1424 return 0; 1425 } 1426 1427 static const cmdinfo_t truncate_cmd = { 1428 .name = "truncate", 1429 .altname = "t", 1430 .cfunc = truncate_f, 1431 .argmin = 1, 1432 .argmax = 1, 1433 .args = "off", 1434 .oneline = "truncates the current file at the given offset", 1435 }; 1436 1437 static int length_f(int argc, char **argv) 1438 { 1439 int64_t size; 1440 char s1[64]; 1441 1442 size = bdrv_getlength(bs); 1443 if (size < 0) { 1444 printf("getlength: %s\n", strerror(-size)); 1445 return 0; 1446 } 1447 1448 cvtstr(size, s1, sizeof(s1)); 1449 printf("%s\n", s1); 1450 return 0; 1451 } 1452 1453 1454 static const cmdinfo_t length_cmd = { 1455 .name = "length", 1456 .altname = "l", 1457 .cfunc = length_f, 1458 .oneline = "gets the length of the current file", 1459 }; 1460 1461 1462 static int info_f(int argc, char **argv) 1463 { 1464 BlockDriverInfo bdi; 1465 char s1[64], s2[64]; 1466 int ret; 1467 1468 if (bs->drv && bs->drv->format_name) { 1469 printf("format name: %s\n", bs->drv->format_name); 1470 } 1471 if (bs->drv && bs->drv->protocol_name) { 1472 printf("format name: %s\n", bs->drv->protocol_name); 1473 } 1474 1475 ret = bdrv_get_info(bs, &bdi); 1476 if (ret) { 1477 return 0; 1478 } 1479 1480 cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1481 cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1482 1483 printf("cluster size: %s\n", s1); 1484 printf("vm state offset: %s\n", s2); 1485 1486 return 0; 1487 } 1488 1489 1490 1491 static const cmdinfo_t info_cmd = { 1492 .name = "info", 1493 .altname = "i", 1494 .cfunc = info_f, 1495 .oneline = "prints information about the current file", 1496 }; 1497 1498 static void discard_help(void) 1499 { 1500 printf( 1501 "\n" 1502 " discards a range of bytes from the given offset\n" 1503 "\n" 1504 " Example:\n" 1505 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n" 1506 "\n" 1507 " Discards a segment of the currently open file.\n" 1508 " -C, -- report statistics in a machine parsable format\n" 1509 " -q, -- quiet mode, do not show I/O statistics\n" 1510 "\n"); 1511 } 1512 1513 static int discard_f(int argc, char **argv); 1514 1515 static const cmdinfo_t discard_cmd = { 1516 .name = "discard", 1517 .altname = "d", 1518 .cfunc = discard_f, 1519 .argmin = 2, 1520 .argmax = -1, 1521 .args = "[-Cq] off len", 1522 .oneline = "discards a number of bytes at a specified offset", 1523 .help = discard_help, 1524 }; 1525 1526 static int discard_f(int argc, char **argv) 1527 { 1528 struct timeval t1, t2; 1529 int Cflag = 0, qflag = 0; 1530 int c, ret; 1531 int64_t offset; 1532 int count; 1533 1534 while ((c = getopt(argc, argv, "Cq")) != EOF) { 1535 switch (c) { 1536 case 'C': 1537 Cflag = 1; 1538 break; 1539 case 'q': 1540 qflag = 1; 1541 break; 1542 default: 1543 return command_usage(&discard_cmd); 1544 } 1545 } 1546 1547 if (optind != argc - 2) { 1548 return command_usage(&discard_cmd); 1549 } 1550 1551 offset = cvtnum(argv[optind]); 1552 if (offset < 0) { 1553 printf("non-numeric length argument -- %s\n", argv[optind]); 1554 return 0; 1555 } 1556 1557 optind++; 1558 count = cvtnum(argv[optind]); 1559 if (count < 0) { 1560 printf("non-numeric length argument -- %s\n", argv[optind]); 1561 return 0; 1562 } 1563 1564 gettimeofday(&t1, NULL); 1565 ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, 1566 count >> BDRV_SECTOR_BITS); 1567 gettimeofday(&t2, NULL); 1568 1569 if (ret < 0) { 1570 printf("discard failed: %s\n", strerror(-ret)); 1571 goto out; 1572 } 1573 1574 /* Finally, report back -- -C gives a parsable format */ 1575 if (!qflag) { 1576 t2 = tsub(t2, t1); 1577 print_report("discard", &t2, offset, count, count, 1, Cflag); 1578 } 1579 1580 out: 1581 return 0; 1582 } 1583 1584 static int alloc_f(int argc, char **argv) 1585 { 1586 int64_t offset, sector_num; 1587 int nb_sectors, remaining; 1588 char s1[64]; 1589 int num, sum_alloc; 1590 int ret; 1591 1592 offset = cvtnum(argv[1]); 1593 if (offset & 0x1ff) { 1594 printf("offset %" PRId64 " is not sector aligned\n", 1595 offset); 1596 return 0; 1597 } 1598 1599 if (argc == 3) { 1600 nb_sectors = cvtnum(argv[2]); 1601 } else { 1602 nb_sectors = 1; 1603 } 1604 1605 remaining = nb_sectors; 1606 sum_alloc = 0; 1607 sector_num = offset >> 9; 1608 while (remaining) { 1609 ret = bdrv_is_allocated(bs, sector_num, remaining, &num); 1610 sector_num += num; 1611 remaining -= num; 1612 if (ret) { 1613 sum_alloc += num; 1614 } 1615 if (num == 0) { 1616 nb_sectors -= remaining; 1617 remaining = 0; 1618 } 1619 } 1620 1621 cvtstr(offset, s1, sizeof(s1)); 1622 1623 printf("%d/%d sectors allocated at offset %s\n", 1624 sum_alloc, nb_sectors, s1); 1625 return 0; 1626 } 1627 1628 static const cmdinfo_t alloc_cmd = { 1629 .name = "alloc", 1630 .altname = "a", 1631 .argmin = 1, 1632 .argmax = 2, 1633 .cfunc = alloc_f, 1634 .args = "off [sectors]", 1635 .oneline = "checks if a sector is present in the file", 1636 }; 1637 1638 static int map_f(int argc, char **argv) 1639 { 1640 int64_t offset; 1641 int64_t nb_sectors; 1642 char s1[64]; 1643 int num, num_checked; 1644 int ret; 1645 const char *retstr; 1646 1647 offset = 0; 1648 nb_sectors = bs->total_sectors; 1649 1650 do { 1651 num_checked = MIN(nb_sectors, INT_MAX); 1652 ret = bdrv_is_allocated(bs, offset, num_checked, &num); 1653 retstr = ret ? " allocated" : "not allocated"; 1654 cvtstr(offset << 9ULL, s1, sizeof(s1)); 1655 printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n", 1656 offset << 9ULL, num, num_checked, retstr, s1, ret); 1657 1658 offset += num; 1659 nb_sectors -= num; 1660 } while (offset < bs->total_sectors); 1661 1662 return 0; 1663 } 1664 1665 static const cmdinfo_t map_cmd = { 1666 .name = "map", 1667 .argmin = 0, 1668 .argmax = 0, 1669 .cfunc = map_f, 1670 .args = "", 1671 .oneline = "prints the allocated areas of a file", 1672 }; 1673 1674 static int break_f(int argc, char **argv) 1675 { 1676 int ret; 1677 1678 ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]); 1679 if (ret < 0) { 1680 printf("Could not set breakpoint: %s\n", strerror(-ret)); 1681 } 1682 1683 return 0; 1684 } 1685 1686 static const cmdinfo_t break_cmd = { 1687 .name = "break", 1688 .argmin = 2, 1689 .argmax = 2, 1690 .cfunc = break_f, 1691 .args = "event tag", 1692 .oneline = "sets a breakpoint on event and tags the stopped " 1693 "request as tag", 1694 }; 1695 1696 static int resume_f(int argc, char **argv) 1697 { 1698 int ret; 1699 1700 ret = bdrv_debug_resume(bs, argv[1]); 1701 if (ret < 0) { 1702 printf("Could not resume request: %s\n", strerror(-ret)); 1703 } 1704 1705 return 0; 1706 } 1707 1708 static const cmdinfo_t resume_cmd = { 1709 .name = "resume", 1710 .argmin = 1, 1711 .argmax = 1, 1712 .cfunc = resume_f, 1713 .args = "tag", 1714 .oneline = "resumes the request tagged as tag", 1715 }; 1716 1717 static int wait_break_f(int argc, char **argv) 1718 { 1719 while (!bdrv_debug_is_suspended(bs, argv[1])) { 1720 qemu_aio_wait(); 1721 } 1722 1723 return 0; 1724 } 1725 1726 static const cmdinfo_t wait_break_cmd = { 1727 .name = "wait_break", 1728 .argmin = 1, 1729 .argmax = 1, 1730 .cfunc = wait_break_f, 1731 .args = "tag", 1732 .oneline = "waits for the suspension of a request", 1733 }; 1734 1735 static int abort_f(int argc, char **argv) 1736 { 1737 abort(); 1738 } 1739 1740 static const cmdinfo_t abort_cmd = { 1741 .name = "abort", 1742 .cfunc = abort_f, 1743 .flags = CMD_NOFILE_OK, 1744 .oneline = "simulate a program crash using abort(3)", 1745 }; 1746 1747 static int close_f(int argc, char **argv) 1748 { 1749 bdrv_delete(bs); 1750 bs = NULL; 1751 return 0; 1752 } 1753 1754 static const cmdinfo_t close_cmd = { 1755 .name = "close", 1756 .altname = "c", 1757 .cfunc = close_f, 1758 .oneline = "close the current open file", 1759 }; 1760 1761 static int openfile(char *name, int flags, int growable) 1762 { 1763 if (bs) { 1764 fprintf(stderr, "file open already, try 'help close'\n"); 1765 return 1; 1766 } 1767 1768 if (growable) { 1769 if (bdrv_file_open(&bs, name, NULL, flags)) { 1770 fprintf(stderr, "%s: can't open device %s\n", progname, name); 1771 return 1; 1772 } 1773 } else { 1774 bs = bdrv_new("hda"); 1775 1776 if (bdrv_open(bs, name, NULL, flags, NULL) < 0) { 1777 fprintf(stderr, "%s: can't open device %s\n", progname, name); 1778 bdrv_delete(bs); 1779 bs = NULL; 1780 return 1; 1781 } 1782 } 1783 1784 return 0; 1785 } 1786 1787 static void open_help(void) 1788 { 1789 printf( 1790 "\n" 1791 " opens a new file in the requested mode\n" 1792 "\n" 1793 " Example:\n" 1794 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 1795 "\n" 1796 " Opens a file for subsequent use by all of the other qemu-io commands.\n" 1797 " -r, -- open file read-only\n" 1798 " -s, -- use snapshot file\n" 1799 " -n, -- disable host cache\n" 1800 " -g, -- allow file to grow (only applies to protocols)" 1801 "\n"); 1802 } 1803 1804 static int open_f(int argc, char **argv); 1805 1806 static const cmdinfo_t open_cmd = { 1807 .name = "open", 1808 .altname = "o", 1809 .cfunc = open_f, 1810 .argmin = 1, 1811 .argmax = -1, 1812 .flags = CMD_NOFILE_OK, 1813 .args = "[-Crsn] [path]", 1814 .oneline = "open the file specified by path", 1815 .help = open_help, 1816 }; 1817 1818 static int open_f(int argc, char **argv) 1819 { 1820 int flags = 0; 1821 int readonly = 0; 1822 int growable = 0; 1823 int c; 1824 1825 while ((c = getopt(argc, argv, "snrg")) != EOF) { 1826 switch (c) { 1827 case 's': 1828 flags |= BDRV_O_SNAPSHOT; 1829 break; 1830 case 'n': 1831 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 1832 break; 1833 case 'r': 1834 readonly = 1; 1835 break; 1836 case 'g': 1837 growable = 1; 1838 break; 1839 default: 1840 return command_usage(&open_cmd); 1841 } 1842 } 1843 1844 if (!readonly) { 1845 flags |= BDRV_O_RDWR; 1846 } 1847 1848 if (optind != argc - 1) { 1849 return command_usage(&open_cmd); 1850 } 1851 1852 return openfile(argv[optind], flags, growable); 1853 } 1854 1855 static int init_args_command(int index) 1856 { 1857 /* only one device allowed so far */ 1858 if (index >= 1) { 1859 return 0; 1860 } 1861 return ++index; 1862 } 1863 1864 static int init_check_command(const cmdinfo_t *ct) 1865 { 1866 if (ct->flags & CMD_FLAG_GLOBAL) { 1867 return 1; 1868 } 1869 if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1870 fprintf(stderr, "no file open, try 'help open'\n"); 1871 return 0; 1872 } 1873 return 1; 1874 } 1875 1876 static void usage(const char *name) 1877 { 1878 printf( 1879 "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" 1880 "QEMU Disk exerciser\n" 1881 "\n" 1882 " -c, --cmd command to execute\n" 1883 " -r, --read-only export read-only\n" 1884 " -s, --snapshot use snapshot file\n" 1885 " -n, --nocache disable host cache\n" 1886 " -g, --growable allow file to grow (only applies to protocols)\n" 1887 " -m, --misalign misalign allocations for O_DIRECT\n" 1888 " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 1889 " -t, --cache=MODE use the given cache mode for the image\n" 1890 " -T, --trace FILE enable trace events listed in the given file\n" 1891 " -h, --help display this help and exit\n" 1892 " -V, --version output version information and exit\n" 1893 "\n", 1894 name); 1895 } 1896 1897 1898 int main(int argc, char **argv) 1899 { 1900 int readonly = 0; 1901 int growable = 0; 1902 const char *sopt = "hVc:d:rsnmgkt:T:"; 1903 const struct option lopt[] = { 1904 { "help", 0, NULL, 'h' }, 1905 { "version", 0, NULL, 'V' }, 1906 { "offset", 1, NULL, 'o' }, 1907 { "cmd", 1, NULL, 'c' }, 1908 { "read-only", 0, NULL, 'r' }, 1909 { "snapshot", 0, NULL, 's' }, 1910 { "nocache", 0, NULL, 'n' }, 1911 { "misalign", 0, NULL, 'm' }, 1912 { "growable", 0, NULL, 'g' }, 1913 { "native-aio", 0, NULL, 'k' }, 1914 { "discard", 1, NULL, 'd' }, 1915 { "cache", 1, NULL, 't' }, 1916 { "trace", 1, NULL, 'T' }, 1917 { NULL, 0, NULL, 0 } 1918 }; 1919 int c; 1920 int opt_index = 0; 1921 int flags = BDRV_O_UNMAP; 1922 1923 progname = basename(argv[0]); 1924 1925 while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1926 switch (c) { 1927 case 's': 1928 flags |= BDRV_O_SNAPSHOT; 1929 break; 1930 case 'n': 1931 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 1932 break; 1933 case 'd': 1934 if (bdrv_parse_discard_flags(optarg, &flags) < 0) { 1935 error_report("Invalid discard option: %s", optarg); 1936 exit(1); 1937 } 1938 break; 1939 case 'c': 1940 add_user_command(optarg); 1941 break; 1942 case 'r': 1943 readonly = 1; 1944 break; 1945 case 'm': 1946 misalign = 1; 1947 break; 1948 case 'g': 1949 growable = 1; 1950 break; 1951 case 'k': 1952 flags |= BDRV_O_NATIVE_AIO; 1953 break; 1954 case 't': 1955 if (bdrv_parse_cache_flags(optarg, &flags) < 0) { 1956 error_report("Invalid cache option: %s", optarg); 1957 exit(1); 1958 } 1959 break; 1960 case 'T': 1961 if (!trace_backend_init(optarg, NULL)) { 1962 exit(1); /* error message will have been printed */ 1963 } 1964 break; 1965 case 'V': 1966 printf("%s version %s\n", progname, VERSION); 1967 exit(0); 1968 case 'h': 1969 usage(progname); 1970 exit(0); 1971 default: 1972 usage(progname); 1973 exit(1); 1974 } 1975 } 1976 1977 if ((argc - optind) > 1) { 1978 usage(progname); 1979 exit(1); 1980 } 1981 1982 qemu_init_main_loop(); 1983 bdrv_init(); 1984 1985 /* initialize commands */ 1986 quit_init(); 1987 help_init(); 1988 add_command(&open_cmd); 1989 add_command(&close_cmd); 1990 add_command(&read_cmd); 1991 add_command(&readv_cmd); 1992 add_command(&write_cmd); 1993 add_command(&writev_cmd); 1994 add_command(&multiwrite_cmd); 1995 add_command(&aio_read_cmd); 1996 add_command(&aio_write_cmd); 1997 add_command(&aio_flush_cmd); 1998 add_command(&flush_cmd); 1999 add_command(&truncate_cmd); 2000 add_command(&length_cmd); 2001 add_command(&info_cmd); 2002 add_command(&discard_cmd); 2003 add_command(&alloc_cmd); 2004 add_command(&map_cmd); 2005 add_command(&break_cmd); 2006 add_command(&resume_cmd); 2007 add_command(&wait_break_cmd); 2008 add_command(&abort_cmd); 2009 2010 add_args_command(init_args_command); 2011 add_check_command(init_check_command); 2012 2013 /* open the device */ 2014 if (!readonly) { 2015 flags |= BDRV_O_RDWR; 2016 } 2017 2018 if ((argc - optind) == 1) { 2019 openfile(argv[optind], flags, growable); 2020 } 2021 command_loop(); 2022 2023 /* 2024 * Make sure all outstanding requests complete before the program exits. 2025 */ 2026 bdrv_drain_all(); 2027 2028 if (bs) { 2029 bdrv_delete(bs); 2030 } 2031 return 0; 2032 } 2033