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