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