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