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