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