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