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 "block_int.h" 19 #include "cmd.h" 20 21 #define VERSION "0.0.1" 22 23 #define CMD_NOFILE_OK 0x01 24 25 char *progname; 26 static BlockDriverState *bs; 27 28 static int misalign; 29 30 /* 31 * Parse the pattern argument to various sub-commands. 32 * 33 * Because the pattern is used as an argument to memset it must evaluate 34 * to an unsigned integer that fits into a single byte. 35 */ 36 static int parse_pattern(const char *arg) 37 { 38 char *endptr = NULL; 39 long pattern; 40 41 pattern = strtol(arg, &endptr, 0); 42 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') { 43 printf("%s is not a valid pattern byte\n", arg); 44 return -1; 45 } 46 47 return pattern; 48 } 49 50 /* 51 * Memory allocation helpers. 52 * 53 * Make sure memory is aligned by default, or purposefully misaligned if 54 * that is specified on the command line. 55 */ 56 57 #define MISALIGN_OFFSET 16 58 static void *qemu_io_alloc(size_t len, int pattern) 59 { 60 void *buf; 61 62 if (misalign) 63 len += MISALIGN_OFFSET; 64 buf = qemu_memalign(512, len); 65 memset(buf, pattern, len); 66 if (misalign) 67 buf += MISALIGN_OFFSET; 68 return buf; 69 } 70 71 static void qemu_io_free(void *p) 72 { 73 if (misalign) 74 p -= MISALIGN_OFFSET; 75 qemu_vfree(p); 76 } 77 78 static void 79 dump_buffer(const void *buffer, int64_t offset, int len) 80 { 81 int i, j; 82 const uint8_t *p; 83 84 for (i = 0, p = buffer; i < len; i += 16) { 85 const uint8_t *s = p; 86 87 printf("%08llx: ", (unsigned long long)offset + i); 88 for (j = 0; j < 16 && i + j < len; j++, p++) 89 printf("%02x ", *p); 90 printf(" "); 91 for (j = 0; j < 16 && i + j < len; j++, s++) { 92 if (isalnum(*s)) 93 printf("%c", *s); 94 else 95 printf("."); 96 } 97 printf("\n"); 98 } 99 } 100 101 static void 102 print_report(const char *op, struct timeval *t, int64_t offset, 103 int count, int total, int cnt, int Cflag) 104 { 105 char s1[64], s2[64], ts[64]; 106 107 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); 108 if (!Cflag) { 109 cvtstr((double)total, s1, sizeof(s1)); 110 cvtstr(tdiv((double)total, *t), s2, sizeof(s2)); 111 printf("%s %d/%d bytes at offset %lld\n", 112 op, total, count, (long long)offset); 113 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n", 114 s1, cnt, ts, s2, tdiv((double)cnt, *t)); 115 } else {/* bytes,ops,time,bytes/sec,ops/sec */ 116 printf("%d,%d,%s,%.3f,%.3f\n", 117 total, cnt, ts, 118 tdiv((double)total, *t), 119 tdiv((double)cnt, *t)); 120 } 121 } 122 123 /* 124 * Parse multiple length statements for vectored I/O, and construct an I/O 125 * vector matching it. 126 */ 127 static void * 128 create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern) 129 { 130 size_t *sizes = calloc(nr_iov, sizeof(size_t)); 131 size_t count = 0; 132 void *buf, *p; 133 int i; 134 135 for (i = 0; i < nr_iov; i++) { 136 char *arg = argv[i]; 137 long long len; 138 139 len = cvtnum(arg); 140 if (len < 0) { 141 printf("non-numeric length argument -- %s\n", arg); 142 return NULL; 143 } 144 145 /* should be SIZE_T_MAX, but that doesn't exist */ 146 if (len > UINT_MAX) { 147 printf("too large length argument -- %s\n", arg); 148 return NULL; 149 } 150 151 if (len & 0x1ff) { 152 printf("length argument %lld is not sector aligned\n", 153 len); 154 return NULL; 155 } 156 157 sizes[i] = len; 158 count += len; 159 } 160 161 qemu_iovec_init(qiov, nr_iov); 162 163 buf = p = qemu_io_alloc(count, pattern); 164 165 for (i = 0; i < nr_iov; i++) { 166 qemu_iovec_add(qiov, p, sizes[i]); 167 p += sizes[i]; 168 } 169 170 free(sizes); 171 return buf; 172 } 173 174 static int do_read(char *buf, int64_t offset, int count, int *total) 175 { 176 int ret; 177 178 ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9); 179 if (ret < 0) 180 return ret; 181 *total = count; 182 return 1; 183 } 184 185 static int do_write(char *buf, int64_t offset, int count, int *total) 186 { 187 int ret; 188 189 ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9); 190 if (ret < 0) 191 return ret; 192 *total = count; 193 return 1; 194 } 195 196 static int do_pread(char *buf, int64_t offset, int count, int *total) 197 { 198 *total = bdrv_pread(bs, offset, (uint8_t *)buf, count); 199 if (*total < 0) 200 return *total; 201 return 1; 202 } 203 204 static int do_pwrite(char *buf, int64_t offset, int count, int *total) 205 { 206 *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count); 207 if (*total < 0) 208 return *total; 209 return 1; 210 } 211 212 static int do_load_vmstate(char *buf, int64_t offset, int count, int *total) 213 { 214 *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count); 215 if (*total < 0) 216 return *total; 217 return 1; 218 } 219 220 static int do_save_vmstate(char *buf, int64_t offset, int count, int *total) 221 { 222 *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count); 223 if (*total < 0) 224 return *total; 225 return 1; 226 } 227 228 #define NOT_DONE 0x7fffffff 229 static void aio_rw_done(void *opaque, int ret) 230 { 231 *(int *)opaque = ret; 232 } 233 234 static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total) 235 { 236 BlockDriverAIOCB *acb; 237 int async_ret = NOT_DONE; 238 239 acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, 240 aio_rw_done, &async_ret); 241 if (!acb) 242 return -EIO; 243 244 while (async_ret == NOT_DONE) 245 qemu_aio_wait(); 246 247 *total = qiov->size; 248 return async_ret < 0 ? async_ret : 1; 249 } 250 251 static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) 252 { 253 BlockDriverAIOCB *acb; 254 int async_ret = NOT_DONE; 255 256 acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, 257 aio_rw_done, &async_ret); 258 if (!acb) 259 return -EIO; 260 261 while (async_ret == NOT_DONE) 262 qemu_aio_wait(); 263 264 *total = qiov->size; 265 return async_ret < 0 ? async_ret : 1; 266 } 267 268 269 static const cmdinfo_t read_cmd; 270 271 static void 272 read_help(void) 273 { 274 printf( 275 "\n" 276 " reads a range of bytes from the given offset\n" 277 "\n" 278 " Example:\n" 279 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 280 "\n" 281 " Reads a segment of the currently open file, optionally dumping it to the\n" 282 " standard output stream (with -v option) for subsequent inspection.\n" 283 " -b, -- read from the VM state rather than the virtual disk\n" 284 " -C, -- report statistics in a machine parsable format\n" 285 " -l, -- length for pattern verification (only with -P)\n" 286 " -p, -- use bdrv_pread to read the file\n" 287 " -P, -- use a pattern to verify read data\n" 288 " -q, -- quite mode, do not show I/O statistics\n" 289 " -s, -- start offset for pattern verification (only with -P)\n" 290 " -v, -- dump buffer to standard output\n" 291 "\n"); 292 } 293 294 static int 295 read_f(int argc, char **argv) 296 { 297 struct timeval t1, t2; 298 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 299 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; 300 int c, cnt; 301 char *buf; 302 int64_t offset; 303 int count; 304 /* Some compilers get confused and warn if this is not initialized. */ 305 int total = 0; 306 int pattern = 0, pattern_offset = 0, pattern_count = 0; 307 308 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { 309 switch (c) { 310 case 'b': 311 bflag = 1; 312 break; 313 case 'C': 314 Cflag = 1; 315 break; 316 case 'l': 317 lflag = 1; 318 pattern_count = cvtnum(optarg); 319 if (pattern_count < 0) { 320 printf("non-numeric length argument -- %s\n", optarg); 321 return 0; 322 } 323 break; 324 case 'p': 325 pflag = 1; 326 break; 327 case 'P': 328 Pflag = 1; 329 pattern = parse_pattern(optarg); 330 if (pattern < 0) 331 return 0; 332 break; 333 case 'q': 334 qflag = 1; 335 break; 336 case 's': 337 sflag = 1; 338 pattern_offset = cvtnum(optarg); 339 if (pattern_offset < 0) { 340 printf("non-numeric length argument -- %s\n", optarg); 341 return 0; 342 } 343 break; 344 case 'v': 345 vflag = 1; 346 break; 347 default: 348 return command_usage(&read_cmd); 349 } 350 } 351 352 if (optind != argc - 2) 353 return command_usage(&read_cmd); 354 355 if (bflag && pflag) { 356 printf("-b and -p cannot be specified at the same time\n"); 357 return 0; 358 } 359 360 offset = cvtnum(argv[optind]); 361 if (offset < 0) { 362 printf("non-numeric length argument -- %s\n", argv[optind]); 363 return 0; 364 } 365 366 optind++; 367 count = cvtnum(argv[optind]); 368 if (count < 0) { 369 printf("non-numeric length argument -- %s\n", argv[optind]); 370 return 0; 371 } 372 373 if (!Pflag && (lflag || sflag)) { 374 return command_usage(&read_cmd); 375 } 376 377 if (!lflag) { 378 pattern_count = count - pattern_offset; 379 } 380 381 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 382 printf("pattern verfication range exceeds end of read data\n"); 383 return 0; 384 } 385 386 if (!pflag) 387 if (offset & 0x1ff) { 388 printf("offset %lld is not sector aligned\n", 389 (long long)offset); 390 return 0; 391 392 if (count & 0x1ff) { 393 printf("count %d is not sector aligned\n", 394 count); 395 return 0; 396 } 397 } 398 399 buf = qemu_io_alloc(count, 0xab); 400 401 gettimeofday(&t1, NULL); 402 if (pflag) 403 cnt = do_pread(buf, offset, count, &total); 404 else if (bflag) 405 cnt = do_load_vmstate(buf, offset, count, &total); 406 else 407 cnt = do_read(buf, offset, count, &total); 408 gettimeofday(&t2, NULL); 409 410 if (cnt < 0) { 411 printf("read failed: %s\n", strerror(-cnt)); 412 goto out; 413 } 414 415 if (Pflag) { 416 void* cmp_buf = malloc(pattern_count); 417 memset(cmp_buf, pattern, pattern_count); 418 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 419 printf("Pattern verification failed at offset %lld, " 420 "%d bytes\n", 421 (long long) offset + pattern_offset, pattern_count); 422 } 423 free(cmp_buf); 424 } 425 426 if (qflag) 427 goto out; 428 429 if (vflag) 430 dump_buffer(buf, offset, count); 431 432 /* Finally, report back -- -C gives a parsable format */ 433 t2 = tsub(t2, t1); 434 print_report("read", &t2, offset, count, total, cnt, Cflag); 435 436 out: 437 qemu_io_free(buf); 438 439 return 0; 440 } 441 442 static const cmdinfo_t read_cmd = { 443 .name = "read", 444 .altname = "r", 445 .cfunc = read_f, 446 .argmin = 2, 447 .argmax = -1, 448 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", 449 .oneline = "reads a number of bytes at a specified offset", 450 .help = read_help, 451 }; 452 453 static const cmdinfo_t readv_cmd; 454 455 static void 456 readv_help(void) 457 { 458 printf( 459 "\n" 460 " reads a range of bytes from the given offset into multiple buffers\n" 461 "\n" 462 " Example:\n" 463 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 464 "\n" 465 " Reads a segment of the currently open file, optionally dumping it to the\n" 466 " standard output stream (with -v option) for subsequent inspection.\n" 467 " Uses multiple iovec buffers if more than one byte range is specified.\n" 468 " -C, -- report statistics in a machine parsable format\n" 469 " -P, -- use a pattern to verify read data\n" 470 " -v, -- dump buffer to standard output\n" 471 " -q, -- quite mode, do not show I/O statistics\n" 472 "\n"); 473 } 474 475 static int 476 readv_f(int argc, char **argv) 477 { 478 struct timeval t1, t2; 479 int Cflag = 0, qflag = 0, vflag = 0; 480 int c, cnt; 481 char *buf; 482 int64_t offset; 483 int total; 484 int nr_iov; 485 QEMUIOVector qiov; 486 int pattern = 0; 487 int Pflag = 0; 488 489 while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 490 switch (c) { 491 case 'C': 492 Cflag = 1; 493 break; 494 case 'P': 495 Pflag = 1; 496 pattern = parse_pattern(optarg); 497 if (pattern < 0) 498 return 0; 499 break; 500 case 'q': 501 qflag = 1; 502 break; 503 case 'v': 504 vflag = 1; 505 break; 506 default: 507 return command_usage(&readv_cmd); 508 } 509 } 510 511 if (optind > argc - 2) 512 return command_usage(&readv_cmd); 513 514 515 offset = cvtnum(argv[optind]); 516 if (offset < 0) { 517 printf("non-numeric length argument -- %s\n", argv[optind]); 518 return 0; 519 } 520 optind++; 521 522 if (offset & 0x1ff) { 523 printf("offset %lld is not sector aligned\n", 524 (long long)offset); 525 return 0; 526 } 527 528 nr_iov = argc - optind; 529 buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); 530 531 gettimeofday(&t1, NULL); 532 cnt = do_aio_readv(&qiov, offset, &total); 533 gettimeofday(&t2, NULL); 534 535 if (cnt < 0) { 536 printf("readv failed: %s\n", strerror(-cnt)); 537 goto out; 538 } 539 540 if (Pflag) { 541 void* cmp_buf = malloc(qiov.size); 542 memset(cmp_buf, pattern, qiov.size); 543 if (memcmp(buf, cmp_buf, qiov.size)) { 544 printf("Pattern verification failed at offset %lld, " 545 "%zd bytes\n", 546 (long long) offset, qiov.size); 547 } 548 free(cmp_buf); 549 } 550 551 if (qflag) 552 goto out; 553 554 if (vflag) 555 dump_buffer(buf, offset, qiov.size); 556 557 /* Finally, report back -- -C gives a parsable format */ 558 t2 = tsub(t2, t1); 559 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 560 561 out: 562 qemu_io_free(buf); 563 return 0; 564 } 565 566 static const cmdinfo_t readv_cmd = { 567 .name = "readv", 568 .cfunc = readv_f, 569 .argmin = 2, 570 .argmax = -1, 571 .args = "[-Cqv] [-P pattern ] off len [len..]", 572 .oneline = "reads a number of bytes at a specified offset", 573 .help = readv_help, 574 }; 575 576 static const cmdinfo_t write_cmd; 577 578 static void 579 write_help(void) 580 { 581 printf( 582 "\n" 583 " writes a range of bytes from the given offset\n" 584 "\n" 585 " Example:\n" 586 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 587 "\n" 588 " Writes into a segment of the currently open file, using a buffer\n" 589 " filled with a set pattern (0xcdcdcdcd).\n" 590 " -b, -- write to the VM state rather than the virtual disk\n" 591 " -p, -- use bdrv_pwrite to write the file\n" 592 " -P, -- use different pattern to fill file\n" 593 " -C, -- report statistics in a machine parsable format\n" 594 " -q, -- quite mode, do not show I/O statistics\n" 595 "\n"); 596 } 597 598 static int 599 write_f(int argc, char **argv) 600 { 601 struct timeval t1, t2; 602 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0; 603 int c, cnt; 604 char *buf; 605 int64_t offset; 606 int count; 607 /* Some compilers get confused and warn if this is not initialized. */ 608 int total = 0; 609 int pattern = 0xcd; 610 611 while ((c = getopt(argc, argv, "bCpP:q")) != EOF) { 612 switch (c) { 613 case 'b': 614 bflag = 1; 615 break; 616 case 'C': 617 Cflag = 1; 618 break; 619 case 'p': 620 pflag = 1; 621 break; 622 case 'P': 623 pattern = parse_pattern(optarg); 624 if (pattern < 0) 625 return 0; 626 break; 627 case 'q': 628 qflag = 1; 629 break; 630 default: 631 return command_usage(&write_cmd); 632 } 633 } 634 635 if (optind != argc - 2) 636 return command_usage(&write_cmd); 637 638 if (bflag && pflag) { 639 printf("-b and -p cannot be specified at the same time\n"); 640 return 0; 641 } 642 643 offset = cvtnum(argv[optind]); 644 if (offset < 0) { 645 printf("non-numeric length argument -- %s\n", argv[optind]); 646 return 0; 647 } 648 649 optind++; 650 count = cvtnum(argv[optind]); 651 if (count < 0) { 652 printf("non-numeric length argument -- %s\n", argv[optind]); 653 return 0; 654 } 655 656 if (!pflag) { 657 if (offset & 0x1ff) { 658 printf("offset %lld is not sector aligned\n", 659 (long long)offset); 660 return 0; 661 } 662 663 if (count & 0x1ff) { 664 printf("count %d is not sector aligned\n", 665 count); 666 return 0; 667 } 668 } 669 670 buf = qemu_io_alloc(count, pattern); 671 672 gettimeofday(&t1, NULL); 673 if (pflag) 674 cnt = do_pwrite(buf, offset, count, &total); 675 else if (bflag) 676 cnt = do_save_vmstate(buf, offset, count, &total); 677 else 678 cnt = do_write(buf, offset, count, &total); 679 gettimeofday(&t2, NULL); 680 681 if (cnt < 0) { 682 printf("write failed: %s\n", strerror(-cnt)); 683 goto out; 684 } 685 686 if (qflag) 687 goto out; 688 689 /* Finally, report back -- -C gives a parsable format */ 690 t2 = tsub(t2, t1); 691 print_report("wrote", &t2, offset, count, total, cnt, Cflag); 692 693 out: 694 qemu_io_free(buf); 695 696 return 0; 697 } 698 699 static const cmdinfo_t write_cmd = { 700 .name = "write", 701 .altname = "w", 702 .cfunc = write_f, 703 .argmin = 2, 704 .argmax = -1, 705 .args = "[-abCpq] [-P pattern ] off len", 706 .oneline = "writes a number of bytes at a specified offset", 707 .help = write_help, 708 }; 709 710 static const cmdinfo_t writev_cmd; 711 712 static void 713 writev_help(void) 714 { 715 printf( 716 "\n" 717 " writes a range of bytes from the given offset source from multiple buffers\n" 718 "\n" 719 " Example:\n" 720 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 721 "\n" 722 " Writes into a segment of the currently open file, using a buffer\n" 723 " filled with a set pattern (0xcdcdcdcd).\n" 724 " -P, -- use different pattern to fill file\n" 725 " -C, -- report statistics in a machine parsable format\n" 726 " -q, -- quite mode, do not show I/O statistics\n" 727 "\n"); 728 } 729 730 static int 731 writev_f(int argc, char **argv) 732 { 733 struct timeval t1, t2; 734 int Cflag = 0, qflag = 0; 735 int c, cnt; 736 char *buf; 737 int64_t offset; 738 int total; 739 int nr_iov; 740 int pattern = 0xcd; 741 QEMUIOVector qiov; 742 743 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 744 switch (c) { 745 case 'C': 746 Cflag = 1; 747 break; 748 case 'q': 749 qflag = 1; 750 break; 751 case 'P': 752 pattern = parse_pattern(optarg); 753 if (pattern < 0) 754 return 0; 755 break; 756 default: 757 return command_usage(&writev_cmd); 758 } 759 } 760 761 if (optind > argc - 2) 762 return command_usage(&writev_cmd); 763 764 offset = cvtnum(argv[optind]); 765 if (offset < 0) { 766 printf("non-numeric length argument -- %s\n", argv[optind]); 767 return 0; 768 } 769 optind++; 770 771 if (offset & 0x1ff) { 772 printf("offset %lld is not sector aligned\n", 773 (long long)offset); 774 return 0; 775 } 776 777 nr_iov = argc - optind; 778 buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); 779 780 gettimeofday(&t1, NULL); 781 cnt = do_aio_writev(&qiov, offset, &total); 782 gettimeofday(&t2, NULL); 783 784 if (cnt < 0) { 785 printf("writev failed: %s\n", strerror(-cnt)); 786 goto out; 787 } 788 789 if (qflag) 790 goto out; 791 792 /* Finally, report back -- -C gives a parsable format */ 793 t2 = tsub(t2, t1); 794 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 795 out: 796 qemu_io_free(buf); 797 return 0; 798 } 799 800 static const cmdinfo_t writev_cmd = { 801 .name = "writev", 802 .cfunc = writev_f, 803 .argmin = 2, 804 .argmax = -1, 805 .args = "[-Cq] [-P pattern ] off len [len..]", 806 .oneline = "writes a number of bytes at a specified offset", 807 .help = writev_help, 808 }; 809 810 struct aio_ctx { 811 QEMUIOVector qiov; 812 int64_t offset; 813 char *buf; 814 int qflag; 815 int vflag; 816 int Cflag; 817 int Pflag; 818 int pattern; 819 struct timeval t1; 820 }; 821 822 static void 823 aio_write_done(void *opaque, int ret) 824 { 825 struct aio_ctx *ctx = opaque; 826 struct timeval t2; 827 828 gettimeofday(&t2, NULL); 829 830 831 if (ret < 0) { 832 printf("aio_write failed: %s\n", strerror(-ret)); 833 goto out; 834 } 835 836 if (ctx->qflag) { 837 goto out; 838 } 839 840 /* Finally, report back -- -C gives a parsable format */ 841 t2 = tsub(t2, ctx->t1); 842 print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 843 ctx->qiov.size, 1, ctx->Cflag); 844 out: 845 qemu_io_free(ctx->buf); 846 free(ctx); 847 } 848 849 static const cmdinfo_t aio_read_cmd; 850 851 static void 852 aio_read_done(void *opaque, int ret) 853 { 854 struct aio_ctx *ctx = opaque; 855 struct timeval t2; 856 857 gettimeofday(&t2, NULL); 858 859 if (ret < 0) { 860 printf("readv failed: %s\n", strerror(-ret)); 861 goto out; 862 } 863 864 if (ctx->Pflag) { 865 void *cmp_buf = malloc(ctx->qiov.size); 866 867 memset(cmp_buf, ctx->pattern, ctx->qiov.size); 868 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 869 printf("Pattern verification failed at offset %lld, " 870 "%zd bytes\n", 871 (long long) ctx->offset, ctx->qiov.size); 872 } 873 free(cmp_buf); 874 } 875 876 if (ctx->qflag) { 877 goto out; 878 } 879 880 if (ctx->vflag) { 881 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 882 } 883 884 /* Finally, report back -- -C gives a parsable format */ 885 t2 = tsub(t2, ctx->t1); 886 print_report("read", &t2, ctx->offset, ctx->qiov.size, 887 ctx->qiov.size, 1, ctx->Cflag); 888 out: 889 qemu_io_free(ctx->buf); 890 free(ctx); 891 } 892 893 static void 894 aio_read_help(void) 895 { 896 printf( 897 "\n" 898 " asynchronously reads a range of bytes from the given offset\n" 899 "\n" 900 " Example:\n" 901 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 902 "\n" 903 " Reads a segment of the currently open file, optionally dumping it to the\n" 904 " standard output stream (with -v option) for subsequent inspection.\n" 905 " The read is performed asynchronously and should the aio_flush command \n" 906 " should be used to ensure all outstanding aio requests have been completed\n" 907 " -C, -- report statistics in a machine parsable format\n" 908 " -P, -- use a pattern to verify read data\n" 909 " -v, -- dump buffer to standard output\n" 910 " -q, -- quite mode, do not show I/O statistics\n" 911 "\n"); 912 } 913 914 static int 915 aio_read_f(int argc, char **argv) 916 { 917 int nr_iov, c; 918 struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 919 BlockDriverAIOCB *acb; 920 921 while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 922 switch (c) { 923 case 'C': 924 ctx->Cflag = 1; 925 break; 926 case 'P': 927 ctx->Pflag = 1; 928 ctx->pattern = parse_pattern(optarg); 929 if (ctx->pattern < 0) 930 return 0; 931 break; 932 case 'q': 933 ctx->qflag = 1; 934 break; 935 case 'v': 936 ctx->vflag = 1; 937 break; 938 default: 939 free(ctx); 940 return command_usage(&aio_read_cmd); 941 } 942 } 943 944 if (optind > argc - 2) { 945 free(ctx); 946 return command_usage(&aio_read_cmd); 947 } 948 949 ctx->offset = cvtnum(argv[optind]); 950 if (ctx->offset < 0) { 951 printf("non-numeric length argument -- %s\n", argv[optind]); 952 free(ctx); 953 return 0; 954 } 955 optind++; 956 957 if (ctx->offset & 0x1ff) { 958 printf("offset %lld is not sector aligned\n", 959 (long long)ctx->offset); 960 free(ctx); 961 return 0; 962 } 963 964 nr_iov = argc - optind; 965 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); 966 967 gettimeofday(&ctx->t1, NULL); 968 acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 969 ctx->qiov.size >> 9, aio_read_done, ctx); 970 if (!acb) { 971 free(ctx->buf); 972 free(ctx); 973 return -EIO; 974 } 975 976 return 0; 977 } 978 979 static const cmdinfo_t aio_read_cmd = { 980 .name = "aio_read", 981 .cfunc = aio_read_f, 982 .argmin = 2, 983 .argmax = -1, 984 .args = "[-Cqv] [-P pattern ] off len [len..]", 985 .oneline = "asynchronously reads a number of bytes", 986 .help = aio_read_help, 987 }; 988 989 static const cmdinfo_t aio_write_cmd; 990 991 static void 992 aio_write_help(void) 993 { 994 printf( 995 "\n" 996 " asynchronously writes a range of bytes from the given offset source \n" 997 " from multiple buffers\n" 998 "\n" 999 " Example:\n" 1000 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1001 "\n" 1002 " Writes into a segment of the currently open file, using a buffer\n" 1003 " filled with a set pattern (0xcdcdcdcd).\n" 1004 " The write is performed asynchronously and should the aio_flush command \n" 1005 " should be used to ensure all outstanding aio requests have been completed\n" 1006 " -P, -- use different pattern to fill file\n" 1007 " -C, -- report statistics in a machine parsable format\n" 1008 " -q, -- quite mode, do not show I/O statistics\n" 1009 "\n"); 1010 } 1011 1012 1013 static int 1014 aio_write_f(int argc, char **argv) 1015 { 1016 int nr_iov, c; 1017 int pattern = 0xcd; 1018 struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 1019 BlockDriverAIOCB *acb; 1020 1021 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 1022 switch (c) { 1023 case 'C': 1024 ctx->Cflag = 1; 1025 break; 1026 case 'q': 1027 ctx->qflag = 1; 1028 break; 1029 case 'P': 1030 pattern = parse_pattern(optarg); 1031 if (pattern < 0) 1032 return 0; 1033 break; 1034 default: 1035 free(ctx); 1036 return command_usage(&aio_write_cmd); 1037 } 1038 } 1039 1040 if (optind > argc - 2) { 1041 free(ctx); 1042 return command_usage(&aio_write_cmd); 1043 } 1044 1045 ctx->offset = cvtnum(argv[optind]); 1046 if (ctx->offset < 0) { 1047 printf("non-numeric length argument -- %s\n", argv[optind]); 1048 free(ctx); 1049 return 0; 1050 } 1051 optind++; 1052 1053 if (ctx->offset & 0x1ff) { 1054 printf("offset %lld is not sector aligned\n", 1055 (long long)ctx->offset); 1056 free(ctx); 1057 return 0; 1058 } 1059 1060 nr_iov = argc - optind; 1061 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); 1062 1063 gettimeofday(&ctx->t1, NULL); 1064 acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 1065 ctx->qiov.size >> 9, aio_write_done, ctx); 1066 if (!acb) { 1067 free(ctx->buf); 1068 free(ctx); 1069 return -EIO; 1070 } 1071 1072 return 0; 1073 } 1074 1075 static const cmdinfo_t aio_write_cmd = { 1076 .name = "aio_write", 1077 .cfunc = aio_write_f, 1078 .argmin = 2, 1079 .argmax = -1, 1080 .args = "[-Cq] [-P pattern ] off len [len..]", 1081 .oneline = "asynchronously writes a number of bytes", 1082 .help = aio_write_help, 1083 }; 1084 1085 static int 1086 aio_flush_f(int argc, char **argv) 1087 { 1088 qemu_aio_flush(); 1089 return 0; 1090 } 1091 1092 static const cmdinfo_t aio_flush_cmd = { 1093 .name = "aio_flush", 1094 .cfunc = aio_flush_f, 1095 .oneline = "completes all outstanding aio requets" 1096 }; 1097 1098 static int 1099 flush_f(int argc, char **argv) 1100 { 1101 bdrv_flush(bs); 1102 return 0; 1103 } 1104 1105 static const cmdinfo_t flush_cmd = { 1106 .name = "flush", 1107 .altname = "f", 1108 .cfunc = flush_f, 1109 .oneline = "flush all in-core file state to disk", 1110 }; 1111 1112 static int 1113 truncate_f(int argc, char **argv) 1114 { 1115 int64_t offset; 1116 int ret; 1117 1118 offset = cvtnum(argv[1]); 1119 if (offset < 0) { 1120 printf("non-numeric truncate argument -- %s\n", argv[1]); 1121 return 0; 1122 } 1123 1124 ret = bdrv_truncate(bs, offset); 1125 if (ret < 0) { 1126 printf("truncate: %s", strerror(ret)); 1127 return 0; 1128 } 1129 1130 return 0; 1131 } 1132 1133 static const cmdinfo_t truncate_cmd = { 1134 .name = "truncate", 1135 .altname = "t", 1136 .cfunc = truncate_f, 1137 .argmin = 1, 1138 .argmax = 1, 1139 .args = "off", 1140 .oneline = "truncates the current file at the given offset", 1141 }; 1142 1143 static int 1144 length_f(int argc, char **argv) 1145 { 1146 int64_t size; 1147 char s1[64]; 1148 1149 size = bdrv_getlength(bs); 1150 if (size < 0) { 1151 printf("getlength: %s", strerror(size)); 1152 return 0; 1153 } 1154 1155 cvtstr(size, s1, sizeof(s1)); 1156 printf("%s\n", s1); 1157 return 0; 1158 } 1159 1160 1161 static const cmdinfo_t length_cmd = { 1162 .name = "length", 1163 .altname = "l", 1164 .cfunc = length_f, 1165 .oneline = "gets the length of the current file", 1166 }; 1167 1168 1169 static int 1170 info_f(int argc, char **argv) 1171 { 1172 BlockDriverInfo bdi; 1173 char s1[64], s2[64]; 1174 int ret; 1175 1176 if (bs->drv && bs->drv->format_name) 1177 printf("format name: %s\n", bs->drv->format_name); 1178 if (bs->drv && bs->drv->protocol_name) 1179 printf("format name: %s\n", bs->drv->protocol_name); 1180 1181 ret = bdrv_get_info(bs, &bdi); 1182 if (ret) 1183 return 0; 1184 1185 cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1186 cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1187 1188 printf("cluster size: %s\n", s1); 1189 printf("vm state offset: %s\n", s2); 1190 1191 return 0; 1192 } 1193 1194 1195 1196 static const cmdinfo_t info_cmd = { 1197 .name = "info", 1198 .altname = "i", 1199 .cfunc = info_f, 1200 .oneline = "prints information about the current file", 1201 }; 1202 1203 static int 1204 alloc_f(int argc, char **argv) 1205 { 1206 int64_t offset; 1207 int nb_sectors, remaining; 1208 char s1[64]; 1209 int num, sum_alloc; 1210 int ret; 1211 1212 offset = cvtnum(argv[1]); 1213 if (offset & 0x1ff) { 1214 printf("offset %lld is not sector aligned\n", 1215 (long long)offset); 1216 return 0; 1217 } 1218 1219 if (argc == 3) 1220 nb_sectors = cvtnum(argv[2]); 1221 else 1222 nb_sectors = 1; 1223 1224 remaining = nb_sectors; 1225 sum_alloc = 0; 1226 while (remaining) { 1227 ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); 1228 remaining -= num; 1229 if (ret) { 1230 sum_alloc += num; 1231 } 1232 } 1233 1234 cvtstr(offset, s1, sizeof(s1)); 1235 1236 if (nb_sectors == 1) 1237 printf("sector allocated at offset %s\n", s1); 1238 else 1239 printf("%d/%d sectors allocated at offset %s\n", 1240 sum_alloc, nb_sectors, s1); 1241 return 0; 1242 } 1243 1244 static const cmdinfo_t alloc_cmd = { 1245 .name = "alloc", 1246 .altname = "a", 1247 .argmin = 1, 1248 .argmax = 2, 1249 .cfunc = alloc_f, 1250 .args = "off [sectors]", 1251 .oneline = "checks if a sector is present in the file", 1252 }; 1253 1254 static int 1255 close_f(int argc, char **argv) 1256 { 1257 bdrv_close(bs); 1258 bs = NULL; 1259 return 0; 1260 } 1261 1262 static const cmdinfo_t close_cmd = { 1263 .name = "close", 1264 .altname = "c", 1265 .cfunc = close_f, 1266 .oneline = "close the current open file", 1267 }; 1268 1269 static int openfile(char *name, int flags, int growable) 1270 { 1271 if (bs) { 1272 fprintf(stderr, "file open already, try 'help close'\n"); 1273 return 1; 1274 } 1275 1276 bs = bdrv_new("hda"); 1277 if (!bs) 1278 return 1; 1279 1280 if (growable) { 1281 flags |= BDRV_O_FILE; 1282 } 1283 1284 if (bdrv_open(bs, name, flags) == -1) { 1285 fprintf(stderr, "%s: can't open device %s\n", progname, name); 1286 bs = NULL; 1287 return 1; 1288 } 1289 1290 if (growable) { 1291 bs->growable = 1; 1292 } 1293 return 0; 1294 } 1295 1296 static void 1297 open_help(void) 1298 { 1299 printf( 1300 "\n" 1301 " opens a new file in the requested mode\n" 1302 "\n" 1303 " Example:\n" 1304 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 1305 "\n" 1306 " Opens a file for subsequent use by all of the other qemu-io commands.\n" 1307 " -C, -- create new file if it doesn't exist\n" 1308 " -r, -- open file read-only\n" 1309 " -s, -- use snapshot file\n" 1310 " -n, -- disable host cache\n" 1311 " -g, -- allow file to grow (only applies to protocols)" 1312 "\n"); 1313 } 1314 1315 static const cmdinfo_t open_cmd; 1316 1317 static int 1318 open_f(int argc, char **argv) 1319 { 1320 int flags = 0; 1321 int readonly = 0; 1322 int growable = 0; 1323 int c; 1324 1325 while ((c = getopt(argc, argv, "snCrg")) != EOF) { 1326 switch (c) { 1327 case 's': 1328 flags |= BDRV_O_SNAPSHOT; 1329 break; 1330 case 'n': 1331 flags |= BDRV_O_NOCACHE; 1332 break; 1333 case 'C': 1334 flags |= BDRV_O_CREAT; 1335 break; 1336 case 'r': 1337 readonly = 1; 1338 break; 1339 case 'g': 1340 growable = 1; 1341 break; 1342 default: 1343 return command_usage(&open_cmd); 1344 } 1345 } 1346 1347 if (readonly) 1348 flags |= BDRV_O_RDONLY; 1349 else 1350 flags |= BDRV_O_RDWR; 1351 1352 if (optind != argc - 1) 1353 return command_usage(&open_cmd); 1354 1355 return openfile(argv[optind], flags, growable); 1356 } 1357 1358 static const cmdinfo_t open_cmd = { 1359 .name = "open", 1360 .altname = "o", 1361 .cfunc = open_f, 1362 .argmin = 1, 1363 .argmax = -1, 1364 .flags = CMD_NOFILE_OK, 1365 .args = "[-Crsn] [path]", 1366 .oneline = "open the file specified by path", 1367 .help = open_help, 1368 }; 1369 1370 static int 1371 init_args_command( 1372 int index) 1373 { 1374 /* only one device allowed so far */ 1375 if (index >= 1) 1376 return 0; 1377 return ++index; 1378 } 1379 1380 static int 1381 init_check_command( 1382 const cmdinfo_t *ct) 1383 { 1384 if (ct->flags & CMD_FLAG_GLOBAL) 1385 return 1; 1386 if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1387 fprintf(stderr, "no file open, try 'help open'\n"); 1388 return 0; 1389 } 1390 return 1; 1391 } 1392 1393 static void usage(const char *name) 1394 { 1395 printf( 1396 "Usage: %s [-h] [-V] [-Crsnm] [-c cmd] ... [file]\n" 1397 "QEMU Disk exerciser\n" 1398 "\n" 1399 " -C, --create create new file if it doesn't exist\n" 1400 " -c, --cmd command to execute\n" 1401 " -r, --read-only export read-only\n" 1402 " -s, --snapshot use snapshot file\n" 1403 " -n, --nocache disable host cache\n" 1404 " -g, --growable allow file to grow (only applies to protocols)\n" 1405 " -m, --misalign misalign allocations for O_DIRECT\n" 1406 " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 1407 " -h, --help display this help and exit\n" 1408 " -V, --version output version information and exit\n" 1409 "\n", 1410 name); 1411 } 1412 1413 1414 int main(int argc, char **argv) 1415 { 1416 int readonly = 0; 1417 int growable = 0; 1418 const char *sopt = "hVc:Crsnmgk"; 1419 struct option lopt[] = { 1420 { "help", 0, NULL, 'h' }, 1421 { "version", 0, NULL, 'V' }, 1422 { "offset", 1, NULL, 'o' }, 1423 { "cmd", 1, NULL, 'c' }, 1424 { "create", 0, NULL, 'C' }, 1425 { "read-only", 0, NULL, 'r' }, 1426 { "snapshot", 0, NULL, 's' }, 1427 { "nocache", 0, NULL, 'n' }, 1428 { "misalign", 0, NULL, 'm' }, 1429 { "growable", 0, NULL, 'g' }, 1430 { "native-aio", 0, NULL, 'k' }, 1431 { NULL, 0, NULL, 0 } 1432 }; 1433 int c; 1434 int opt_index = 0; 1435 int flags = 0; 1436 1437 progname = basename(argv[0]); 1438 1439 while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1440 switch (c) { 1441 case 's': 1442 flags |= BDRV_O_SNAPSHOT; 1443 break; 1444 case 'n': 1445 flags |= BDRV_O_NOCACHE; 1446 break; 1447 case 'c': 1448 add_user_command(optarg); 1449 break; 1450 case 'C': 1451 flags |= BDRV_O_CREAT; 1452 break; 1453 case 'r': 1454 readonly = 1; 1455 break; 1456 case 'm': 1457 misalign = 1; 1458 break; 1459 case 'g': 1460 growable = 1; 1461 break; 1462 case 'k': 1463 flags |= BDRV_O_NATIVE_AIO; 1464 break; 1465 case 'V': 1466 printf("%s version %s\n", progname, VERSION); 1467 exit(0); 1468 case 'h': 1469 usage(progname); 1470 exit(0); 1471 default: 1472 usage(progname); 1473 exit(1); 1474 } 1475 } 1476 1477 if ((argc - optind) > 1) { 1478 usage(progname); 1479 exit(1); 1480 } 1481 1482 bdrv_init(); 1483 1484 /* initialize commands */ 1485 quit_init(); 1486 help_init(); 1487 add_command(&open_cmd); 1488 add_command(&close_cmd); 1489 add_command(&read_cmd); 1490 add_command(&readv_cmd); 1491 add_command(&write_cmd); 1492 add_command(&writev_cmd); 1493 add_command(&aio_read_cmd); 1494 add_command(&aio_write_cmd); 1495 add_command(&aio_flush_cmd); 1496 add_command(&flush_cmd); 1497 add_command(&truncate_cmd); 1498 add_command(&length_cmd); 1499 add_command(&info_cmd); 1500 add_command(&alloc_cmd); 1501 1502 add_args_command(init_args_command); 1503 add_check_command(init_check_command); 1504 1505 /* open the device */ 1506 if (readonly) 1507 flags |= BDRV_O_RDONLY; 1508 else 1509 flags |= BDRV_O_RDWR; 1510 1511 if ((argc - optind) == 1) 1512 openfile(argv[optind], flags, growable); 1513 command_loop(); 1514 1515 /* 1516 * Make sure all outstanding requests get flushed the program exits. 1517 */ 1518 qemu_aio_flush(); 1519 1520 if (bs) 1521 bdrv_close(bs); 1522 return 0; 1523 } 1524