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 verification 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 if (buf == NULL) { 600 return 0; 601 } 602 603 gettimeofday(&t1, NULL); 604 cnt = do_aio_readv(&qiov, offset, &total); 605 gettimeofday(&t2, NULL); 606 607 if (cnt < 0) { 608 printf("readv failed: %s\n", strerror(-cnt)); 609 goto out; 610 } 611 612 if (Pflag) { 613 void *cmp_buf = malloc(qiov.size); 614 memset(cmp_buf, pattern, qiov.size); 615 if (memcmp(buf, cmp_buf, qiov.size)) { 616 printf("Pattern verification failed at offset %" 617 PRId64 ", %zd bytes\n", offset, qiov.size); 618 } 619 free(cmp_buf); 620 } 621 622 if (qflag) { 623 goto out; 624 } 625 626 if (vflag) { 627 dump_buffer(buf, offset, qiov.size); 628 } 629 630 /* Finally, report back -- -C gives a parsable format */ 631 t2 = tsub(t2, t1); 632 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 633 634 out: 635 qemu_io_free(buf); 636 return 0; 637 } 638 639 static void write_help(void) 640 { 641 printf( 642 "\n" 643 " writes a range of bytes from the given offset\n" 644 "\n" 645 " Example:\n" 646 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 647 "\n" 648 " Writes into a segment of the currently open file, using a buffer\n" 649 " filled with a set pattern (0xcdcdcdcd).\n" 650 " -b, -- write to the VM state rather than the virtual disk\n" 651 " -p, -- use bdrv_pwrite to write the file\n" 652 " -P, -- use different pattern to fill file\n" 653 " -C, -- report statistics in a machine parsable format\n" 654 " -q, -- quiet mode, do not show I/O statistics\n" 655 "\n"); 656 } 657 658 static int write_f(int argc, char **argv); 659 660 static const cmdinfo_t write_cmd = { 661 .name = "write", 662 .altname = "w", 663 .cfunc = write_f, 664 .argmin = 2, 665 .argmax = -1, 666 .args = "[-abCpq] [-P pattern ] off len", 667 .oneline = "writes a number of bytes at a specified offset", 668 .help = write_help, 669 }; 670 671 static int write_f(int argc, char **argv) 672 { 673 struct timeval t1, t2; 674 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0; 675 int c, cnt; 676 char *buf; 677 int64_t offset; 678 int count; 679 /* Some compilers get confused and warn if this is not initialized. */ 680 int total = 0; 681 int pattern = 0xcd; 682 683 while ((c = getopt(argc, argv, "bCpP:q")) != EOF) { 684 switch (c) { 685 case 'b': 686 bflag = 1; 687 break; 688 case 'C': 689 Cflag = 1; 690 break; 691 case 'p': 692 pflag = 1; 693 break; 694 case 'P': 695 pattern = parse_pattern(optarg); 696 if (pattern < 0) { 697 return 0; 698 } 699 break; 700 case 'q': 701 qflag = 1; 702 break; 703 default: 704 return command_usage(&write_cmd); 705 } 706 } 707 708 if (optind != argc - 2) { 709 return command_usage(&write_cmd); 710 } 711 712 if (bflag && pflag) { 713 printf("-b and -p cannot be specified at the same time\n"); 714 return 0; 715 } 716 717 offset = cvtnum(argv[optind]); 718 if (offset < 0) { 719 printf("non-numeric length argument -- %s\n", argv[optind]); 720 return 0; 721 } 722 723 optind++; 724 count = cvtnum(argv[optind]); 725 if (count < 0) { 726 printf("non-numeric length argument -- %s\n", argv[optind]); 727 return 0; 728 } 729 730 if (!pflag) { 731 if (offset & 0x1ff) { 732 printf("offset %" PRId64 " is not sector aligned\n", 733 offset); 734 return 0; 735 } 736 737 if (count & 0x1ff) { 738 printf("count %d is not sector aligned\n", 739 count); 740 return 0; 741 } 742 } 743 744 buf = qemu_io_alloc(count, pattern); 745 746 gettimeofday(&t1, NULL); 747 if (pflag) { 748 cnt = do_pwrite(buf, offset, count, &total); 749 } else if (bflag) { 750 cnt = do_save_vmstate(buf, offset, count, &total); 751 } else { 752 cnt = do_write(buf, offset, count, &total); 753 } 754 gettimeofday(&t2, NULL); 755 756 if (cnt < 0) { 757 printf("write failed: %s\n", strerror(-cnt)); 758 goto out; 759 } 760 761 if (qflag) { 762 goto out; 763 } 764 765 /* Finally, report back -- -C gives a parsable format */ 766 t2 = tsub(t2, t1); 767 print_report("wrote", &t2, offset, count, total, cnt, Cflag); 768 769 out: 770 qemu_io_free(buf); 771 772 return 0; 773 } 774 775 static void 776 writev_help(void) 777 { 778 printf( 779 "\n" 780 " writes a range of bytes from the given offset source from multiple buffers\n" 781 "\n" 782 " Example:\n" 783 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 784 "\n" 785 " Writes into a segment of the currently open file, using a buffer\n" 786 " filled with a set pattern (0xcdcdcdcd).\n" 787 " -P, -- use different pattern to fill file\n" 788 " -C, -- report statistics in a machine parsable format\n" 789 " -q, -- quiet mode, do not show I/O statistics\n" 790 "\n"); 791 } 792 793 static int writev_f(int argc, char **argv); 794 795 static const cmdinfo_t writev_cmd = { 796 .name = "writev", 797 .cfunc = writev_f, 798 .argmin = 2, 799 .argmax = -1, 800 .args = "[-Cq] [-P pattern ] off len [len..]", 801 .oneline = "writes a number of bytes at a specified offset", 802 .help = writev_help, 803 }; 804 805 static int writev_f(int argc, char **argv) 806 { 807 struct timeval t1, t2; 808 int Cflag = 0, qflag = 0; 809 int c, cnt; 810 char *buf; 811 int64_t offset; 812 /* Some compilers get confused and warn if this is not initialized. */ 813 int total = 0; 814 int nr_iov; 815 int pattern = 0xcd; 816 QEMUIOVector qiov; 817 818 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 819 switch (c) { 820 case 'C': 821 Cflag = 1; 822 break; 823 case 'q': 824 qflag = 1; 825 break; 826 case 'P': 827 pattern = parse_pattern(optarg); 828 if (pattern < 0) { 829 return 0; 830 } 831 break; 832 default: 833 return command_usage(&writev_cmd); 834 } 835 } 836 837 if (optind > argc - 2) { 838 return command_usage(&writev_cmd); 839 } 840 841 offset = cvtnum(argv[optind]); 842 if (offset < 0) { 843 printf("non-numeric length argument -- %s\n", argv[optind]); 844 return 0; 845 } 846 optind++; 847 848 if (offset & 0x1ff) { 849 printf("offset %" PRId64 " is not sector aligned\n", 850 offset); 851 return 0; 852 } 853 854 nr_iov = argc - optind; 855 buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); 856 if (buf == NULL) { 857 return 0; 858 } 859 860 gettimeofday(&t1, NULL); 861 cnt = do_aio_writev(&qiov, offset, &total); 862 gettimeofday(&t2, NULL); 863 864 if (cnt < 0) { 865 printf("writev failed: %s\n", strerror(-cnt)); 866 goto out; 867 } 868 869 if (qflag) { 870 goto out; 871 } 872 873 /* Finally, report back -- -C gives a parsable format */ 874 t2 = tsub(t2, t1); 875 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 876 out: 877 qemu_io_free(buf); 878 return 0; 879 } 880 881 static void multiwrite_help(void) 882 { 883 printf( 884 "\n" 885 " writes a range of bytes from the given offset source from multiple buffers,\n" 886 " in a batch of requests that may be merged by qemu\n" 887 "\n" 888 " Example:\n" 889 " 'multiwrite 512 1k 1k ; 4k 1k'\n" 890 " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n" 891 "\n" 892 " Writes into a segment of the currently open file, using a buffer\n" 893 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n" 894 " by one for each request contained in the multiwrite command.\n" 895 " -P, -- use different pattern to fill file\n" 896 " -C, -- report statistics in a machine parsable format\n" 897 " -q, -- quiet mode, do not show I/O statistics\n" 898 "\n"); 899 } 900 901 static int multiwrite_f(int argc, char **argv); 902 903 static const cmdinfo_t multiwrite_cmd = { 904 .name = "multiwrite", 905 .cfunc = multiwrite_f, 906 .argmin = 2, 907 .argmax = -1, 908 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]", 909 .oneline = "issues multiple write requests at once", 910 .help = multiwrite_help, 911 }; 912 913 static int multiwrite_f(int argc, char **argv) 914 { 915 struct timeval t1, t2; 916 int Cflag = 0, qflag = 0; 917 int c, cnt; 918 char **buf; 919 int64_t offset, first_offset = 0; 920 /* Some compilers get confused and warn if this is not initialized. */ 921 int total = 0; 922 int nr_iov; 923 int nr_reqs; 924 int pattern = 0xcd; 925 QEMUIOVector *qiovs; 926 int i; 927 BlockRequest *reqs; 928 929 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 930 switch (c) { 931 case 'C': 932 Cflag = 1; 933 break; 934 case 'q': 935 qflag = 1; 936 break; 937 case 'P': 938 pattern = parse_pattern(optarg); 939 if (pattern < 0) { 940 return 0; 941 } 942 break; 943 default: 944 return command_usage(&writev_cmd); 945 } 946 } 947 948 if (optind > argc - 2) { 949 return command_usage(&writev_cmd); 950 } 951 952 nr_reqs = 1; 953 for (i = optind; i < argc; i++) { 954 if (!strcmp(argv[i], ";")) { 955 nr_reqs++; 956 } 957 } 958 959 reqs = g_malloc0(nr_reqs * sizeof(*reqs)); 960 buf = g_malloc0(nr_reqs * sizeof(*buf)); 961 qiovs = g_malloc(nr_reqs * sizeof(*qiovs)); 962 963 for (i = 0; i < nr_reqs && optind < argc; i++) { 964 int j; 965 966 /* Read the offset of the request */ 967 offset = cvtnum(argv[optind]); 968 if (offset < 0) { 969 printf("non-numeric offset argument -- %s\n", argv[optind]); 970 goto out; 971 } 972 optind++; 973 974 if (offset & 0x1ff) { 975 printf("offset %lld is not sector aligned\n", 976 (long long)offset); 977 goto out; 978 } 979 980 if (i == 0) { 981 first_offset = offset; 982 } 983 984 /* Read lengths for qiov entries */ 985 for (j = optind; j < argc; j++) { 986 if (!strcmp(argv[j], ";")) { 987 break; 988 } 989 } 990 991 nr_iov = j - optind; 992 993 /* Build request */ 994 buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern); 995 if (buf[i] == NULL) { 996 goto out; 997 } 998 999 reqs[i].qiov = &qiovs[i]; 1000 reqs[i].sector = offset >> 9; 1001 reqs[i].nb_sectors = reqs[i].qiov->size >> 9; 1002 1003 optind = j + 1; 1004 1005 pattern++; 1006 } 1007 1008 /* If there were empty requests at the end, ignore them */ 1009 nr_reqs = i; 1010 1011 gettimeofday(&t1, NULL); 1012 cnt = do_aio_multiwrite(reqs, nr_reqs, &total); 1013 gettimeofday(&t2, NULL); 1014 1015 if (cnt < 0) { 1016 printf("aio_multiwrite failed: %s\n", strerror(-cnt)); 1017 goto out; 1018 } 1019 1020 if (qflag) { 1021 goto out; 1022 } 1023 1024 /* Finally, report back -- -C gives a parsable format */ 1025 t2 = tsub(t2, t1); 1026 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); 1027 out: 1028 for (i = 0; i < nr_reqs; i++) { 1029 qemu_io_free(buf[i]); 1030 if (reqs[i].qiov != NULL) { 1031 qemu_iovec_destroy(&qiovs[i]); 1032 } 1033 } 1034 g_free(buf); 1035 g_free(reqs); 1036 g_free(qiovs); 1037 return 0; 1038 } 1039 1040 struct aio_ctx { 1041 QEMUIOVector qiov; 1042 int64_t offset; 1043 char *buf; 1044 int qflag; 1045 int vflag; 1046 int Cflag; 1047 int Pflag; 1048 int pattern; 1049 struct timeval t1; 1050 }; 1051 1052 static void aio_write_done(void *opaque, int ret) 1053 { 1054 struct aio_ctx *ctx = opaque; 1055 struct timeval t2; 1056 1057 gettimeofday(&t2, NULL); 1058 1059 1060 if (ret < 0) { 1061 printf("aio_write failed: %s\n", strerror(-ret)); 1062 goto out; 1063 } 1064 1065 if (ctx->qflag) { 1066 goto out; 1067 } 1068 1069 /* Finally, report back -- -C gives a parsable format */ 1070 t2 = tsub(t2, ctx->t1); 1071 print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1072 ctx->qiov.size, 1, ctx->Cflag); 1073 out: 1074 qemu_io_free(ctx->buf); 1075 free(ctx); 1076 } 1077 1078 static void aio_read_done(void *opaque, int ret) 1079 { 1080 struct aio_ctx *ctx = opaque; 1081 struct timeval t2; 1082 1083 gettimeofday(&t2, NULL); 1084 1085 if (ret < 0) { 1086 printf("readv failed: %s\n", strerror(-ret)); 1087 goto out; 1088 } 1089 1090 if (ctx->Pflag) { 1091 void *cmp_buf = malloc(ctx->qiov.size); 1092 1093 memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1094 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 1095 printf("Pattern verification failed at offset %" 1096 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size); 1097 } 1098 free(cmp_buf); 1099 } 1100 1101 if (ctx->qflag) { 1102 goto out; 1103 } 1104 1105 if (ctx->vflag) { 1106 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1107 } 1108 1109 /* Finally, report back -- -C gives a parsable format */ 1110 t2 = tsub(t2, ctx->t1); 1111 print_report("read", &t2, ctx->offset, ctx->qiov.size, 1112 ctx->qiov.size, 1, ctx->Cflag); 1113 out: 1114 qemu_io_free(ctx->buf); 1115 free(ctx); 1116 } 1117 1118 static void aio_read_help(void) 1119 { 1120 printf( 1121 "\n" 1122 " asynchronously reads a range of bytes from the given offset\n" 1123 "\n" 1124 " Example:\n" 1125 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 1126 "\n" 1127 " Reads a segment of the currently open file, optionally dumping it to the\n" 1128 " standard output stream (with -v option) for subsequent inspection.\n" 1129 " The read is performed asynchronously and the aio_flush command must be\n" 1130 " used to ensure all outstanding aio requests have been completed\n" 1131 " -C, -- report statistics in a machine parsable format\n" 1132 " -P, -- use a pattern to verify read data\n" 1133 " -v, -- dump buffer to standard output\n" 1134 " -q, -- quiet mode, do not show I/O statistics\n" 1135 "\n"); 1136 } 1137 1138 static int aio_read_f(int argc, char **argv); 1139 1140 static const cmdinfo_t aio_read_cmd = { 1141 .name = "aio_read", 1142 .cfunc = aio_read_f, 1143 .argmin = 2, 1144 .argmax = -1, 1145 .args = "[-Cqv] [-P pattern ] off len [len..]", 1146 .oneline = "asynchronously reads a number of bytes", 1147 .help = aio_read_help, 1148 }; 1149 1150 static int aio_read_f(int argc, char **argv) 1151 { 1152 int nr_iov, c; 1153 struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 1154 BlockDriverAIOCB *acb; 1155 1156 while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 1157 switch (c) { 1158 case 'C': 1159 ctx->Cflag = 1; 1160 break; 1161 case 'P': 1162 ctx->Pflag = 1; 1163 ctx->pattern = parse_pattern(optarg); 1164 if (ctx->pattern < 0) { 1165 free(ctx); 1166 return 0; 1167 } 1168 break; 1169 case 'q': 1170 ctx->qflag = 1; 1171 break; 1172 case 'v': 1173 ctx->vflag = 1; 1174 break; 1175 default: 1176 free(ctx); 1177 return command_usage(&aio_read_cmd); 1178 } 1179 } 1180 1181 if (optind > argc - 2) { 1182 free(ctx); 1183 return command_usage(&aio_read_cmd); 1184 } 1185 1186 ctx->offset = cvtnum(argv[optind]); 1187 if (ctx->offset < 0) { 1188 printf("non-numeric length argument -- %s\n", argv[optind]); 1189 free(ctx); 1190 return 0; 1191 } 1192 optind++; 1193 1194 if (ctx->offset & 0x1ff) { 1195 printf("offset %" PRId64 " is not sector aligned\n", 1196 ctx->offset); 1197 free(ctx); 1198 return 0; 1199 } 1200 1201 nr_iov = argc - optind; 1202 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); 1203 if (ctx->buf == NULL) { 1204 free(ctx); 1205 return 0; 1206 } 1207 1208 gettimeofday(&ctx->t1, NULL); 1209 acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 1210 ctx->qiov.size >> 9, aio_read_done, ctx); 1211 if (!acb) { 1212 free(ctx->buf); 1213 free(ctx); 1214 return -EIO; 1215 } 1216 1217 return 0; 1218 } 1219 1220 static void aio_write_help(void) 1221 { 1222 printf( 1223 "\n" 1224 " asynchronously writes a range of bytes from the given offset source\n" 1225 " from multiple buffers\n" 1226 "\n" 1227 " Example:\n" 1228 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1229 "\n" 1230 " Writes into a segment of the currently open file, using a buffer\n" 1231 " filled with a set pattern (0xcdcdcdcd).\n" 1232 " The write is performed asynchronously and the aio_flush command must be\n" 1233 " used to ensure all outstanding aio requests have been completed\n" 1234 " -P, -- use different pattern to fill file\n" 1235 " -C, -- report statistics in a machine parsable format\n" 1236 " -q, -- quiet mode, do not show I/O statistics\n" 1237 "\n"); 1238 } 1239 1240 static int aio_write_f(int argc, char **argv); 1241 1242 static const cmdinfo_t aio_write_cmd = { 1243 .name = "aio_write", 1244 .cfunc = aio_write_f, 1245 .argmin = 2, 1246 .argmax = -1, 1247 .args = "[-Cq] [-P pattern ] off len [len..]", 1248 .oneline = "asynchronously writes a number of bytes", 1249 .help = aio_write_help, 1250 }; 1251 1252 static int aio_write_f(int argc, char **argv) 1253 { 1254 int nr_iov, c; 1255 int pattern = 0xcd; 1256 struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 1257 BlockDriverAIOCB *acb; 1258 1259 while ((c = getopt(argc, argv, "CqP:")) != EOF) { 1260 switch (c) { 1261 case 'C': 1262 ctx->Cflag = 1; 1263 break; 1264 case 'q': 1265 ctx->qflag = 1; 1266 break; 1267 case 'P': 1268 pattern = parse_pattern(optarg); 1269 if (pattern < 0) { 1270 free(ctx); 1271 return 0; 1272 } 1273 break; 1274 default: 1275 free(ctx); 1276 return command_usage(&aio_write_cmd); 1277 } 1278 } 1279 1280 if (optind > argc - 2) { 1281 free(ctx); 1282 return command_usage(&aio_write_cmd); 1283 } 1284 1285 ctx->offset = cvtnum(argv[optind]); 1286 if (ctx->offset < 0) { 1287 printf("non-numeric length argument -- %s\n", argv[optind]); 1288 free(ctx); 1289 return 0; 1290 } 1291 optind++; 1292 1293 if (ctx->offset & 0x1ff) { 1294 printf("offset %" PRId64 " is not sector aligned\n", 1295 ctx->offset); 1296 free(ctx); 1297 return 0; 1298 } 1299 1300 nr_iov = argc - optind; 1301 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); 1302 if (ctx->buf == NULL) { 1303 free(ctx); 1304 return 0; 1305 } 1306 1307 gettimeofday(&ctx->t1, NULL); 1308 acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 1309 ctx->qiov.size >> 9, aio_write_done, ctx); 1310 if (!acb) { 1311 free(ctx->buf); 1312 free(ctx); 1313 return -EIO; 1314 } 1315 1316 return 0; 1317 } 1318 1319 static int aio_flush_f(int argc, char **argv) 1320 { 1321 qemu_aio_flush(); 1322 return 0; 1323 } 1324 1325 static const cmdinfo_t aio_flush_cmd = { 1326 .name = "aio_flush", 1327 .cfunc = aio_flush_f, 1328 .oneline = "completes all outstanding aio requests" 1329 }; 1330 1331 static int flush_f(int argc, char **argv) 1332 { 1333 bdrv_flush(bs); 1334 return 0; 1335 } 1336 1337 static const cmdinfo_t flush_cmd = { 1338 .name = "flush", 1339 .altname = "f", 1340 .cfunc = flush_f, 1341 .oneline = "flush all in-core file state to disk", 1342 }; 1343 1344 static int truncate_f(int argc, char **argv) 1345 { 1346 int64_t offset; 1347 int ret; 1348 1349 offset = cvtnum(argv[1]); 1350 if (offset < 0) { 1351 printf("non-numeric truncate argument -- %s\n", argv[1]); 1352 return 0; 1353 } 1354 1355 ret = bdrv_truncate(bs, offset); 1356 if (ret < 0) { 1357 printf("truncate: %s\n", strerror(-ret)); 1358 return 0; 1359 } 1360 1361 return 0; 1362 } 1363 1364 static const cmdinfo_t truncate_cmd = { 1365 .name = "truncate", 1366 .altname = "t", 1367 .cfunc = truncate_f, 1368 .argmin = 1, 1369 .argmax = 1, 1370 .args = "off", 1371 .oneline = "truncates the current file at the given offset", 1372 }; 1373 1374 static int length_f(int argc, char **argv) 1375 { 1376 int64_t size; 1377 char s1[64]; 1378 1379 size = bdrv_getlength(bs); 1380 if (size < 0) { 1381 printf("getlength: %s\n", strerror(-size)); 1382 return 0; 1383 } 1384 1385 cvtstr(size, s1, sizeof(s1)); 1386 printf("%s\n", s1); 1387 return 0; 1388 } 1389 1390 1391 static const cmdinfo_t length_cmd = { 1392 .name = "length", 1393 .altname = "l", 1394 .cfunc = length_f, 1395 .oneline = "gets the length of the current file", 1396 }; 1397 1398 1399 static int info_f(int argc, char **argv) 1400 { 1401 BlockDriverInfo bdi; 1402 char s1[64], s2[64]; 1403 int ret; 1404 1405 if (bs->drv && bs->drv->format_name) { 1406 printf("format name: %s\n", bs->drv->format_name); 1407 } 1408 if (bs->drv && bs->drv->protocol_name) { 1409 printf("format name: %s\n", bs->drv->protocol_name); 1410 } 1411 1412 ret = bdrv_get_info(bs, &bdi); 1413 if (ret) { 1414 return 0; 1415 } 1416 1417 cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1418 cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1419 1420 printf("cluster size: %s\n", s1); 1421 printf("vm state offset: %s\n", s2); 1422 1423 return 0; 1424 } 1425 1426 1427 1428 static const cmdinfo_t info_cmd = { 1429 .name = "info", 1430 .altname = "i", 1431 .cfunc = info_f, 1432 .oneline = "prints information about the current file", 1433 }; 1434 1435 static void discard_help(void) 1436 { 1437 printf( 1438 "\n" 1439 " discards a range of bytes from the given offset\n" 1440 "\n" 1441 " Example:\n" 1442 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n" 1443 "\n" 1444 " Discards a segment of the currently open file.\n" 1445 " -C, -- report statistics in a machine parsable format\n" 1446 " -q, -- quiet mode, do not show I/O statistics\n" 1447 "\n"); 1448 } 1449 1450 static int discard_f(int argc, char **argv); 1451 1452 static const cmdinfo_t discard_cmd = { 1453 .name = "discard", 1454 .altname = "d", 1455 .cfunc = discard_f, 1456 .argmin = 2, 1457 .argmax = -1, 1458 .args = "[-Cq] off len", 1459 .oneline = "discards a number of bytes at a specified offset", 1460 .help = discard_help, 1461 }; 1462 1463 static int discard_f(int argc, char **argv) 1464 { 1465 struct timeval t1, t2; 1466 int Cflag = 0, qflag = 0; 1467 int c, ret; 1468 int64_t offset; 1469 int count; 1470 1471 while ((c = getopt(argc, argv, "Cq")) != EOF) { 1472 switch (c) { 1473 case 'C': 1474 Cflag = 1; 1475 break; 1476 case 'q': 1477 qflag = 1; 1478 break; 1479 default: 1480 return command_usage(&discard_cmd); 1481 } 1482 } 1483 1484 if (optind != argc - 2) { 1485 return command_usage(&discard_cmd); 1486 } 1487 1488 offset = cvtnum(argv[optind]); 1489 if (offset < 0) { 1490 printf("non-numeric length argument -- %s\n", argv[optind]); 1491 return 0; 1492 } 1493 1494 optind++; 1495 count = cvtnum(argv[optind]); 1496 if (count < 0) { 1497 printf("non-numeric length argument -- %s\n", argv[optind]); 1498 return 0; 1499 } 1500 1501 gettimeofday(&t1, NULL); 1502 ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, 1503 count >> BDRV_SECTOR_BITS); 1504 gettimeofday(&t2, NULL); 1505 1506 if (ret < 0) { 1507 printf("discard failed: %s\n", strerror(-ret)); 1508 goto out; 1509 } 1510 1511 /* Finally, report back -- -C gives a parsable format */ 1512 if (!qflag) { 1513 t2 = tsub(t2, t1); 1514 print_report("discard", &t2, offset, count, count, 1, Cflag); 1515 } 1516 1517 out: 1518 return 0; 1519 } 1520 1521 static int alloc_f(int argc, char **argv) 1522 { 1523 int64_t offset; 1524 int nb_sectors, remaining; 1525 char s1[64]; 1526 int num, sum_alloc; 1527 int ret; 1528 1529 offset = cvtnum(argv[1]); 1530 if (offset & 0x1ff) { 1531 printf("offset %" PRId64 " is not sector aligned\n", 1532 offset); 1533 return 0; 1534 } 1535 1536 if (argc == 3) { 1537 nb_sectors = cvtnum(argv[2]); 1538 } else { 1539 nb_sectors = 1; 1540 } 1541 1542 remaining = nb_sectors; 1543 sum_alloc = 0; 1544 while (remaining) { 1545 ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); 1546 remaining -= num; 1547 if (ret) { 1548 sum_alloc += num; 1549 } 1550 } 1551 1552 cvtstr(offset, s1, sizeof(s1)); 1553 1554 printf("%d/%d sectors allocated at offset %s\n", 1555 sum_alloc, nb_sectors, s1); 1556 return 0; 1557 } 1558 1559 static const cmdinfo_t alloc_cmd = { 1560 .name = "alloc", 1561 .altname = "a", 1562 .argmin = 1, 1563 .argmax = 2, 1564 .cfunc = alloc_f, 1565 .args = "off [sectors]", 1566 .oneline = "checks if a sector is present in the file", 1567 }; 1568 1569 static int map_f(int argc, char **argv) 1570 { 1571 int64_t offset; 1572 int64_t nb_sectors; 1573 char s1[64]; 1574 int num, num_checked; 1575 int ret; 1576 const char *retstr; 1577 1578 offset = 0; 1579 nb_sectors = bs->total_sectors; 1580 1581 do { 1582 num_checked = MIN(nb_sectors, INT_MAX); 1583 ret = bdrv_is_allocated(bs, offset, num_checked, &num); 1584 retstr = ret ? " allocated" : "not allocated"; 1585 cvtstr(offset << 9ULL, s1, sizeof(s1)); 1586 printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n", 1587 offset << 9ULL, num, num_checked, retstr, s1, ret); 1588 1589 offset += num; 1590 nb_sectors -= num; 1591 } while (offset < bs->total_sectors); 1592 1593 return 0; 1594 } 1595 1596 static const cmdinfo_t map_cmd = { 1597 .name = "map", 1598 .argmin = 0, 1599 .argmax = 0, 1600 .cfunc = map_f, 1601 .args = "", 1602 .oneline = "prints the allocated areas of a file", 1603 }; 1604 1605 1606 static int close_f(int argc, char **argv) 1607 { 1608 bdrv_delete(bs); 1609 bs = NULL; 1610 return 0; 1611 } 1612 1613 static const cmdinfo_t close_cmd = { 1614 .name = "close", 1615 .altname = "c", 1616 .cfunc = close_f, 1617 .oneline = "close the current open file", 1618 }; 1619 1620 static int openfile(char *name, int flags, int growable) 1621 { 1622 if (bs) { 1623 fprintf(stderr, "file open already, try 'help close'\n"); 1624 return 1; 1625 } 1626 1627 if (growable) { 1628 if (bdrv_file_open(&bs, name, flags)) { 1629 fprintf(stderr, "%s: can't open device %s\n", progname, name); 1630 return 1; 1631 } 1632 } else { 1633 bs = bdrv_new("hda"); 1634 1635 if (bdrv_open(bs, name, flags, NULL) < 0) { 1636 fprintf(stderr, "%s: can't open device %s\n", progname, name); 1637 bdrv_delete(bs); 1638 bs = NULL; 1639 return 1; 1640 } 1641 } 1642 1643 return 0; 1644 } 1645 1646 static void open_help(void) 1647 { 1648 printf( 1649 "\n" 1650 " opens a new file in the requested mode\n" 1651 "\n" 1652 " Example:\n" 1653 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 1654 "\n" 1655 " Opens a file for subsequent use by all of the other qemu-io commands.\n" 1656 " -r, -- open file read-only\n" 1657 " -s, -- use snapshot file\n" 1658 " -n, -- disable host cache\n" 1659 " -g, -- allow file to grow (only applies to protocols)" 1660 "\n"); 1661 } 1662 1663 static int open_f(int argc, char **argv); 1664 1665 static const cmdinfo_t open_cmd = { 1666 .name = "open", 1667 .altname = "o", 1668 .cfunc = open_f, 1669 .argmin = 1, 1670 .argmax = -1, 1671 .flags = CMD_NOFILE_OK, 1672 .args = "[-Crsn] [path]", 1673 .oneline = "open the file specified by path", 1674 .help = open_help, 1675 }; 1676 1677 static int open_f(int argc, char **argv) 1678 { 1679 int flags = 0; 1680 int readonly = 0; 1681 int growable = 0; 1682 int c; 1683 1684 while ((c = getopt(argc, argv, "snrg")) != EOF) { 1685 switch (c) { 1686 case 's': 1687 flags |= BDRV_O_SNAPSHOT; 1688 break; 1689 case 'n': 1690 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 1691 break; 1692 case 'r': 1693 readonly = 1; 1694 break; 1695 case 'g': 1696 growable = 1; 1697 break; 1698 default: 1699 return command_usage(&open_cmd); 1700 } 1701 } 1702 1703 if (!readonly) { 1704 flags |= BDRV_O_RDWR; 1705 } 1706 1707 if (optind != argc - 1) { 1708 return command_usage(&open_cmd); 1709 } 1710 1711 return openfile(argv[optind], flags, growable); 1712 } 1713 1714 static int init_args_command(int index) 1715 { 1716 /* only one device allowed so far */ 1717 if (index >= 1) { 1718 return 0; 1719 } 1720 return ++index; 1721 } 1722 1723 static int init_check_command(const cmdinfo_t *ct) 1724 { 1725 if (ct->flags & CMD_FLAG_GLOBAL) { 1726 return 1; 1727 } 1728 if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1729 fprintf(stderr, "no file open, try 'help open'\n"); 1730 return 0; 1731 } 1732 return 1; 1733 } 1734 1735 static void usage(const char *name) 1736 { 1737 printf( 1738 "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" 1739 "QEMU Disk exerciser\n" 1740 "\n" 1741 " -c, --cmd command to execute\n" 1742 " -r, --read-only export read-only\n" 1743 " -s, --snapshot use snapshot file\n" 1744 " -n, --nocache disable host cache\n" 1745 " -g, --growable allow file to grow (only applies to protocols)\n" 1746 " -m, --misalign misalign allocations for O_DIRECT\n" 1747 " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 1748 " -h, --help display this help and exit\n" 1749 " -V, --version output version information and exit\n" 1750 "\n", 1751 name); 1752 } 1753 1754 1755 int main(int argc, char **argv) 1756 { 1757 int readonly = 0; 1758 int growable = 0; 1759 const char *sopt = "hVc:rsnmgk"; 1760 const struct option lopt[] = { 1761 { "help", 0, NULL, 'h' }, 1762 { "version", 0, NULL, 'V' }, 1763 { "offset", 1, NULL, 'o' }, 1764 { "cmd", 1, NULL, 'c' }, 1765 { "read-only", 0, NULL, 'r' }, 1766 { "snapshot", 0, NULL, 's' }, 1767 { "nocache", 0, NULL, 'n' }, 1768 { "misalign", 0, NULL, 'm' }, 1769 { "growable", 0, NULL, 'g' }, 1770 { "native-aio", 0, NULL, 'k' }, 1771 { NULL, 0, NULL, 0 } 1772 }; 1773 int c; 1774 int opt_index = 0; 1775 int flags = 0; 1776 1777 progname = basename(argv[0]); 1778 1779 while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1780 switch (c) { 1781 case 's': 1782 flags |= BDRV_O_SNAPSHOT; 1783 break; 1784 case 'n': 1785 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 1786 break; 1787 case 'c': 1788 add_user_command(optarg); 1789 break; 1790 case 'r': 1791 readonly = 1; 1792 break; 1793 case 'm': 1794 misalign = 1; 1795 break; 1796 case 'g': 1797 growable = 1; 1798 break; 1799 case 'k': 1800 flags |= BDRV_O_NATIVE_AIO; 1801 break; 1802 case 'V': 1803 printf("%s version %s\n", progname, VERSION); 1804 exit(0); 1805 case 'h': 1806 usage(progname); 1807 exit(0); 1808 default: 1809 usage(progname); 1810 exit(1); 1811 } 1812 } 1813 1814 if ((argc - optind) > 1) { 1815 usage(progname); 1816 exit(1); 1817 } 1818 1819 bdrv_init(); 1820 1821 /* initialize commands */ 1822 quit_init(); 1823 help_init(); 1824 add_command(&open_cmd); 1825 add_command(&close_cmd); 1826 add_command(&read_cmd); 1827 add_command(&readv_cmd); 1828 add_command(&write_cmd); 1829 add_command(&writev_cmd); 1830 add_command(&multiwrite_cmd); 1831 add_command(&aio_read_cmd); 1832 add_command(&aio_write_cmd); 1833 add_command(&aio_flush_cmd); 1834 add_command(&flush_cmd); 1835 add_command(&truncate_cmd); 1836 add_command(&length_cmd); 1837 add_command(&info_cmd); 1838 add_command(&discard_cmd); 1839 add_command(&alloc_cmd); 1840 add_command(&map_cmd); 1841 1842 add_args_command(init_args_command); 1843 add_check_command(init_check_command); 1844 1845 /* open the device */ 1846 if (!readonly) { 1847 flags |= BDRV_O_RDWR; 1848 } 1849 1850 if ((argc - optind) == 1) { 1851 openfile(argv[optind], flags, growable); 1852 } 1853 command_loop(); 1854 1855 /* 1856 * Make sure all outstanding requests complete before the program exits. 1857 */ 1858 bdrv_drain_all(); 1859 1860 if (bs) { 1861 bdrv_delete(bs); 1862 } 1863 return 0; 1864 } 1865