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 goto out; 1432 } 1433 1434 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct); 1435 1436 if (ctx->qflag) { 1437 goto out; 1438 } 1439 1440 /* Finally, report back -- -C gives a parsable format */ 1441 t2 = tsub(t2, ctx->t1); 1442 print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1443 ctx->qiov.size, 1, ctx->Cflag); 1444 out: 1445 qemu_io_free(ctx->buf); 1446 qemu_iovec_destroy(&ctx->qiov); 1447 g_free(ctx); 1448 } 1449 1450 static void aio_read_done(void *opaque, int ret) 1451 { 1452 struct aio_ctx *ctx = opaque; 1453 struct timeval t2; 1454 1455 gettimeofday(&t2, NULL); 1456 1457 if (ret < 0) { 1458 printf("readv failed: %s\n", strerror(-ret)); 1459 goto out; 1460 } 1461 1462 if (ctx->Pflag) { 1463 void *cmp_buf = g_malloc(ctx->qiov.size); 1464 1465 memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1466 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 1467 printf("Pattern verification failed at offset %" 1468 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size); 1469 } 1470 g_free(cmp_buf); 1471 } 1472 1473 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct); 1474 1475 if (ctx->qflag) { 1476 goto out; 1477 } 1478 1479 if (ctx->vflag) { 1480 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1481 } 1482 1483 /* Finally, report back -- -C gives a parsable format */ 1484 t2 = tsub(t2, ctx->t1); 1485 print_report("read", &t2, ctx->offset, ctx->qiov.size, 1486 ctx->qiov.size, 1, ctx->Cflag); 1487 out: 1488 qemu_io_free(ctx->buf); 1489 qemu_iovec_destroy(&ctx->qiov); 1490 g_free(ctx); 1491 } 1492 1493 static void aio_read_help(void) 1494 { 1495 printf( 1496 "\n" 1497 " asynchronously reads a range of bytes from the given offset\n" 1498 "\n" 1499 " Example:\n" 1500 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 1501 "\n" 1502 " Reads a segment of the currently open file, optionally dumping it to the\n" 1503 " standard output stream (with -v option) for subsequent inspection.\n" 1504 " The read is performed asynchronously and the aio_flush command must be\n" 1505 " used to ensure all outstanding aio requests have been completed.\n" 1506 " -C, -- report statistics in a machine parsable format\n" 1507 " -P, -- use a pattern to verify read data\n" 1508 " -v, -- dump buffer to standard output\n" 1509 " -q, -- quiet mode, do not show I/O statistics\n" 1510 "\n"); 1511 } 1512 1513 static int aio_read_f(BlockBackend *blk, int argc, char **argv); 1514 1515 static const cmdinfo_t aio_read_cmd = { 1516 .name = "aio_read", 1517 .cfunc = aio_read_f, 1518 .argmin = 2, 1519 .argmax = -1, 1520 .args = "[-Cqv] [-P pattern ] off len [len..]", 1521 .oneline = "asynchronously reads a number of bytes", 1522 .help = aio_read_help, 1523 }; 1524 1525 static int aio_read_f(BlockBackend *blk, int argc, char **argv) 1526 { 1527 int nr_iov, c; 1528 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1529 1530 ctx->blk = blk; 1531 while ((c = getopt(argc, argv, "CP:qv")) != -1) { 1532 switch (c) { 1533 case 'C': 1534 ctx->Cflag = 1; 1535 break; 1536 case 'P': 1537 ctx->Pflag = 1; 1538 ctx->pattern = parse_pattern(optarg); 1539 if (ctx->pattern < 0) { 1540 g_free(ctx); 1541 return 0; 1542 } 1543 break; 1544 case 'q': 1545 ctx->qflag = 1; 1546 break; 1547 case 'v': 1548 ctx->vflag = 1; 1549 break; 1550 default: 1551 g_free(ctx); 1552 return qemuio_command_usage(&aio_read_cmd); 1553 } 1554 } 1555 1556 if (optind > argc - 2) { 1557 g_free(ctx); 1558 return qemuio_command_usage(&aio_read_cmd); 1559 } 1560 1561 ctx->offset = cvtnum(argv[optind]); 1562 if (ctx->offset < 0) { 1563 print_cvtnum_err(ctx->offset, argv[optind]); 1564 g_free(ctx); 1565 return 0; 1566 } 1567 optind++; 1568 1569 if (ctx->offset & 0x1ff) { 1570 printf("offset %" PRId64 " is not sector aligned\n", 1571 ctx->offset); 1572 g_free(ctx); 1573 return 0; 1574 } 1575 1576 nr_iov = argc - optind; 1577 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab); 1578 if (ctx->buf == NULL) { 1579 g_free(ctx); 1580 return 0; 1581 } 1582 1583 gettimeofday(&ctx->t1, NULL); 1584 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, 1585 BLOCK_ACCT_READ); 1586 blk_aio_readv(blk, ctx->offset >> 9, &ctx->qiov, 1587 ctx->qiov.size >> 9, aio_read_done, ctx); 1588 return 0; 1589 } 1590 1591 static void aio_write_help(void) 1592 { 1593 printf( 1594 "\n" 1595 " asynchronously writes a range of bytes from the given offset source\n" 1596 " from multiple buffers\n" 1597 "\n" 1598 " Example:\n" 1599 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1600 "\n" 1601 " Writes into a segment of the currently open file, using a buffer\n" 1602 " filled with a set pattern (0xcdcdcdcd).\n" 1603 " The write is performed asynchronously and the aio_flush command must be\n" 1604 " used to ensure all outstanding aio requests have been completed.\n" 1605 " -P, -- use different pattern to fill file\n" 1606 " -C, -- report statistics in a machine parsable format\n" 1607 " -q, -- quiet mode, do not show I/O statistics\n" 1608 "\n"); 1609 } 1610 1611 static int aio_write_f(BlockBackend *blk, int argc, char **argv); 1612 1613 static const cmdinfo_t aio_write_cmd = { 1614 .name = "aio_write", 1615 .cfunc = aio_write_f, 1616 .argmin = 2, 1617 .argmax = -1, 1618 .args = "[-Cq] [-P pattern ] off len [len..]", 1619 .oneline = "asynchronously writes a number of bytes", 1620 .help = aio_write_help, 1621 }; 1622 1623 static int aio_write_f(BlockBackend *blk, int argc, char **argv) 1624 { 1625 int nr_iov, c; 1626 int pattern = 0xcd; 1627 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1628 1629 ctx->blk = blk; 1630 while ((c = getopt(argc, argv, "CqP:")) != -1) { 1631 switch (c) { 1632 case 'C': 1633 ctx->Cflag = 1; 1634 break; 1635 case 'q': 1636 ctx->qflag = 1; 1637 break; 1638 case 'P': 1639 pattern = parse_pattern(optarg); 1640 if (pattern < 0) { 1641 g_free(ctx); 1642 return 0; 1643 } 1644 break; 1645 default: 1646 g_free(ctx); 1647 return qemuio_command_usage(&aio_write_cmd); 1648 } 1649 } 1650 1651 if (optind > argc - 2) { 1652 g_free(ctx); 1653 return qemuio_command_usage(&aio_write_cmd); 1654 } 1655 1656 ctx->offset = cvtnum(argv[optind]); 1657 if (ctx->offset < 0) { 1658 print_cvtnum_err(ctx->offset, argv[optind]); 1659 g_free(ctx); 1660 return 0; 1661 } 1662 optind++; 1663 1664 if (ctx->offset & 0x1ff) { 1665 printf("offset %" PRId64 " is not sector aligned\n", 1666 ctx->offset); 1667 g_free(ctx); 1668 return 0; 1669 } 1670 1671 nr_iov = argc - optind; 1672 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, pattern); 1673 if (ctx->buf == NULL) { 1674 g_free(ctx); 1675 return 0; 1676 } 1677 1678 gettimeofday(&ctx->t1, NULL); 1679 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, 1680 BLOCK_ACCT_WRITE); 1681 blk_aio_writev(blk, ctx->offset >> 9, &ctx->qiov, 1682 ctx->qiov.size >> 9, aio_write_done, ctx); 1683 return 0; 1684 } 1685 1686 static int aio_flush_f(BlockBackend *blk, int argc, char **argv) 1687 { 1688 blk_drain_all(); 1689 return 0; 1690 } 1691 1692 static const cmdinfo_t aio_flush_cmd = { 1693 .name = "aio_flush", 1694 .cfunc = aio_flush_f, 1695 .oneline = "completes all outstanding aio requests" 1696 }; 1697 1698 static int flush_f(BlockBackend *blk, int argc, char **argv) 1699 { 1700 blk_flush(blk); 1701 return 0; 1702 } 1703 1704 static const cmdinfo_t flush_cmd = { 1705 .name = "flush", 1706 .altname = "f", 1707 .cfunc = flush_f, 1708 .oneline = "flush all in-core file state to disk", 1709 }; 1710 1711 static int truncate_f(BlockBackend *blk, int argc, char **argv) 1712 { 1713 int64_t offset; 1714 int ret; 1715 1716 offset = cvtnum(argv[1]); 1717 if (offset < 0) { 1718 print_cvtnum_err(offset, argv[1]); 1719 return 0; 1720 } 1721 1722 ret = blk_truncate(blk, offset); 1723 if (ret < 0) { 1724 printf("truncate: %s\n", strerror(-ret)); 1725 return 0; 1726 } 1727 1728 return 0; 1729 } 1730 1731 static const cmdinfo_t truncate_cmd = { 1732 .name = "truncate", 1733 .altname = "t", 1734 .cfunc = truncate_f, 1735 .argmin = 1, 1736 .argmax = 1, 1737 .args = "off", 1738 .oneline = "truncates the current file at the given offset", 1739 }; 1740 1741 static int length_f(BlockBackend *blk, int argc, char **argv) 1742 { 1743 int64_t size; 1744 char s1[64]; 1745 1746 size = blk_getlength(blk); 1747 if (size < 0) { 1748 printf("getlength: %s\n", strerror(-size)); 1749 return 0; 1750 } 1751 1752 cvtstr(size, s1, sizeof(s1)); 1753 printf("%s\n", s1); 1754 return 0; 1755 } 1756 1757 1758 static const cmdinfo_t length_cmd = { 1759 .name = "length", 1760 .altname = "l", 1761 .cfunc = length_f, 1762 .oneline = "gets the length of the current file", 1763 }; 1764 1765 1766 static int info_f(BlockBackend *blk, int argc, char **argv) 1767 { 1768 BlockDriverState *bs = blk_bs(blk); 1769 BlockDriverInfo bdi; 1770 ImageInfoSpecific *spec_info; 1771 char s1[64], s2[64]; 1772 int ret; 1773 1774 if (bs->drv && bs->drv->format_name) { 1775 printf("format name: %s\n", bs->drv->format_name); 1776 } 1777 if (bs->drv && bs->drv->protocol_name) { 1778 printf("format name: %s\n", bs->drv->protocol_name); 1779 } 1780 1781 ret = bdrv_get_info(bs, &bdi); 1782 if (ret) { 1783 return 0; 1784 } 1785 1786 cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1787 cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1788 1789 printf("cluster size: %s\n", s1); 1790 printf("vm state offset: %s\n", s2); 1791 1792 spec_info = bdrv_get_specific_info(bs); 1793 if (spec_info) { 1794 printf("Format specific information:\n"); 1795 bdrv_image_info_specific_dump(fprintf, stdout, spec_info); 1796 qapi_free_ImageInfoSpecific(spec_info); 1797 } 1798 1799 return 0; 1800 } 1801 1802 1803 1804 static const cmdinfo_t info_cmd = { 1805 .name = "info", 1806 .altname = "i", 1807 .cfunc = info_f, 1808 .oneline = "prints information about the current file", 1809 }; 1810 1811 static void discard_help(void) 1812 { 1813 printf( 1814 "\n" 1815 " discards a range of bytes from the given offset\n" 1816 "\n" 1817 " Example:\n" 1818 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n" 1819 "\n" 1820 " Discards a segment of the currently open file.\n" 1821 " -C, -- report statistics in a machine parsable format\n" 1822 " -q, -- quiet mode, do not show I/O statistics\n" 1823 "\n"); 1824 } 1825 1826 static int discard_f(BlockBackend *blk, int argc, char **argv); 1827 1828 static const cmdinfo_t discard_cmd = { 1829 .name = "discard", 1830 .altname = "d", 1831 .cfunc = discard_f, 1832 .argmin = 2, 1833 .argmax = -1, 1834 .args = "[-Cq] off len", 1835 .oneline = "discards a number of bytes at a specified offset", 1836 .help = discard_help, 1837 }; 1838 1839 static int discard_f(BlockBackend *blk, int argc, char **argv) 1840 { 1841 struct timeval t1, t2; 1842 int Cflag = 0, qflag = 0; 1843 int c, ret; 1844 int64_t offset, count; 1845 1846 while ((c = getopt(argc, argv, "Cq")) != -1) { 1847 switch (c) { 1848 case 'C': 1849 Cflag = 1; 1850 break; 1851 case 'q': 1852 qflag = 1; 1853 break; 1854 default: 1855 return qemuio_command_usage(&discard_cmd); 1856 } 1857 } 1858 1859 if (optind != argc - 2) { 1860 return qemuio_command_usage(&discard_cmd); 1861 } 1862 1863 offset = cvtnum(argv[optind]); 1864 if (offset < 0) { 1865 print_cvtnum_err(offset, argv[optind]); 1866 return 0; 1867 } 1868 1869 optind++; 1870 count = cvtnum(argv[optind]); 1871 if (count < 0) { 1872 print_cvtnum_err(count, argv[optind]); 1873 return 0; 1874 } else if (count >> BDRV_SECTOR_BITS > INT_MAX) { 1875 printf("length cannot exceed %"PRIu64", given %s\n", 1876 (uint64_t)INT_MAX << BDRV_SECTOR_BITS, 1877 argv[optind]); 1878 return 0; 1879 } 1880 1881 gettimeofday(&t1, NULL); 1882 ret = blk_discard(blk, offset >> BDRV_SECTOR_BITS, 1883 count >> BDRV_SECTOR_BITS); 1884 gettimeofday(&t2, NULL); 1885 1886 if (ret < 0) { 1887 printf("discard failed: %s\n", strerror(-ret)); 1888 goto out; 1889 } 1890 1891 /* Finally, report back -- -C gives a parsable format */ 1892 if (!qflag) { 1893 t2 = tsub(t2, t1); 1894 print_report("discard", &t2, offset, count, count, 1, Cflag); 1895 } 1896 1897 out: 1898 return 0; 1899 } 1900 1901 static int alloc_f(BlockBackend *blk, int argc, char **argv) 1902 { 1903 BlockDriverState *bs = blk_bs(blk); 1904 int64_t offset, sector_num, nb_sectors, remaining; 1905 char s1[64]; 1906 int num, ret; 1907 int64_t sum_alloc; 1908 1909 offset = cvtnum(argv[1]); 1910 if (offset < 0) { 1911 print_cvtnum_err(offset, argv[1]); 1912 return 0; 1913 } else if (offset & 0x1ff) { 1914 printf("offset %" PRId64 " is not sector aligned\n", 1915 offset); 1916 return 0; 1917 } 1918 1919 if (argc == 3) { 1920 nb_sectors = cvtnum(argv[2]); 1921 if (nb_sectors < 0) { 1922 print_cvtnum_err(nb_sectors, argv[2]); 1923 return 0; 1924 } else if (nb_sectors > INT_MAX) { 1925 printf("length argument cannot exceed %d, given %s\n", 1926 INT_MAX, argv[2]); 1927 return 0; 1928 } 1929 } else { 1930 nb_sectors = 1; 1931 } 1932 1933 remaining = nb_sectors; 1934 sum_alloc = 0; 1935 sector_num = offset >> 9; 1936 while (remaining) { 1937 ret = bdrv_is_allocated(bs, sector_num, remaining, &num); 1938 if (ret < 0) { 1939 printf("is_allocated failed: %s\n", strerror(-ret)); 1940 return 0; 1941 } 1942 sector_num += num; 1943 remaining -= num; 1944 if (ret) { 1945 sum_alloc += num; 1946 } 1947 if (num == 0) { 1948 nb_sectors -= remaining; 1949 remaining = 0; 1950 } 1951 } 1952 1953 cvtstr(offset, s1, sizeof(s1)); 1954 1955 printf("%"PRId64"/%"PRId64" sectors allocated at offset %s\n", 1956 sum_alloc, nb_sectors, s1); 1957 return 0; 1958 } 1959 1960 static const cmdinfo_t alloc_cmd = { 1961 .name = "alloc", 1962 .altname = "a", 1963 .argmin = 1, 1964 .argmax = 2, 1965 .cfunc = alloc_f, 1966 .args = "off [sectors]", 1967 .oneline = "checks if a sector is present in the file", 1968 }; 1969 1970 1971 static int map_is_allocated(BlockDriverState *bs, int64_t sector_num, 1972 int64_t nb_sectors, int64_t *pnum) 1973 { 1974 int num, num_checked; 1975 int ret, firstret; 1976 1977 num_checked = MIN(nb_sectors, INT_MAX); 1978 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num); 1979 if (ret < 0) { 1980 return ret; 1981 } 1982 1983 firstret = ret; 1984 *pnum = num; 1985 1986 while (nb_sectors > 0 && ret == firstret) { 1987 sector_num += num; 1988 nb_sectors -= num; 1989 1990 num_checked = MIN(nb_sectors, INT_MAX); 1991 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num); 1992 if (ret == firstret && num) { 1993 *pnum += num; 1994 } else { 1995 break; 1996 } 1997 } 1998 1999 return firstret; 2000 } 2001 2002 static int map_f(BlockBackend *blk, int argc, char **argv) 2003 { 2004 int64_t offset; 2005 int64_t nb_sectors, total_sectors; 2006 char s1[64]; 2007 int64_t num; 2008 int ret; 2009 const char *retstr; 2010 2011 offset = 0; 2012 total_sectors = blk_nb_sectors(blk); 2013 if (total_sectors < 0) { 2014 error_report("Failed to query image length: %s", 2015 strerror(-total_sectors)); 2016 return 0; 2017 } 2018 2019 nb_sectors = total_sectors; 2020 2021 do { 2022 ret = map_is_allocated(blk_bs(blk), offset, nb_sectors, &num); 2023 if (ret < 0) { 2024 error_report("Failed to get allocation status: %s", strerror(-ret)); 2025 return 0; 2026 } else if (!num) { 2027 error_report("Unexpected end of image"); 2028 return 0; 2029 } 2030 2031 retstr = ret ? " allocated" : "not allocated"; 2032 cvtstr(offset << 9ULL, s1, sizeof(s1)); 2033 printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s " 2034 "at offset %s (%d)\n", 2035 offset << 9ULL, num, nb_sectors, retstr, s1, ret); 2036 2037 offset += num; 2038 nb_sectors -= num; 2039 } while (offset < total_sectors); 2040 2041 return 0; 2042 } 2043 2044 static const cmdinfo_t map_cmd = { 2045 .name = "map", 2046 .argmin = 0, 2047 .argmax = 0, 2048 .cfunc = map_f, 2049 .args = "", 2050 .oneline = "prints the allocated areas of a file", 2051 }; 2052 2053 static void reopen_help(void) 2054 { 2055 printf( 2056 "\n" 2057 " Changes the open options of an already opened image\n" 2058 "\n" 2059 " Example:\n" 2060 " 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n" 2061 "\n" 2062 " -r, -- Reopen the image read-only\n" 2063 " -c, -- Change the cache mode to the given value\n" 2064 " -o, -- Changes block driver options (cf. 'open' command)\n" 2065 "\n"); 2066 } 2067 2068 static int reopen_f(BlockBackend *blk, int argc, char **argv); 2069 2070 static QemuOptsList reopen_opts = { 2071 .name = "reopen", 2072 .merge_lists = true, 2073 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head), 2074 .desc = { 2075 /* no elements => accept any params */ 2076 { /* end of list */ } 2077 }, 2078 }; 2079 2080 static const cmdinfo_t reopen_cmd = { 2081 .name = "reopen", 2082 .argmin = 0, 2083 .argmax = -1, 2084 .cfunc = reopen_f, 2085 .args = "[-r] [-c cache] [-o options]", 2086 .oneline = "reopens an image with new options", 2087 .help = reopen_help, 2088 }; 2089 2090 static int reopen_f(BlockBackend *blk, int argc, char **argv) 2091 { 2092 BlockDriverState *bs = blk_bs(blk); 2093 QemuOpts *qopts; 2094 QDict *opts; 2095 int c; 2096 int flags = bs->open_flags; 2097 2098 BlockReopenQueue *brq; 2099 Error *local_err = NULL; 2100 2101 while ((c = getopt(argc, argv, "c:o:r")) != -1) { 2102 switch (c) { 2103 case 'c': 2104 if (bdrv_parse_cache_flags(optarg, &flags) < 0) { 2105 error_report("Invalid cache option: %s", optarg); 2106 return 0; 2107 } 2108 break; 2109 case 'o': 2110 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) { 2111 qemu_opts_reset(&reopen_opts); 2112 return 0; 2113 } 2114 break; 2115 case 'r': 2116 flags &= ~BDRV_O_RDWR; 2117 break; 2118 default: 2119 qemu_opts_reset(&reopen_opts); 2120 return qemuio_command_usage(&reopen_cmd); 2121 } 2122 } 2123 2124 if (optind != argc) { 2125 qemu_opts_reset(&reopen_opts); 2126 return qemuio_command_usage(&reopen_cmd); 2127 } 2128 2129 qopts = qemu_opts_find(&reopen_opts, NULL); 2130 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL; 2131 qemu_opts_reset(&reopen_opts); 2132 2133 brq = bdrv_reopen_queue(NULL, bs, opts, flags); 2134 bdrv_reopen_multiple(brq, &local_err); 2135 if (local_err) { 2136 error_report_err(local_err); 2137 } 2138 2139 return 0; 2140 } 2141 2142 static int break_f(BlockBackend *blk, int argc, char **argv) 2143 { 2144 int ret; 2145 2146 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]); 2147 if (ret < 0) { 2148 printf("Could not set breakpoint: %s\n", strerror(-ret)); 2149 } 2150 2151 return 0; 2152 } 2153 2154 static int remove_break_f(BlockBackend *blk, int argc, char **argv) 2155 { 2156 int ret; 2157 2158 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]); 2159 if (ret < 0) { 2160 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret)); 2161 } 2162 2163 return 0; 2164 } 2165 2166 static const cmdinfo_t break_cmd = { 2167 .name = "break", 2168 .argmin = 2, 2169 .argmax = 2, 2170 .cfunc = break_f, 2171 .args = "event tag", 2172 .oneline = "sets a breakpoint on event and tags the stopped " 2173 "request as tag", 2174 }; 2175 2176 static const cmdinfo_t remove_break_cmd = { 2177 .name = "remove_break", 2178 .argmin = 1, 2179 .argmax = 1, 2180 .cfunc = remove_break_f, 2181 .args = "tag", 2182 .oneline = "remove a breakpoint by tag", 2183 }; 2184 2185 static int resume_f(BlockBackend *blk, int argc, char **argv) 2186 { 2187 int ret; 2188 2189 ret = bdrv_debug_resume(blk_bs(blk), argv[1]); 2190 if (ret < 0) { 2191 printf("Could not resume request: %s\n", strerror(-ret)); 2192 } 2193 2194 return 0; 2195 } 2196 2197 static const cmdinfo_t resume_cmd = { 2198 .name = "resume", 2199 .argmin = 1, 2200 .argmax = 1, 2201 .cfunc = resume_f, 2202 .args = "tag", 2203 .oneline = "resumes the request tagged as tag", 2204 }; 2205 2206 static int wait_break_f(BlockBackend *blk, int argc, char **argv) 2207 { 2208 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) { 2209 aio_poll(blk_get_aio_context(blk), true); 2210 } 2211 2212 return 0; 2213 } 2214 2215 static const cmdinfo_t wait_break_cmd = { 2216 .name = "wait_break", 2217 .argmin = 1, 2218 .argmax = 1, 2219 .cfunc = wait_break_f, 2220 .args = "tag", 2221 .oneline = "waits for the suspension of a request", 2222 }; 2223 2224 static int abort_f(BlockBackend *blk, int argc, char **argv) 2225 { 2226 abort(); 2227 } 2228 2229 static const cmdinfo_t abort_cmd = { 2230 .name = "abort", 2231 .cfunc = abort_f, 2232 .flags = CMD_NOFILE_OK, 2233 .oneline = "simulate a program crash using abort(3)", 2234 }; 2235 2236 static void sigraise_help(void) 2237 { 2238 printf( 2239 "\n" 2240 " raises the given signal\n" 2241 "\n" 2242 " Example:\n" 2243 " 'sigraise %i' - raises SIGTERM\n" 2244 "\n" 2245 " Invokes raise(signal), where \"signal\" is the mandatory integer argument\n" 2246 " given to sigraise.\n" 2247 "\n", SIGTERM); 2248 } 2249 2250 static int sigraise_f(BlockBackend *blk, int argc, char **argv); 2251 2252 static const cmdinfo_t sigraise_cmd = { 2253 .name = "sigraise", 2254 .cfunc = sigraise_f, 2255 .argmin = 1, 2256 .argmax = 1, 2257 .flags = CMD_NOFILE_OK, 2258 .args = "signal", 2259 .oneline = "raises a signal", 2260 .help = sigraise_help, 2261 }; 2262 2263 static int sigraise_f(BlockBackend *blk, int argc, char **argv) 2264 { 2265 int64_t sig = cvtnum(argv[1]); 2266 if (sig < 0) { 2267 print_cvtnum_err(sig, argv[1]); 2268 return 0; 2269 } else if (sig > NSIG) { 2270 printf("signal argument '%s' is too large to be a valid signal\n", 2271 argv[1]); 2272 return 0; 2273 } 2274 2275 /* Using raise() to kill this process does not necessarily flush all open 2276 * streams. At least stdout and stderr (although the latter should be 2277 * non-buffered anyway) should be flushed, though. */ 2278 fflush(stdout); 2279 fflush(stderr); 2280 2281 raise(sig); 2282 return 0; 2283 } 2284 2285 static void sleep_cb(void *opaque) 2286 { 2287 bool *expired = opaque; 2288 *expired = true; 2289 } 2290 2291 static int sleep_f(BlockBackend *blk, int argc, char **argv) 2292 { 2293 char *endptr; 2294 long ms; 2295 struct QEMUTimer *timer; 2296 bool expired = false; 2297 2298 ms = strtol(argv[1], &endptr, 0); 2299 if (ms < 0 || *endptr != '\0') { 2300 printf("%s is not a valid number\n", argv[1]); 2301 return 0; 2302 } 2303 2304 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired); 2305 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms); 2306 2307 while (!expired) { 2308 main_loop_wait(false); 2309 } 2310 2311 timer_free(timer); 2312 2313 return 0; 2314 } 2315 2316 static const cmdinfo_t sleep_cmd = { 2317 .name = "sleep", 2318 .argmin = 1, 2319 .argmax = 1, 2320 .cfunc = sleep_f, 2321 .flags = CMD_NOFILE_OK, 2322 .oneline = "waits for the given value in milliseconds", 2323 }; 2324 2325 static void help_oneline(const char *cmd, const cmdinfo_t *ct) 2326 { 2327 if (cmd) { 2328 printf("%s ", cmd); 2329 } else { 2330 printf("%s ", ct->name); 2331 if (ct->altname) { 2332 printf("(or %s) ", ct->altname); 2333 } 2334 } 2335 2336 if (ct->args) { 2337 printf("%s ", ct->args); 2338 } 2339 printf("-- %s\n", ct->oneline); 2340 } 2341 2342 static void help_onecmd(const char *cmd, const cmdinfo_t *ct) 2343 { 2344 help_oneline(cmd, ct); 2345 if (ct->help) { 2346 ct->help(); 2347 } 2348 } 2349 2350 static void help_all(void) 2351 { 2352 const cmdinfo_t *ct; 2353 2354 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) { 2355 help_oneline(ct->name, ct); 2356 } 2357 printf("\nUse 'help commandname' for extended help.\n"); 2358 } 2359 2360 static int help_f(BlockBackend *blk, int argc, char **argv) 2361 { 2362 const cmdinfo_t *ct; 2363 2364 if (argc == 1) { 2365 help_all(); 2366 return 0; 2367 } 2368 2369 ct = find_command(argv[1]); 2370 if (ct == NULL) { 2371 printf("command %s not found\n", argv[1]); 2372 return 0; 2373 } 2374 2375 help_onecmd(argv[1], ct); 2376 return 0; 2377 } 2378 2379 static const cmdinfo_t help_cmd = { 2380 .name = "help", 2381 .altname = "?", 2382 .cfunc = help_f, 2383 .argmin = 0, 2384 .argmax = 1, 2385 .flags = CMD_FLAG_GLOBAL, 2386 .args = "[command]", 2387 .oneline = "help for one or all commands", 2388 }; 2389 2390 bool qemuio_command(BlockBackend *blk, const char *cmd) 2391 { 2392 char *input; 2393 const cmdinfo_t *ct; 2394 char **v; 2395 int c; 2396 bool done = false; 2397 2398 input = g_strdup(cmd); 2399 v = breakline(input, &c); 2400 if (c) { 2401 ct = find_command(v[0]); 2402 if (ct) { 2403 done = command(blk, ct, c, v); 2404 } else { 2405 fprintf(stderr, "command \"%s\" not found\n", v[0]); 2406 } 2407 } 2408 g_free(input); 2409 g_free(v); 2410 2411 return done; 2412 } 2413 2414 static void __attribute((constructor)) init_qemuio_commands(void) 2415 { 2416 /* initialize commands */ 2417 qemuio_add_command(&help_cmd); 2418 qemuio_add_command(&read_cmd); 2419 qemuio_add_command(&readv_cmd); 2420 qemuio_add_command(&write_cmd); 2421 qemuio_add_command(&writev_cmd); 2422 qemuio_add_command(&multiwrite_cmd); 2423 qemuio_add_command(&aio_read_cmd); 2424 qemuio_add_command(&aio_write_cmd); 2425 qemuio_add_command(&aio_flush_cmd); 2426 qemuio_add_command(&flush_cmd); 2427 qemuio_add_command(&truncate_cmd); 2428 qemuio_add_command(&length_cmd); 2429 qemuio_add_command(&info_cmd); 2430 qemuio_add_command(&discard_cmd); 2431 qemuio_add_command(&alloc_cmd); 2432 qemuio_add_command(&map_cmd); 2433 qemuio_add_command(&reopen_cmd); 2434 qemuio_add_command(&break_cmd); 2435 qemuio_add_command(&remove_break_cmd); 2436 qemuio_add_command(&resume_cmd); 2437 qemuio_add_command(&wait_break_cmd); 2438 qemuio_add_command(&abort_cmd); 2439 qemuio_add_command(&sleep_cmd); 2440 qemuio_add_command(&sigraise_cmd); 2441 } 2442