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