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