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