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