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