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