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 BlockDriverAIOCB *acb; 248 int async_ret = NOT_DONE; 249 250 acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, 251 aio_rw_done, &async_ret); 252 if (!acb) { 253 return -EIO; 254 } 255 while (async_ret == NOT_DONE) { 256 qemu_aio_wait(); 257 } 258 259 *total = qiov->size; 260 return async_ret < 0 ? async_ret : 1; 261 } 262 263 static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) 264 { 265 BlockDriverAIOCB *acb; 266 int async_ret = NOT_DONE; 267 268 acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, 269 aio_rw_done, &async_ret); 270 if (!acb) { 271 return -EIO; 272 } 273 274 while (async_ret == NOT_DONE) { 275 qemu_aio_wait(); 276 } 277 278 *total = qiov->size; 279 return async_ret < 0 ? async_ret : 1; 280 } 281 282 struct multiwrite_async_ret { 283 int num_done; 284 int error; 285 }; 286 287 static void multiwrite_cb(void *opaque, int ret) 288 { 289 struct multiwrite_async_ret *async_ret = opaque; 290 291 async_ret->num_done++; 292 if (ret < 0) { 293 async_ret->error = ret; 294 } 295 } 296 297 static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total) 298 { 299 int i, ret; 300 struct multiwrite_async_ret async_ret = { 301 .num_done = 0, 302 .error = 0, 303 }; 304 305 *total = 0; 306 for (i = 0; i < num_reqs; i++) { 307 reqs[i].cb = multiwrite_cb; 308 reqs[i].opaque = &async_ret; 309 *total += reqs[i].qiov->size; 310 } 311 312 ret = bdrv_aio_multiwrite(bs, reqs, num_reqs); 313 if (ret < 0) { 314 return ret; 315 } 316 317 while (async_ret.num_done < num_reqs) { 318 qemu_aio_wait(); 319 } 320 321 return async_ret.error < 0 ? async_ret.error : 1; 322 } 323 324 static void read_help(void) 325 { 326 printf( 327 "\n" 328 " reads a range of bytes from the given offset\n" 329 "\n" 330 " Example:\n" 331 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 332 "\n" 333 " Reads a segment of the currently open file, optionally dumping it to the\n" 334 " standard output stream (with -v option) for subsequent inspection.\n" 335 " -b, -- read from the VM state rather than the virtual disk\n" 336 " -C, -- report statistics in a machine parsable format\n" 337 " -l, -- length for pattern verification (only with -P)\n" 338 " -p, -- use bdrv_pread to read the file\n" 339 " -P, -- use a pattern to verify read data\n" 340 " -q, -- quiet mode, do not show I/O statistics\n" 341 " -s, -- start offset for pattern verification (only with -P)\n" 342 " -v, -- dump buffer to standard output\n" 343 "\n"); 344 } 345 346 static int read_f(int argc, char **argv); 347 348 static const cmdinfo_t read_cmd = { 349 .name = "read", 350 .altname = "r", 351 .cfunc = read_f, 352 .argmin = 2, 353 .argmax = -1, 354 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", 355 .oneline = "reads a number of bytes at a specified offset", 356 .help = read_help, 357 }; 358 359 static int read_f(int argc, char **argv) 360 { 361 struct timeval t1, t2; 362 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 363 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; 364 int c, cnt; 365 char *buf; 366 int64_t offset; 367 int count; 368 /* Some compilers get confused and warn if this is not initialized. */ 369 int total = 0; 370 int pattern = 0, pattern_offset = 0, pattern_count = 0; 371 372 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { 373 switch (c) { 374 case 'b': 375 bflag = 1; 376 break; 377 case 'C': 378 Cflag = 1; 379 break; 380 case 'l': 381 lflag = 1; 382 pattern_count = cvtnum(optarg); 383 if (pattern_count < 0) { 384 printf("non-numeric length argument -- %s\n", optarg); 385 return 0; 386 } 387 break; 388 case 'p': 389 pflag = 1; 390 break; 391 case 'P': 392 Pflag = 1; 393 pattern = parse_pattern(optarg); 394 if (pattern < 0) { 395 return 0; 396 } 397 break; 398 case 'q': 399 qflag = 1; 400 break; 401 case 's': 402 sflag = 1; 403 pattern_offset = cvtnum(optarg); 404 if (pattern_offset < 0) { 405 printf("non-numeric length argument -- %s\n", optarg); 406 return 0; 407 } 408 break; 409 case 'v': 410 vflag = 1; 411 break; 412 default: 413 return command_usage(&read_cmd); 414 } 415 } 416 417 if (optind != argc - 2) { 418 return command_usage(&read_cmd); 419 } 420 421 if (bflag && pflag) { 422 printf("-b and -p cannot be specified at the same time\n"); 423 return 0; 424 } 425 426 offset = cvtnum(argv[optind]); 427 if (offset < 0) { 428 printf("non-numeric length argument -- %s\n", argv[optind]); 429 return 0; 430 } 431 432 optind++; 433 count = cvtnum(argv[optind]); 434 if (count < 0) { 435 printf("non-numeric length argument -- %s\n", argv[optind]); 436 return 0; 437 } 438 439 if (!Pflag && (lflag || sflag)) { 440 return command_usage(&read_cmd); 441 } 442 443 if (!lflag) { 444 pattern_count = count - pattern_offset; 445 } 446 447 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 448 printf("pattern verfication range exceeds end of read data\n"); 449 return 0; 450 } 451 452 if (!pflag) { 453 if (offset & 0x1ff) { 454 printf("offset %" PRId64 " is not sector aligned\n", 455 offset); 456 return 0; 457 } 458 if (count & 0x1ff) { 459 printf("count %d is not sector aligned\n", 460 count); 461 return 0; 462 } 463 } 464 465 buf = qemu_io_alloc(count, 0xab); 466 467 gettimeofday(&t1, NULL); 468 if (pflag) { 469 cnt = do_pread(buf, offset, count, &total); 470 } else if (bflag) { 471 cnt = do_load_vmstate(buf, offset, count, &total); 472 } else { 473 cnt = do_read(buf, offset, count, &total); 474 } 475 gettimeofday(&t2, NULL); 476 477 if (cnt < 0) { 478 printf("read failed: %s\n", strerror(-cnt)); 479 goto out; 480 } 481 482 if (Pflag) { 483 void *cmp_buf = malloc(pattern_count); 484 memset(cmp_buf, pattern, pattern_count); 485 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 486 printf("Pattern verification failed at offset %" 487 PRId64 ", %d bytes\n", 488 offset + pattern_offset, pattern_count); 489 } 490 free(cmp_buf); 491 } 492 493 if (qflag) { 494 goto out; 495 } 496 497 if (vflag) { 498 dump_buffer(buf, offset, count); 499 } 500 501 /* Finally, report back -- -C gives a parsable format */ 502 t2 = tsub(t2, t1); 503 print_report("read", &t2, offset, count, total, cnt, Cflag); 504 505 out: 506 qemu_io_free(buf); 507 508 return 0; 509 } 510 511 static void readv_help(void) 512 { 513 printf( 514 "\n" 515 " reads a range of bytes from the given offset into multiple buffers\n" 516 "\n" 517 " Example:\n" 518 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 519 "\n" 520 " Reads a segment of the currently open file, optionally dumping it to the\n" 521 " standard output stream (with -v option) for subsequent inspection.\n" 522 " Uses multiple iovec buffers if more than one byte range is specified.\n" 523 " -C, -- report statistics in a machine parsable format\n" 524 " -P, -- use a pattern to verify read data\n" 525 " -v, -- dump buffer to standard output\n" 526 " -q, -- quiet mode, do not show I/O statistics\n" 527 "\n"); 528 } 529 530 static int readv_f(int argc, char **argv); 531 532 static const cmdinfo_t readv_cmd = { 533 .name = "readv", 534 .cfunc = readv_f, 535 .argmin = 2, 536 .argmax = -1, 537 .args = "[-Cqv] [-P pattern ] off len [len..]", 538 .oneline = "reads a number of bytes at a specified offset", 539 .help = readv_help, 540 }; 541 542 static int readv_f(int argc, char **argv) 543 { 544 struct timeval t1, t2; 545 int Cflag = 0, qflag = 0, vflag = 0; 546 int c, cnt; 547 char *buf; 548 int64_t offset; 549 /* Some compilers get confused and warn if this is not initialized. */ 550 int total = 0; 551 int nr_iov; 552 QEMUIOVector qiov; 553 int pattern = 0; 554 int Pflag = 0; 555 556 while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 557 switch (c) { 558 case 'C': 559 Cflag = 1; 560 break; 561 case 'P': 562 Pflag = 1; 563 pattern = parse_pattern(optarg); 564 if (pattern < 0) { 565 return 0; 566 } 567 break; 568 case 'q': 569 qflag = 1; 570 break; 571 case 'v': 572 vflag = 1; 573 break; 574 default: 575 return command_usage(&readv_cmd); 576 } 577 } 578 579 if (optind > argc - 2) { 580 return command_usage(&readv_cmd); 581 } 582 583 584 offset = cvtnum(argv[optind]); 585 if (offset < 0) { 586 printf("non-numeric length argument -- %s\n", argv[optind]); 587 return 0; 588 } 589 optind++; 590 591 if (offset & 0x1ff) { 592 printf("offset %" PRId64 " is not sector aligned\n", 593 offset); 594 return 0; 595 } 596 597 nr_iov = argc - optind; 598 buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); 599 600 gettimeofday(&t1, NULL); 601 cnt = do_aio_readv(&qiov, offset, &total); 602 gettimeofday(&t2, NULL); 603 604 if (cnt < 0) { 605 printf("readv failed: %s\n", strerror(-cnt)); 606 goto out; 607 } 608 609 if (Pflag) { 610 void *cmp_buf = malloc(qiov.size); 611 memset(cmp_buf, pattern, qiov.size); 612 if (memcmp(buf, cmp_buf, qiov.size)) { 613 printf("Pattern verification failed at offset %" 614 PRId64 ", %zd bytes\n", offset, qiov.size); 615 } 616 free(cmp_buf); 617 } 618 619 if (qflag) { 620 goto out; 621 } 622 623 if (vflag) { 624 dump_buffer(buf, offset, qiov.size); 625 } 626 627 /* Finally, report back -- -C gives a parsable format */ 628 t2 = tsub(t2, t1); 629 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 630 631 out: 632 qemu_io_free(buf); 633 return 0; 634 } 635 636 static void write_help(void) 637 { 638 printf( 639 "\n" 640 " writes a range of bytes from the given offset\n" 641 "\n" 642 " Example:\n" 643 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 644 "\n" 645 " Writes into a segment of the currently open file, using a buffer\n" 646 " filled with a set pattern (0xcdcdcdcd).\n" 647 " -b, -- write to the VM state rather than the virtual disk\n" 648 " -p, -- use bdrv_pwrite to write the file\n" 649 " -P, -- use different pattern to fill file\n" 650 " -C, -- report statistics in a machine parsable format\n" 651 " -q, -- quiet mode, do not show I/O statistics\n" 652 "\n"); 653 } 654 655 static int write_f(int argc, char **argv); 656 657 static const cmdinfo_t write_cmd = { 658 .name = "write", 659 .altname = "w", 660 .cfunc = write_f, 661 .argmin = 2, 662 .argmax = -1, 663 .args = "[-abCpq] [-P pattern ] off len", 664 .oneline = "writes a number of bytes at a specified offset", 665 .help = write_help, 666 }; 667 668 static int write_f(int argc, char **argv) 669 { 670 struct timeval t1, t2; 671 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0; 672 int c, cnt; 673 char *buf; 674 int64_t offset; 675 int count; 676 /* Some compilers get confused and warn if this is not initialized. */ 677 int total = 0; 678 int pattern = 0xcd; 679 680 while ((c = getopt(argc, argv, "bCpP:q")) != EOF) { 681 switch (c) { 682 case 'b': 683 bflag = 1; 684 break; 685 case 'C': 686 Cflag = 1; 687 break; 688 case 'p': 689 pflag = 1; 690 break; 691 case 'P': 692 pattern = parse_pattern(optarg); 693 if (pattern < 0) { 694 return 0; 695 } 696 break; 697 case 'q': 698 qflag = 1; 699 break; 700 default: 701 return command_usage(&write_cmd); 702 } 703 } 704 705 if (optind != argc - 2) { 706 return command_usage(&write_cmd); 707 } 708 709 if (bflag && pflag) { 710 printf("-b and -p cannot be specified at the same time\n"); 711 return 0; 712 } 713 714 offset = cvtnum(argv[optind]); 715 if (offset < 0) { 716 printf("non-numeric length argument -- %s\n", argv[optind]); 717 return 0; 718 } 719 720 optind++; 721 count = cvtnum(argv[optind]); 722 if (count < 0) { 723 printf("non-numeric length argument -- %s\n", argv[optind]); 724 return 0; 725 } 726 727 if (!pflag) { 728 if (offset & 0x1ff) { 729 printf("offset %" PRId64 " is not sector aligned\n", 730 offset); 731 return 0; 732 } 733 734 if (count & 0x1ff) { 735 printf("count %d is not sector aligned\n", 736 count); 737 return 0; 738 } 739 } 740 741 buf = qemu_io_alloc(count, pattern); 742 743 gettimeofday(&t1, NULL); 744 if (pflag) { 745 cnt = do_pwrite(buf, offset, count, &total); 746 } else if (bflag) { 747 cnt = do_save_vmstate(buf, offset, count, &total); 748 } else { 749 cnt = do_write(buf, offset, count, &total); 750 } 751 gettimeofday(&t2, NULL); 752 753 if (cnt < 0) { 754 printf("write failed: %s\n", strerror(-cnt)); 755 goto out; 756 } 757 758 if (qflag) { 759 goto out; 760 } 761 762 /* Finally, report back -- -C gives a parsable format */ 763 t2 = tsub(t2, t1); 764 print_report("wrote", &t2, offset, count, total, cnt, Cflag); 765 766 out: 767 qemu_io_free(buf); 768 769 return 0; 770 } 771 772 static void 773 writev_help(void) 774 { 775 printf( 776 "\n" 777 " writes a range of bytes from the given offset source from multiple buffers\n" 778 "\n" 779 " Example:\n" 780 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 781 "\n" 782 " Writes into a segment of the currently open file, using a buffer\n" 783 " filled with a set pattern (0xcdcdcdcd).\n" 784 " -P, -- use different pattern to fill file\n" 785 " -C, -- report statistics in a machine parsable format\n" 786 " -q, -- quiet mode, do not show I/O statistics\n" 787 "\n"); 788 } 789 790 static int writev_f(int argc, char **argv); 791 792 static const cmdinfo_t writev_cmd = { 793 .name = "writev", 794 .cfunc = writev_f, 795 .argmin = 2, 796 .argmax = -1, 797 .args = "[-Cq] [-P pattern ] off len [len..]", 798 .oneline = "writes a number of bytes at a specified offset", 799 .help = writev_help, 800 }; 801 802 static int writev_f(int argc, char **argv) 803 { 804 struct timeval t1, t2; 805 int Cflag = 0, qflag = 0; 806 int c, cnt; 807 char *buf; 808 int64_t offset; 809 /* Some compilers get confused and warn if this is not initialized. */ 810 int total = 0; 811 int nr_iov; 812 int pattern = 0xcd; 813 QEMUIOVector qiov; 814 815 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 816 switch (c) { 817 case 'C': 818 Cflag = 1; 819 break; 820 case 'q': 821 qflag = 1; 822 break; 823 case 'P': 824 pattern = parse_pattern(optarg); 825 if (pattern < 0) { 826 return 0; 827 } 828 break; 829 default: 830 return command_usage(&writev_cmd); 831 } 832 } 833 834 if (optind > argc - 2) { 835 return command_usage(&writev_cmd); 836 } 837 838 offset = cvtnum(argv[optind]); 839 if (offset < 0) { 840 printf("non-numeric length argument -- %s\n", argv[optind]); 841 return 0; 842 } 843 optind++; 844 845 if (offset & 0x1ff) { 846 printf("offset %" PRId64 " is not sector aligned\n", 847 offset); 848 return 0; 849 } 850 851 nr_iov = argc - optind; 852 buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); 853 854 gettimeofday(&t1, NULL); 855 cnt = do_aio_writev(&qiov, offset, &total); 856 gettimeofday(&t2, NULL); 857 858 if (cnt < 0) { 859 printf("writev failed: %s\n", strerror(-cnt)); 860 goto out; 861 } 862 863 if (qflag) { 864 goto out; 865 } 866 867 /* Finally, report back -- -C gives a parsable format */ 868 t2 = tsub(t2, t1); 869 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 870 out: 871 qemu_io_free(buf); 872 return 0; 873 } 874 875 static void multiwrite_help(void) 876 { 877 printf( 878 "\n" 879 " writes a range of bytes from the given offset source from multiple buffers,\n" 880 " in a batch of requests that may be merged by qemu\n" 881 "\n" 882 " Example:\n" 883 " 'multiwrite 512 1k 1k ; 4k 1k' \n" 884 " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n" 885 "\n" 886 " Writes into a segment of the currently open file, using a buffer\n" 887 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n" 888 " by one for each request contained in the multiwrite command.\n" 889 " -P, -- use different pattern to fill file\n" 890 " -C, -- report statistics in a machine parsable format\n" 891 " -q, -- quiet mode, do not show I/O statistics\n" 892 "\n"); 893 } 894 895 static int multiwrite_f(int argc, char **argv); 896 897 static const cmdinfo_t multiwrite_cmd = { 898 .name = "multiwrite", 899 .cfunc = multiwrite_f, 900 .argmin = 2, 901 .argmax = -1, 902 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]", 903 .oneline = "issues multiple write requests at once", 904 .help = multiwrite_help, 905 }; 906 907 static int multiwrite_f(int argc, char **argv) 908 { 909 struct timeval t1, t2; 910 int Cflag = 0, qflag = 0; 911 int c, cnt; 912 char **buf; 913 int64_t offset, first_offset = 0; 914 /* Some compilers get confused and warn if this is not initialized. */ 915 int total = 0; 916 int nr_iov; 917 int nr_reqs; 918 int pattern = 0xcd; 919 QEMUIOVector *qiovs; 920 int i; 921 BlockRequest *reqs; 922 923 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 924 switch (c) { 925 case 'C': 926 Cflag = 1; 927 break; 928 case 'q': 929 qflag = 1; 930 break; 931 case 'P': 932 pattern = parse_pattern(optarg); 933 if (pattern < 0) { 934 return 0; 935 } 936 break; 937 default: 938 return command_usage(&writev_cmd); 939 } 940 } 941 942 if (optind > argc - 2) { 943 return command_usage(&writev_cmd); 944 } 945 946 nr_reqs = 1; 947 for (i = optind; i < argc; i++) { 948 if (!strcmp(argv[i], ";")) { 949 nr_reqs++; 950 } 951 } 952 953 reqs = g_malloc(nr_reqs * sizeof(*reqs)); 954 buf = g_malloc(nr_reqs * sizeof(*buf)); 955 qiovs = g_malloc(nr_reqs * sizeof(*qiovs)); 956 957 for (i = 0; i < nr_reqs; i++) { 958 int j; 959 960 /* Read the offset of the request */ 961 offset = cvtnum(argv[optind]); 962 if (offset < 0) { 963 printf("non-numeric offset argument -- %s\n", argv[optind]); 964 return 0; 965 } 966 optind++; 967 968 if (offset & 0x1ff) { 969 printf("offset %lld is not sector aligned\n", 970 (long long)offset); 971 return 0; 972 } 973 974 if (i == 0) { 975 first_offset = offset; 976 } 977 978 /* Read lengths for qiov entries */ 979 for (j = optind; j < argc; j++) { 980 if (!strcmp(argv[j], ";")) { 981 break; 982 } 983 } 984 985 nr_iov = j - optind; 986 987 /* Build request */ 988 reqs[i].qiov = &qiovs[i]; 989 buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern); 990 reqs[i].sector = offset >> 9; 991 reqs[i].nb_sectors = reqs[i].qiov->size >> 9; 992 993 optind = j + 1; 994 995 offset += reqs[i].qiov->size; 996 pattern++; 997 } 998 999 gettimeofday(&t1, NULL); 1000 cnt = do_aio_multiwrite(reqs, nr_reqs, &total); 1001 gettimeofday(&t2, NULL); 1002 1003 if (cnt < 0) { 1004 printf("aio_multiwrite failed: %s\n", strerror(-cnt)); 1005 goto out; 1006 } 1007 1008 if (qflag) { 1009 goto out; 1010 } 1011 1012 /* Finally, report back -- -C gives a parsable format */ 1013 t2 = tsub(t2, t1); 1014 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); 1015 out: 1016 for (i = 0; i < nr_reqs; i++) { 1017 qemu_io_free(buf[i]); 1018 qemu_iovec_destroy(&qiovs[i]); 1019 } 1020 g_free(buf); 1021 g_free(reqs); 1022 g_free(qiovs); 1023 return 0; 1024 } 1025 1026 struct aio_ctx { 1027 QEMUIOVector qiov; 1028 int64_t offset; 1029 char *buf; 1030 int qflag; 1031 int vflag; 1032 int Cflag; 1033 int Pflag; 1034 int pattern; 1035 struct timeval t1; 1036 }; 1037 1038 static void aio_write_done(void *opaque, int ret) 1039 { 1040 struct aio_ctx *ctx = opaque; 1041 struct timeval t2; 1042 1043 gettimeofday(&t2, NULL); 1044 1045 1046 if (ret < 0) { 1047 printf("aio_write failed: %s\n", strerror(-ret)); 1048 goto out; 1049 } 1050 1051 if (ctx->qflag) { 1052 goto out; 1053 } 1054 1055 /* Finally, report back -- -C gives a parsable format */ 1056 t2 = tsub(t2, ctx->t1); 1057 print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1058 ctx->qiov.size, 1, ctx->Cflag); 1059 out: 1060 qemu_io_free(ctx->buf); 1061 free(ctx); 1062 } 1063 1064 static void aio_read_done(void *opaque, int ret) 1065 { 1066 struct aio_ctx *ctx = opaque; 1067 struct timeval t2; 1068 1069 gettimeofday(&t2, NULL); 1070 1071 if (ret < 0) { 1072 printf("readv failed: %s\n", strerror(-ret)); 1073 goto out; 1074 } 1075 1076 if (ctx->Pflag) { 1077 void *cmp_buf = malloc(ctx->qiov.size); 1078 1079 memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1080 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 1081 printf("Pattern verification failed at offset %" 1082 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size); 1083 } 1084 free(cmp_buf); 1085 } 1086 1087 if (ctx->qflag) { 1088 goto out; 1089 } 1090 1091 if (ctx->vflag) { 1092 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1093 } 1094 1095 /* Finally, report back -- -C gives a parsable format */ 1096 t2 = tsub(t2, ctx->t1); 1097 print_report("read", &t2, ctx->offset, ctx->qiov.size, 1098 ctx->qiov.size, 1, ctx->Cflag); 1099 out: 1100 qemu_io_free(ctx->buf); 1101 free(ctx); 1102 } 1103 1104 static void aio_read_help(void) 1105 { 1106 printf( 1107 "\n" 1108 " asynchronously reads a range of bytes from the given offset\n" 1109 "\n" 1110 " Example:\n" 1111 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 1112 "\n" 1113 " Reads a segment of the currently open file, optionally dumping it to the\n" 1114 " standard output stream (with -v option) for subsequent inspection.\n" 1115 " The read is performed asynchronously and the aio_flush command must be\n" 1116 " used to ensure all outstanding aio requests have been completed\n" 1117 " -C, -- report statistics in a machine parsable format\n" 1118 " -P, -- use a pattern to verify read data\n" 1119 " -v, -- dump buffer to standard output\n" 1120 " -q, -- quiet mode, do not show I/O statistics\n" 1121 "\n"); 1122 } 1123 1124 static int aio_read_f(int argc, char **argv); 1125 1126 static const cmdinfo_t aio_read_cmd = { 1127 .name = "aio_read", 1128 .cfunc = aio_read_f, 1129 .argmin = 2, 1130 .argmax = -1, 1131 .args = "[-Cqv] [-P pattern ] off len [len..]", 1132 .oneline = "asynchronously reads a number of bytes", 1133 .help = aio_read_help, 1134 }; 1135 1136 static int aio_read_f(int argc, char **argv) 1137 { 1138 int nr_iov, c; 1139 struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 1140 BlockDriverAIOCB *acb; 1141 1142 while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 1143 switch (c) { 1144 case 'C': 1145 ctx->Cflag = 1; 1146 break; 1147 case 'P': 1148 ctx->Pflag = 1; 1149 ctx->pattern = parse_pattern(optarg); 1150 if (ctx->pattern < 0) { 1151 free(ctx); 1152 return 0; 1153 } 1154 break; 1155 case 'q': 1156 ctx->qflag = 1; 1157 break; 1158 case 'v': 1159 ctx->vflag = 1; 1160 break; 1161 default: 1162 free(ctx); 1163 return command_usage(&aio_read_cmd); 1164 } 1165 } 1166 1167 if (optind > argc - 2) { 1168 free(ctx); 1169 return command_usage(&aio_read_cmd); 1170 } 1171 1172 ctx->offset = cvtnum(argv[optind]); 1173 if (ctx->offset < 0) { 1174 printf("non-numeric length argument -- %s\n", argv[optind]); 1175 free(ctx); 1176 return 0; 1177 } 1178 optind++; 1179 1180 if (ctx->offset & 0x1ff) { 1181 printf("offset %" PRId64 " is not sector aligned\n", 1182 ctx->offset); 1183 free(ctx); 1184 return 0; 1185 } 1186 1187 nr_iov = argc - optind; 1188 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); 1189 1190 gettimeofday(&ctx->t1, NULL); 1191 acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 1192 ctx->qiov.size >> 9, aio_read_done, ctx); 1193 if (!acb) { 1194 free(ctx->buf); 1195 free(ctx); 1196 return -EIO; 1197 } 1198 1199 return 0; 1200 } 1201 1202 static void aio_write_help(void) 1203 { 1204 printf( 1205 "\n" 1206 " asynchronously writes a range of bytes from the given offset source\n" 1207 " from multiple buffers\n" 1208 "\n" 1209 " Example:\n" 1210 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1211 "\n" 1212 " Writes into a segment of the currently open file, using a buffer\n" 1213 " filled with a set pattern (0xcdcdcdcd).\n" 1214 " The write is performed asynchronously and the aio_flush command must be\n" 1215 " used to ensure all outstanding aio requests have been completed\n" 1216 " -P, -- use different pattern to fill file\n" 1217 " -C, -- report statistics in a machine parsable format\n" 1218 " -q, -- quiet mode, do not show I/O statistics\n" 1219 "\n"); 1220 } 1221 1222 static int aio_write_f(int argc, char **argv); 1223 1224 static const cmdinfo_t aio_write_cmd = { 1225 .name = "aio_write", 1226 .cfunc = aio_write_f, 1227 .argmin = 2, 1228 .argmax = -1, 1229 .args = "[-Cq] [-P pattern ] off len [len..]", 1230 .oneline = "asynchronously writes a number of bytes", 1231 .help = aio_write_help, 1232 }; 1233 1234 static int aio_write_f(int argc, char **argv) 1235 { 1236 int nr_iov, c; 1237 int pattern = 0xcd; 1238 struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 1239 BlockDriverAIOCB *acb; 1240 1241 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 1242 switch (c) { 1243 case 'C': 1244 ctx->Cflag = 1; 1245 break; 1246 case 'q': 1247 ctx->qflag = 1; 1248 break; 1249 case 'P': 1250 pattern = parse_pattern(optarg); 1251 if (pattern < 0) { 1252 return 0; 1253 } 1254 break; 1255 default: 1256 free(ctx); 1257 return command_usage(&aio_write_cmd); 1258 } 1259 } 1260 1261 if (optind > argc - 2) { 1262 free(ctx); 1263 return command_usage(&aio_write_cmd); 1264 } 1265 1266 ctx->offset = cvtnum(argv[optind]); 1267 if (ctx->offset < 0) { 1268 printf("non-numeric length argument -- %s\n", argv[optind]); 1269 free(ctx); 1270 return 0; 1271 } 1272 optind++; 1273 1274 if (ctx->offset & 0x1ff) { 1275 printf("offset %" PRId64 " is not sector aligned\n", 1276 ctx->offset); 1277 free(ctx); 1278 return 0; 1279 } 1280 1281 nr_iov = argc - optind; 1282 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); 1283 1284 gettimeofday(&ctx->t1, NULL); 1285 acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 1286 ctx->qiov.size >> 9, aio_write_done, ctx); 1287 if (!acb) { 1288 free(ctx->buf); 1289 free(ctx); 1290 return -EIO; 1291 } 1292 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_close(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 bs = NULL; 1615 return 1; 1616 } 1617 } 1618 1619 return 0; 1620 } 1621 1622 static void open_help(void) 1623 { 1624 printf( 1625 "\n" 1626 " opens a new file in the requested mode\n" 1627 "\n" 1628 " Example:\n" 1629 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 1630 "\n" 1631 " Opens a file for subsequent use by all of the other qemu-io commands.\n" 1632 " -r, -- open file read-only\n" 1633 " -s, -- use snapshot file\n" 1634 " -n, -- disable host cache\n" 1635 " -g, -- allow file to grow (only applies to protocols)" 1636 "\n"); 1637 } 1638 1639 static int open_f(int argc, char **argv); 1640 1641 static const cmdinfo_t open_cmd = { 1642 .name = "open", 1643 .altname = "o", 1644 .cfunc = open_f, 1645 .argmin = 1, 1646 .argmax = -1, 1647 .flags = CMD_NOFILE_OK, 1648 .args = "[-Crsn] [path]", 1649 .oneline = "open the file specified by path", 1650 .help = open_help, 1651 }; 1652 1653 static int open_f(int argc, char **argv) 1654 { 1655 int flags = 0; 1656 int readonly = 0; 1657 int growable = 0; 1658 int c; 1659 1660 while ((c = getopt(argc, argv, "snrg")) != EOF) { 1661 switch (c) { 1662 case 's': 1663 flags |= BDRV_O_SNAPSHOT; 1664 break; 1665 case 'n': 1666 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 1667 break; 1668 case 'r': 1669 readonly = 1; 1670 break; 1671 case 'g': 1672 growable = 1; 1673 break; 1674 default: 1675 return command_usage(&open_cmd); 1676 } 1677 } 1678 1679 if (!readonly) { 1680 flags |= BDRV_O_RDWR; 1681 } 1682 1683 if (optind != argc - 1) { 1684 return command_usage(&open_cmd); 1685 } 1686 1687 return openfile(argv[optind], flags, growable); 1688 } 1689 1690 static int init_args_command(int index) 1691 { 1692 /* only one device allowed so far */ 1693 if (index >= 1) { 1694 return 0; 1695 } 1696 return ++index; 1697 } 1698 1699 static int init_check_command(const cmdinfo_t *ct) 1700 { 1701 if (ct->flags & CMD_FLAG_GLOBAL) { 1702 return 1; 1703 } 1704 if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1705 fprintf(stderr, "no file open, try 'help open'\n"); 1706 return 0; 1707 } 1708 return 1; 1709 } 1710 1711 static void usage(const char *name) 1712 { 1713 printf( 1714 "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" 1715 "QEMU Disk exerciser\n" 1716 "\n" 1717 " -c, --cmd command to execute\n" 1718 " -r, --read-only export read-only\n" 1719 " -s, --snapshot use snapshot file\n" 1720 " -n, --nocache disable host cache\n" 1721 " -g, --growable allow file to grow (only applies to protocols)\n" 1722 " -m, --misalign misalign allocations for O_DIRECT\n" 1723 " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 1724 " -h, --help display this help and exit\n" 1725 " -V, --version output version information and exit\n" 1726 "\n", 1727 name); 1728 } 1729 1730 1731 int main(int argc, char **argv) 1732 { 1733 int readonly = 0; 1734 int growable = 0; 1735 const char *sopt = "hVc:rsnmgk"; 1736 const struct option lopt[] = { 1737 { "help", 0, NULL, 'h' }, 1738 { "version", 0, NULL, 'V' }, 1739 { "offset", 1, NULL, 'o' }, 1740 { "cmd", 1, NULL, 'c' }, 1741 { "read-only", 0, NULL, 'r' }, 1742 { "snapshot", 0, NULL, 's' }, 1743 { "nocache", 0, NULL, 'n' }, 1744 { "misalign", 0, NULL, 'm' }, 1745 { "growable", 0, NULL, 'g' }, 1746 { "native-aio", 0, NULL, 'k' }, 1747 { NULL, 0, NULL, 0 } 1748 }; 1749 int c; 1750 int opt_index = 0; 1751 int flags = 0; 1752 1753 progname = basename(argv[0]); 1754 1755 while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1756 switch (c) { 1757 case 's': 1758 flags |= BDRV_O_SNAPSHOT; 1759 break; 1760 case 'n': 1761 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 1762 break; 1763 case 'c': 1764 add_user_command(optarg); 1765 break; 1766 case 'r': 1767 readonly = 1; 1768 break; 1769 case 'm': 1770 misalign = 1; 1771 break; 1772 case 'g': 1773 growable = 1; 1774 break; 1775 case 'k': 1776 flags |= BDRV_O_NATIVE_AIO; 1777 break; 1778 case 'V': 1779 printf("%s version %s\n", progname, VERSION); 1780 exit(0); 1781 case 'h': 1782 usage(progname); 1783 exit(0); 1784 default: 1785 usage(progname); 1786 exit(1); 1787 } 1788 } 1789 1790 if ((argc - optind) > 1) { 1791 usage(progname); 1792 exit(1); 1793 } 1794 1795 bdrv_init(); 1796 1797 /* initialize commands */ 1798 quit_init(); 1799 help_init(); 1800 add_command(&open_cmd); 1801 add_command(&close_cmd); 1802 add_command(&read_cmd); 1803 add_command(&readv_cmd); 1804 add_command(&write_cmd); 1805 add_command(&writev_cmd); 1806 add_command(&multiwrite_cmd); 1807 add_command(&aio_read_cmd); 1808 add_command(&aio_write_cmd); 1809 add_command(&aio_flush_cmd); 1810 add_command(&flush_cmd); 1811 add_command(&truncate_cmd); 1812 add_command(&length_cmd); 1813 add_command(&info_cmd); 1814 add_command(&discard_cmd); 1815 add_command(&alloc_cmd); 1816 add_command(&map_cmd); 1817 1818 add_args_command(init_args_command); 1819 add_check_command(init_check_command); 1820 1821 /* open the device */ 1822 if (!readonly) { 1823 flags |= BDRV_O_RDWR; 1824 } 1825 1826 if ((argc - optind) == 1) { 1827 openfile(argv[optind], flags, growable); 1828 } 1829 command_loop(); 1830 1831 /* 1832 * Make sure all outstanding requests get flushed the program exits. 1833 */ 1834 qemu_aio_flush(); 1835 1836 if (bs) { 1837 bdrv_close(bs); 1838 } 1839 return 0; 1840 } 1841