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 "qapi/qmp/qdict.h" 14 #include "qemu-io.h" 15 #include "sysemu/block-backend.h" 16 #include "block/block.h" 17 #include "block/block_int.h" /* for info_f() */ 18 #include "block/qapi.h" 19 #include "qemu/error-report.h" 20 #include "qemu/main-loop.h" 21 #include "qemu/option.h" 22 #include "qemu/timer.h" 23 #include "qemu/cutils.h" 24 25 #define CMD_NOFILE_OK 0x01 26 27 bool qemuio_misalign; 28 29 static cmdinfo_t *cmdtab; 30 static int ncmds; 31 32 static int compare_cmdname(const void *a, const void *b) 33 { 34 return strcmp(((const cmdinfo_t *)a)->name, 35 ((const cmdinfo_t *)b)->name); 36 } 37 38 void qemuio_add_command(const cmdinfo_t *ci) 39 { 40 /* ci->perm assumes a file is open, but the GLOBAL and NOFILE_OK 41 * flags allow it not to be, so that combination is invalid. 42 * Catch it now rather than letting it manifest as a crash if a 43 * particular set of command line options are used. 44 */ 45 assert(ci->perm == 0 || 46 (ci->flags & (CMD_FLAG_GLOBAL | CMD_NOFILE_OK)) == 0); 47 cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds); 48 cmdtab[ncmds - 1] = *ci; 49 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname); 50 } 51 52 void qemuio_command_usage(const cmdinfo_t *ci) 53 { 54 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline); 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 -EINVAL; 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 -EINVAL; 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 ret; 113 } 114 } 115 } 116 117 qemu_reset_optind(); 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 > BDRV_REQUEST_MAX_BYTES) { 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, ret; 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 pattern_count; 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 -EINVAL; 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 pattern_offset; 699 } 700 break; 701 case 'v': 702 vflag = true; 703 break; 704 default: 705 qemuio_command_usage(&read_cmd); 706 return -EINVAL; 707 } 708 } 709 710 if (optind != argc - 2) { 711 qemuio_command_usage(&read_cmd); 712 return -EINVAL; 713 } 714 715 offset = cvtnum(argv[optind]); 716 if (offset < 0) { 717 print_cvtnum_err(offset, argv[optind]); 718 return offset; 719 } 720 721 optind++; 722 count = cvtnum(argv[optind]); 723 if (count < 0) { 724 print_cvtnum_err(count, argv[optind]); 725 return count; 726 } else if (count > BDRV_REQUEST_MAX_BYTES) { 727 printf("length cannot exceed %" PRIu64 ", given %s\n", 728 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]); 729 return -EINVAL; 730 } 731 732 if (!Pflag && (lflag || sflag)) { 733 qemuio_command_usage(&read_cmd); 734 return -EINVAL; 735 } 736 737 if (!lflag) { 738 pattern_count = count - pattern_offset; 739 } 740 741 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 742 printf("pattern verification range exceeds end of read data\n"); 743 return -EINVAL; 744 } 745 746 if (bflag) { 747 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) { 748 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n", 749 offset); 750 return -EINVAL; 751 } 752 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) { 753 printf("%"PRId64" is not a sector-aligned value for 'count'\n", 754 count); 755 return -EINVAL; 756 } 757 } 758 759 buf = qemu_io_alloc(blk, count, 0xab); 760 761 gettimeofday(&t1, NULL); 762 if (bflag) { 763 ret = do_load_vmstate(blk, buf, offset, count, &total); 764 } else { 765 ret = do_pread(blk, buf, offset, count, &total); 766 } 767 gettimeofday(&t2, NULL); 768 769 if (ret < 0) { 770 printf("read failed: %s\n", strerror(-ret)); 771 goto out; 772 } 773 cnt = ret; 774 775 ret = 0; 776 777 if (Pflag) { 778 void *cmp_buf = g_malloc(pattern_count); 779 memset(cmp_buf, pattern, pattern_count); 780 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 781 printf("Pattern verification failed at offset %" 782 PRId64 ", %"PRId64" bytes\n", 783 offset + pattern_offset, pattern_count); 784 ret = -EINVAL; 785 } 786 g_free(cmp_buf); 787 } 788 789 if (qflag) { 790 goto out; 791 } 792 793 if (vflag) { 794 dump_buffer(buf, offset, count); 795 } 796 797 /* Finally, report back -- -C gives a parsable format */ 798 t2 = tsub(t2, t1); 799 print_report("read", &t2, offset, count, total, cnt, Cflag); 800 801 out: 802 qemu_io_free(buf); 803 return ret; 804 } 805 806 static void readv_help(void) 807 { 808 printf( 809 "\n" 810 " reads a range of bytes from the given offset into multiple buffers\n" 811 "\n" 812 " Example:\n" 813 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 814 "\n" 815 " Reads a segment of the currently open file, optionally dumping it to the\n" 816 " standard output stream (with -v option) for subsequent inspection.\n" 817 " Uses multiple iovec buffers if more than one byte range is specified.\n" 818 " -C, -- report statistics in a machine parsable format\n" 819 " -P, -- use a pattern to verify read data\n" 820 " -v, -- dump buffer to standard output\n" 821 " -q, -- quiet mode, do not show I/O statistics\n" 822 "\n"); 823 } 824 825 static int readv_f(BlockBackend *blk, int argc, char **argv); 826 827 static const cmdinfo_t readv_cmd = { 828 .name = "readv", 829 .cfunc = readv_f, 830 .argmin = 2, 831 .argmax = -1, 832 .args = "[-Cqv] [-P pattern] off len [len..]", 833 .oneline = "reads a number of bytes at a specified offset", 834 .help = readv_help, 835 }; 836 837 static int readv_f(BlockBackend *blk, int argc, char **argv) 838 { 839 struct timeval t1, t2; 840 bool Cflag = false, qflag = false, vflag = false; 841 int c, cnt, ret; 842 char *buf; 843 int64_t offset; 844 /* Some compilers get confused and warn if this is not initialized. */ 845 int total = 0; 846 int nr_iov; 847 QEMUIOVector qiov; 848 int pattern = 0; 849 bool Pflag = false; 850 851 while ((c = getopt(argc, argv, "CP:qv")) != -1) { 852 switch (c) { 853 case 'C': 854 Cflag = true; 855 break; 856 case 'P': 857 Pflag = true; 858 pattern = parse_pattern(optarg); 859 if (pattern < 0) { 860 return -EINVAL; 861 } 862 break; 863 case 'q': 864 qflag = true; 865 break; 866 case 'v': 867 vflag = true; 868 break; 869 default: 870 qemuio_command_usage(&readv_cmd); 871 return -EINVAL; 872 } 873 } 874 875 if (optind > argc - 2) { 876 qemuio_command_usage(&readv_cmd); 877 return -EINVAL; 878 } 879 880 881 offset = cvtnum(argv[optind]); 882 if (offset < 0) { 883 print_cvtnum_err(offset, argv[optind]); 884 return offset; 885 } 886 optind++; 887 888 nr_iov = argc - optind; 889 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab); 890 if (buf == NULL) { 891 return -EINVAL; 892 } 893 894 gettimeofday(&t1, NULL); 895 ret = do_aio_readv(blk, &qiov, offset, &total); 896 gettimeofday(&t2, NULL); 897 898 if (ret < 0) { 899 printf("readv failed: %s\n", strerror(-ret)); 900 goto out; 901 } 902 cnt = ret; 903 904 ret = 0; 905 906 if (Pflag) { 907 void *cmp_buf = g_malloc(qiov.size); 908 memset(cmp_buf, pattern, qiov.size); 909 if (memcmp(buf, cmp_buf, qiov.size)) { 910 printf("Pattern verification failed at offset %" 911 PRId64 ", %zu bytes\n", offset, qiov.size); 912 ret = -EINVAL; 913 } 914 g_free(cmp_buf); 915 } 916 917 if (qflag) { 918 goto out; 919 } 920 921 if (vflag) { 922 dump_buffer(buf, offset, qiov.size); 923 } 924 925 /* Finally, report back -- -C gives a parsable format */ 926 t2 = tsub(t2, t1); 927 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 928 929 out: 930 qemu_iovec_destroy(&qiov); 931 qemu_io_free(buf); 932 return ret; 933 } 934 935 static void write_help(void) 936 { 937 printf( 938 "\n" 939 " writes a range of bytes from the given offset\n" 940 "\n" 941 " Example:\n" 942 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 943 "\n" 944 " Writes into a segment of the currently open file, using a buffer\n" 945 " filled with a set pattern (0xcdcdcdcd).\n" 946 " -b, -- write to the VM state rather than the virtual disk\n" 947 " -c, -- write compressed data with blk_write_compressed\n" 948 " -f, -- use Force Unit Access semantics\n" 949 " -n, -- with -z, don't allow slow fallback\n" 950 " -p, -- ignored for backwards compatibility\n" 951 " -P, -- use different pattern to fill file\n" 952 " -C, -- report statistics in a machine parsable format\n" 953 " -q, -- quiet mode, do not show I/O statistics\n" 954 " -u, -- with -z, allow unmapping\n" 955 " -z, -- write zeroes using blk_co_pwrite_zeroes\n" 956 "\n"); 957 } 958 959 static int write_f(BlockBackend *blk, int argc, char **argv); 960 961 static const cmdinfo_t write_cmd = { 962 .name = "write", 963 .altname = "w", 964 .cfunc = write_f, 965 .perm = BLK_PERM_WRITE, 966 .argmin = 2, 967 .argmax = -1, 968 .args = "[-bcCfnquz] [-P pattern] off len", 969 .oneline = "writes a number of bytes at a specified offset", 970 .help = write_help, 971 }; 972 973 static int write_f(BlockBackend *blk, int argc, char **argv) 974 { 975 struct timeval t1, t2; 976 bool Cflag = false, qflag = false, bflag = false; 977 bool Pflag = false, zflag = false, cflag = false; 978 int flags = 0; 979 int c, cnt, ret; 980 char *buf = NULL; 981 int64_t offset; 982 int64_t count; 983 /* Some compilers get confused and warn if this is not initialized. */ 984 int64_t total = 0; 985 int pattern = 0xcd; 986 987 while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) { 988 switch (c) { 989 case 'b': 990 bflag = true; 991 break; 992 case 'c': 993 cflag = true; 994 break; 995 case 'C': 996 Cflag = true; 997 break; 998 case 'f': 999 flags |= BDRV_REQ_FUA; 1000 break; 1001 case 'n': 1002 flags |= BDRV_REQ_NO_FALLBACK; 1003 break; 1004 case 'p': 1005 /* Ignored for backwards compatibility */ 1006 break; 1007 case 'P': 1008 Pflag = true; 1009 pattern = parse_pattern(optarg); 1010 if (pattern < 0) { 1011 return -EINVAL; 1012 } 1013 break; 1014 case 'q': 1015 qflag = true; 1016 break; 1017 case 'u': 1018 flags |= BDRV_REQ_MAY_UNMAP; 1019 break; 1020 case 'z': 1021 zflag = true; 1022 break; 1023 default: 1024 qemuio_command_usage(&write_cmd); 1025 return -EINVAL; 1026 } 1027 } 1028 1029 if (optind != argc - 2) { 1030 qemuio_command_usage(&write_cmd); 1031 return -EINVAL; 1032 } 1033 1034 if (bflag && zflag) { 1035 printf("-b and -z cannot be specified at the same time\n"); 1036 return -EINVAL; 1037 } 1038 1039 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) { 1040 printf("-f and -b or -c cannot be specified at the same time\n"); 1041 return -EINVAL; 1042 } 1043 1044 if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) { 1045 printf("-n requires -z to be specified\n"); 1046 return -EINVAL; 1047 } 1048 1049 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) { 1050 printf("-u requires -z to be specified\n"); 1051 return -EINVAL; 1052 } 1053 1054 if (zflag && Pflag) { 1055 printf("-z and -P cannot be specified at the same time\n"); 1056 return -EINVAL; 1057 } 1058 1059 offset = cvtnum(argv[optind]); 1060 if (offset < 0) { 1061 print_cvtnum_err(offset, argv[optind]); 1062 return offset; 1063 } 1064 1065 optind++; 1066 count = cvtnum(argv[optind]); 1067 if (count < 0) { 1068 print_cvtnum_err(count, argv[optind]); 1069 return count; 1070 } else if (count > BDRV_REQUEST_MAX_BYTES) { 1071 printf("length cannot exceed %" PRIu64 ", given %s\n", 1072 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]); 1073 return -EINVAL; 1074 } 1075 1076 if (bflag || cflag) { 1077 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) { 1078 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n", 1079 offset); 1080 return -EINVAL; 1081 } 1082 1083 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) { 1084 printf("%"PRId64" is not a sector-aligned value for 'count'\n", 1085 count); 1086 return -EINVAL; 1087 } 1088 } 1089 1090 if (!zflag) { 1091 buf = qemu_io_alloc(blk, count, pattern); 1092 } 1093 1094 gettimeofday(&t1, NULL); 1095 if (bflag) { 1096 ret = do_save_vmstate(blk, buf, offset, count, &total); 1097 } else if (zflag) { 1098 ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total); 1099 } else if (cflag) { 1100 ret = do_write_compressed(blk, buf, offset, count, &total); 1101 } else { 1102 ret = do_pwrite(blk, buf, offset, count, flags, &total); 1103 } 1104 gettimeofday(&t2, NULL); 1105 1106 if (ret < 0) { 1107 printf("write failed: %s\n", strerror(-ret)); 1108 goto out; 1109 } 1110 cnt = ret; 1111 1112 ret = 0; 1113 1114 if (qflag) { 1115 goto out; 1116 } 1117 1118 /* Finally, report back -- -C gives a parsable format */ 1119 t2 = tsub(t2, t1); 1120 print_report("wrote", &t2, offset, count, total, cnt, Cflag); 1121 1122 out: 1123 if (!zflag) { 1124 qemu_io_free(buf); 1125 } 1126 return ret; 1127 } 1128 1129 static void 1130 writev_help(void) 1131 { 1132 printf( 1133 "\n" 1134 " writes a range of bytes from the given offset source from multiple buffers\n" 1135 "\n" 1136 " Example:\n" 1137 " 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1138 "\n" 1139 " Writes into a segment of the currently open file, using a buffer\n" 1140 " filled with a set pattern (0xcdcdcdcd).\n" 1141 " -P, -- use different pattern to fill file\n" 1142 " -C, -- report statistics in a machine parsable format\n" 1143 " -f, -- use Force Unit Access semantics\n" 1144 " -q, -- quiet mode, do not show I/O statistics\n" 1145 "\n"); 1146 } 1147 1148 static int writev_f(BlockBackend *blk, int argc, char **argv); 1149 1150 static const cmdinfo_t writev_cmd = { 1151 .name = "writev", 1152 .cfunc = writev_f, 1153 .perm = BLK_PERM_WRITE, 1154 .argmin = 2, 1155 .argmax = -1, 1156 .args = "[-Cfq] [-P pattern] off len [len..]", 1157 .oneline = "writes a number of bytes at a specified offset", 1158 .help = writev_help, 1159 }; 1160 1161 static int writev_f(BlockBackend *blk, int argc, char **argv) 1162 { 1163 struct timeval t1, t2; 1164 bool Cflag = false, qflag = false; 1165 int flags = 0; 1166 int c, cnt, ret; 1167 char *buf; 1168 int64_t offset; 1169 /* Some compilers get confused and warn if this is not initialized. */ 1170 int total = 0; 1171 int nr_iov; 1172 int pattern = 0xcd; 1173 QEMUIOVector qiov; 1174 1175 while ((c = getopt(argc, argv, "CfqP:")) != -1) { 1176 switch (c) { 1177 case 'C': 1178 Cflag = true; 1179 break; 1180 case 'f': 1181 flags |= BDRV_REQ_FUA; 1182 break; 1183 case 'q': 1184 qflag = true; 1185 break; 1186 case 'P': 1187 pattern = parse_pattern(optarg); 1188 if (pattern < 0) { 1189 return -EINVAL; 1190 } 1191 break; 1192 default: 1193 qemuio_command_usage(&writev_cmd); 1194 return -EINVAL; 1195 } 1196 } 1197 1198 if (optind > argc - 2) { 1199 qemuio_command_usage(&writev_cmd); 1200 return -EINVAL; 1201 } 1202 1203 offset = cvtnum(argv[optind]); 1204 if (offset < 0) { 1205 print_cvtnum_err(offset, argv[optind]); 1206 return offset; 1207 } 1208 optind++; 1209 1210 nr_iov = argc - optind; 1211 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern); 1212 if (buf == NULL) { 1213 return -EINVAL; 1214 } 1215 1216 gettimeofday(&t1, NULL); 1217 ret = do_aio_writev(blk, &qiov, offset, flags, &total); 1218 gettimeofday(&t2, NULL); 1219 1220 if (ret < 0) { 1221 printf("writev failed: %s\n", strerror(-ret)); 1222 goto out; 1223 } 1224 cnt = ret; 1225 1226 ret = 0; 1227 1228 if (qflag) { 1229 goto out; 1230 } 1231 1232 /* Finally, report back -- -C gives a parsable format */ 1233 t2 = tsub(t2, t1); 1234 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 1235 out: 1236 qemu_iovec_destroy(&qiov); 1237 qemu_io_free(buf); 1238 return ret; 1239 } 1240 1241 struct aio_ctx { 1242 BlockBackend *blk; 1243 QEMUIOVector qiov; 1244 int64_t offset; 1245 char *buf; 1246 bool qflag; 1247 bool vflag; 1248 bool Cflag; 1249 bool Pflag; 1250 bool zflag; 1251 BlockAcctCookie acct; 1252 int pattern; 1253 struct timeval t1; 1254 }; 1255 1256 static void aio_write_done(void *opaque, int ret) 1257 { 1258 struct aio_ctx *ctx = opaque; 1259 struct timeval t2; 1260 1261 gettimeofday(&t2, NULL); 1262 1263 1264 if (ret < 0) { 1265 printf("aio_write failed: %s\n", strerror(-ret)); 1266 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct); 1267 goto out; 1268 } 1269 1270 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct); 1271 1272 if (ctx->qflag) { 1273 goto out; 1274 } 1275 1276 /* Finally, report back -- -C gives a parsable format */ 1277 t2 = tsub(t2, ctx->t1); 1278 print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1279 ctx->qiov.size, 1, ctx->Cflag); 1280 out: 1281 if (!ctx->zflag) { 1282 qemu_io_free(ctx->buf); 1283 qemu_iovec_destroy(&ctx->qiov); 1284 } 1285 g_free(ctx); 1286 } 1287 1288 static void aio_read_done(void *opaque, int ret) 1289 { 1290 struct aio_ctx *ctx = opaque; 1291 struct timeval t2; 1292 1293 gettimeofday(&t2, NULL); 1294 1295 if (ret < 0) { 1296 printf("readv failed: %s\n", strerror(-ret)); 1297 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct); 1298 goto out; 1299 } 1300 1301 if (ctx->Pflag) { 1302 void *cmp_buf = g_malloc(ctx->qiov.size); 1303 1304 memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1305 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 1306 printf("Pattern verification failed at offset %" 1307 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size); 1308 } 1309 g_free(cmp_buf); 1310 } 1311 1312 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct); 1313 1314 if (ctx->qflag) { 1315 goto out; 1316 } 1317 1318 if (ctx->vflag) { 1319 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1320 } 1321 1322 /* Finally, report back -- -C gives a parsable format */ 1323 t2 = tsub(t2, ctx->t1); 1324 print_report("read", &t2, ctx->offset, ctx->qiov.size, 1325 ctx->qiov.size, 1, ctx->Cflag); 1326 out: 1327 qemu_io_free(ctx->buf); 1328 qemu_iovec_destroy(&ctx->qiov); 1329 g_free(ctx); 1330 } 1331 1332 static void aio_read_help(void) 1333 { 1334 printf( 1335 "\n" 1336 " asynchronously reads a range of bytes from the given offset\n" 1337 "\n" 1338 " Example:\n" 1339 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 1340 "\n" 1341 " Reads a segment of the currently open file, optionally dumping it to the\n" 1342 " standard output stream (with -v option) for subsequent inspection.\n" 1343 " The read is performed asynchronously and the aio_flush command must be\n" 1344 " used to ensure all outstanding aio requests have been completed.\n" 1345 " Note that due to its asynchronous nature, this command will be\n" 1346 " considered successful once the request is submitted, independently\n" 1347 " of potential I/O errors or pattern mismatches.\n" 1348 " -C, -- report statistics in a machine parsable format\n" 1349 " -P, -- use a pattern to verify read data\n" 1350 " -i, -- treat request as invalid, for exercising stats\n" 1351 " -v, -- dump buffer to standard output\n" 1352 " -q, -- quiet mode, do not show I/O statistics\n" 1353 "\n"); 1354 } 1355 1356 static int aio_read_f(BlockBackend *blk, int argc, char **argv); 1357 1358 static const cmdinfo_t aio_read_cmd = { 1359 .name = "aio_read", 1360 .cfunc = aio_read_f, 1361 .argmin = 2, 1362 .argmax = -1, 1363 .args = "[-Ciqv] [-P pattern] off len [len..]", 1364 .oneline = "asynchronously reads a number of bytes", 1365 .help = aio_read_help, 1366 }; 1367 1368 static int aio_read_f(BlockBackend *blk, int argc, char **argv) 1369 { 1370 int nr_iov, c; 1371 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1372 1373 ctx->blk = blk; 1374 while ((c = getopt(argc, argv, "CP:iqv")) != -1) { 1375 switch (c) { 1376 case 'C': 1377 ctx->Cflag = true; 1378 break; 1379 case 'P': 1380 ctx->Pflag = true; 1381 ctx->pattern = parse_pattern(optarg); 1382 if (ctx->pattern < 0) { 1383 g_free(ctx); 1384 return -EINVAL; 1385 } 1386 break; 1387 case 'i': 1388 printf("injecting invalid read request\n"); 1389 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ); 1390 g_free(ctx); 1391 return 0; 1392 case 'q': 1393 ctx->qflag = true; 1394 break; 1395 case 'v': 1396 ctx->vflag = true; 1397 break; 1398 default: 1399 g_free(ctx); 1400 qemuio_command_usage(&aio_read_cmd); 1401 return -EINVAL; 1402 } 1403 } 1404 1405 if (optind > argc - 2) { 1406 g_free(ctx); 1407 qemuio_command_usage(&aio_read_cmd); 1408 return -EINVAL; 1409 } 1410 1411 ctx->offset = cvtnum(argv[optind]); 1412 if (ctx->offset < 0) { 1413 int ret = ctx->offset; 1414 print_cvtnum_err(ret, argv[optind]); 1415 g_free(ctx); 1416 return ret; 1417 } 1418 optind++; 1419 1420 nr_iov = argc - optind; 1421 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab); 1422 if (ctx->buf == NULL) { 1423 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ); 1424 g_free(ctx); 1425 return -EINVAL; 1426 } 1427 1428 gettimeofday(&ctx->t1, NULL); 1429 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, 1430 BLOCK_ACCT_READ); 1431 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx); 1432 return 0; 1433 } 1434 1435 static void aio_write_help(void) 1436 { 1437 printf( 1438 "\n" 1439 " asynchronously writes a range of bytes from the given offset source\n" 1440 " from multiple buffers\n" 1441 "\n" 1442 " Example:\n" 1443 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1444 "\n" 1445 " Writes into a segment of the currently open file, using a buffer\n" 1446 " filled with a set pattern (0xcdcdcdcd).\n" 1447 " The write is performed asynchronously and the aio_flush command must be\n" 1448 " used to ensure all outstanding aio requests have been completed.\n" 1449 " Note that due to its asynchronous nature, this command will be\n" 1450 " considered successful once the request is submitted, independently\n" 1451 " of potential I/O errors or pattern mismatches.\n" 1452 " -P, -- use different pattern to fill file\n" 1453 " -C, -- report statistics in a machine parsable format\n" 1454 " -f, -- use Force Unit Access semantics\n" 1455 " -i, -- treat request as invalid, for exercising stats\n" 1456 " -q, -- quiet mode, do not show I/O statistics\n" 1457 " -u, -- with -z, allow unmapping\n" 1458 " -z, -- write zeroes using blk_aio_pwrite_zeroes\n" 1459 "\n"); 1460 } 1461 1462 static int aio_write_f(BlockBackend *blk, int argc, char **argv); 1463 1464 static const cmdinfo_t aio_write_cmd = { 1465 .name = "aio_write", 1466 .cfunc = aio_write_f, 1467 .perm = BLK_PERM_WRITE, 1468 .argmin = 2, 1469 .argmax = -1, 1470 .args = "[-Cfiquz] [-P pattern] off len [len..]", 1471 .oneline = "asynchronously writes a number of bytes", 1472 .help = aio_write_help, 1473 }; 1474 1475 static int aio_write_f(BlockBackend *blk, int argc, char **argv) 1476 { 1477 int nr_iov, c; 1478 int pattern = 0xcd; 1479 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1480 int flags = 0; 1481 1482 ctx->blk = blk; 1483 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) { 1484 switch (c) { 1485 case 'C': 1486 ctx->Cflag = true; 1487 break; 1488 case 'f': 1489 flags |= BDRV_REQ_FUA; 1490 break; 1491 case 'q': 1492 ctx->qflag = true; 1493 break; 1494 case 'u': 1495 flags |= BDRV_REQ_MAY_UNMAP; 1496 break; 1497 case 'P': 1498 pattern = parse_pattern(optarg); 1499 if (pattern < 0) { 1500 g_free(ctx); 1501 return -EINVAL; 1502 } 1503 break; 1504 case 'i': 1505 printf("injecting invalid write request\n"); 1506 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE); 1507 g_free(ctx); 1508 return 0; 1509 case 'z': 1510 ctx->zflag = true; 1511 break; 1512 default: 1513 g_free(ctx); 1514 qemuio_command_usage(&aio_write_cmd); 1515 return -EINVAL; 1516 } 1517 } 1518 1519 if (optind > argc - 2) { 1520 g_free(ctx); 1521 qemuio_command_usage(&aio_write_cmd); 1522 return -EINVAL; 1523 } 1524 1525 if (ctx->zflag && optind != argc - 2) { 1526 printf("-z supports only a single length parameter\n"); 1527 g_free(ctx); 1528 return -EINVAL; 1529 } 1530 1531 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) { 1532 printf("-u requires -z to be specified\n"); 1533 g_free(ctx); 1534 return -EINVAL; 1535 } 1536 1537 if (ctx->zflag && ctx->Pflag) { 1538 printf("-z and -P cannot be specified at the same time\n"); 1539 g_free(ctx); 1540 return -EINVAL; 1541 } 1542 1543 ctx->offset = cvtnum(argv[optind]); 1544 if (ctx->offset < 0) { 1545 int ret = ctx->offset; 1546 print_cvtnum_err(ret, argv[optind]); 1547 g_free(ctx); 1548 return ret; 1549 } 1550 optind++; 1551 1552 if (ctx->zflag) { 1553 int64_t count = cvtnum(argv[optind]); 1554 if (count < 0) { 1555 print_cvtnum_err(count, argv[optind]); 1556 g_free(ctx); 1557 return count; 1558 } 1559 1560 ctx->qiov.size = count; 1561 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done, 1562 ctx); 1563 } else { 1564 nr_iov = argc - optind; 1565 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 1566 pattern); 1567 if (ctx->buf == NULL) { 1568 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE); 1569 g_free(ctx); 1570 return -EINVAL; 1571 } 1572 1573 gettimeofday(&ctx->t1, NULL); 1574 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, 1575 BLOCK_ACCT_WRITE); 1576 1577 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done, 1578 ctx); 1579 } 1580 1581 return 0; 1582 } 1583 1584 static int aio_flush_f(BlockBackend *blk, int argc, char **argv) 1585 { 1586 BlockAcctCookie cookie; 1587 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH); 1588 blk_drain_all(); 1589 block_acct_done(blk_get_stats(blk), &cookie); 1590 return 0; 1591 } 1592 1593 static const cmdinfo_t aio_flush_cmd = { 1594 .name = "aio_flush", 1595 .cfunc = aio_flush_f, 1596 .oneline = "completes all outstanding aio requests" 1597 }; 1598 1599 static int flush_f(BlockBackend *blk, int argc, char **argv) 1600 { 1601 return blk_flush(blk); 1602 } 1603 1604 static const cmdinfo_t flush_cmd = { 1605 .name = "flush", 1606 .altname = "f", 1607 .cfunc = flush_f, 1608 .oneline = "flush all in-core file state to disk", 1609 }; 1610 1611 static int truncate_f(BlockBackend *blk, int argc, char **argv) 1612 { 1613 Error *local_err = NULL; 1614 int64_t offset; 1615 int ret; 1616 1617 offset = cvtnum(argv[1]); 1618 if (offset < 0) { 1619 print_cvtnum_err(offset, argv[1]); 1620 return offset; 1621 } 1622 1623 ret = blk_truncate(blk, offset, PREALLOC_MODE_OFF, &local_err); 1624 if (ret < 0) { 1625 error_report_err(local_err); 1626 return ret; 1627 } 1628 1629 return 0; 1630 } 1631 1632 static const cmdinfo_t truncate_cmd = { 1633 .name = "truncate", 1634 .altname = "t", 1635 .cfunc = truncate_f, 1636 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE, 1637 .argmin = 1, 1638 .argmax = 1, 1639 .args = "off", 1640 .oneline = "truncates the current file at the given offset", 1641 }; 1642 1643 static int length_f(BlockBackend *blk, int argc, char **argv) 1644 { 1645 int64_t size; 1646 char s1[64]; 1647 1648 size = blk_getlength(blk); 1649 if (size < 0) { 1650 printf("getlength: %s\n", strerror(-size)); 1651 return size; 1652 } 1653 1654 cvtstr(size, s1, sizeof(s1)); 1655 printf("%s\n", s1); 1656 return 0; 1657 } 1658 1659 1660 static const cmdinfo_t length_cmd = { 1661 .name = "length", 1662 .altname = "l", 1663 .cfunc = length_f, 1664 .oneline = "gets the length of the current file", 1665 }; 1666 1667 1668 static int info_f(BlockBackend *blk, int argc, char **argv) 1669 { 1670 BlockDriverState *bs = blk_bs(blk); 1671 BlockDriverInfo bdi; 1672 ImageInfoSpecific *spec_info; 1673 Error *local_err = NULL; 1674 char s1[64], s2[64]; 1675 int ret; 1676 1677 if (bs->drv && bs->drv->format_name) { 1678 printf("format name: %s\n", bs->drv->format_name); 1679 } 1680 if (bs->drv && bs->drv->protocol_name) { 1681 printf("format name: %s\n", bs->drv->protocol_name); 1682 } 1683 1684 ret = bdrv_get_info(bs, &bdi); 1685 if (ret) { 1686 return ret; 1687 } 1688 1689 cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1690 cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1691 1692 printf("cluster size: %s\n", s1); 1693 printf("vm state offset: %s\n", s2); 1694 1695 spec_info = bdrv_get_specific_info(bs, &local_err); 1696 if (local_err) { 1697 error_report_err(local_err); 1698 return -EIO; 1699 } 1700 if (spec_info) { 1701 printf("Format specific information:\n"); 1702 bdrv_image_info_specific_dump(spec_info); 1703 qapi_free_ImageInfoSpecific(spec_info); 1704 } 1705 1706 return 0; 1707 } 1708 1709 1710 1711 static const cmdinfo_t info_cmd = { 1712 .name = "info", 1713 .altname = "i", 1714 .cfunc = info_f, 1715 .oneline = "prints information about the current file", 1716 }; 1717 1718 static void discard_help(void) 1719 { 1720 printf( 1721 "\n" 1722 " discards a range of bytes from the given offset\n" 1723 "\n" 1724 " Example:\n" 1725 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n" 1726 "\n" 1727 " Discards a segment of the currently open file.\n" 1728 " -C, -- report statistics in a machine parsable format\n" 1729 " -q, -- quiet mode, do not show I/O statistics\n" 1730 "\n"); 1731 } 1732 1733 static int discard_f(BlockBackend *blk, int argc, char **argv); 1734 1735 static const cmdinfo_t discard_cmd = { 1736 .name = "discard", 1737 .altname = "d", 1738 .cfunc = discard_f, 1739 .perm = BLK_PERM_WRITE, 1740 .argmin = 2, 1741 .argmax = -1, 1742 .args = "[-Cq] off len", 1743 .oneline = "discards a number of bytes at a specified offset", 1744 .help = discard_help, 1745 }; 1746 1747 static int discard_f(BlockBackend *blk, int argc, char **argv) 1748 { 1749 struct timeval t1, t2; 1750 bool Cflag = false, qflag = false; 1751 int c, ret; 1752 int64_t offset, bytes; 1753 1754 while ((c = getopt(argc, argv, "Cq")) != -1) { 1755 switch (c) { 1756 case 'C': 1757 Cflag = true; 1758 break; 1759 case 'q': 1760 qflag = true; 1761 break; 1762 default: 1763 qemuio_command_usage(&discard_cmd); 1764 return -EINVAL; 1765 } 1766 } 1767 1768 if (optind != argc - 2) { 1769 qemuio_command_usage(&discard_cmd); 1770 return -EINVAL; 1771 } 1772 1773 offset = cvtnum(argv[optind]); 1774 if (offset < 0) { 1775 print_cvtnum_err(offset, argv[optind]); 1776 return offset; 1777 } 1778 1779 optind++; 1780 bytes = cvtnum(argv[optind]); 1781 if (bytes < 0) { 1782 print_cvtnum_err(bytes, argv[optind]); 1783 return bytes; 1784 } else if (bytes > BDRV_REQUEST_MAX_BYTES) { 1785 printf("length cannot exceed %"PRIu64", given %s\n", 1786 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]); 1787 return -EINVAL; 1788 } 1789 1790 gettimeofday(&t1, NULL); 1791 ret = blk_pdiscard(blk, offset, bytes); 1792 gettimeofday(&t2, NULL); 1793 1794 if (ret < 0) { 1795 printf("discard failed: %s\n", strerror(-ret)); 1796 return ret; 1797 } 1798 1799 /* Finally, report back -- -C gives a parsable format */ 1800 if (!qflag) { 1801 t2 = tsub(t2, t1); 1802 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag); 1803 } 1804 1805 return 0; 1806 } 1807 1808 static int alloc_f(BlockBackend *blk, int argc, char **argv) 1809 { 1810 BlockDriverState *bs = blk_bs(blk); 1811 int64_t offset, start, remaining, count; 1812 char s1[64]; 1813 int ret; 1814 int64_t num, sum_alloc; 1815 1816 start = offset = cvtnum(argv[1]); 1817 if (offset < 0) { 1818 print_cvtnum_err(offset, argv[1]); 1819 return offset; 1820 } 1821 1822 if (argc == 3) { 1823 count = cvtnum(argv[2]); 1824 if (count < 0) { 1825 print_cvtnum_err(count, argv[2]); 1826 return count; 1827 } 1828 } else { 1829 count = BDRV_SECTOR_SIZE; 1830 } 1831 1832 remaining = count; 1833 sum_alloc = 0; 1834 while (remaining) { 1835 ret = bdrv_is_allocated(bs, offset, remaining, &num); 1836 if (ret < 0) { 1837 printf("is_allocated failed: %s\n", strerror(-ret)); 1838 return ret; 1839 } 1840 offset += num; 1841 remaining -= num; 1842 if (ret) { 1843 sum_alloc += num; 1844 } 1845 if (num == 0) { 1846 count -= remaining; 1847 remaining = 0; 1848 } 1849 } 1850 1851 cvtstr(start, s1, sizeof(s1)); 1852 1853 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n", 1854 sum_alloc, count, s1); 1855 return 0; 1856 } 1857 1858 static const cmdinfo_t alloc_cmd = { 1859 .name = "alloc", 1860 .altname = "a", 1861 .argmin = 1, 1862 .argmax = 2, 1863 .cfunc = alloc_f, 1864 .args = "offset [count]", 1865 .oneline = "checks if offset is allocated in the file", 1866 }; 1867 1868 1869 static int map_is_allocated(BlockDriverState *bs, int64_t offset, 1870 int64_t bytes, int64_t *pnum) 1871 { 1872 int64_t num; 1873 int num_checked; 1874 int ret, firstret; 1875 1876 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES); 1877 ret = bdrv_is_allocated(bs, offset, num_checked, &num); 1878 if (ret < 0) { 1879 return ret; 1880 } 1881 1882 firstret = ret; 1883 *pnum = num; 1884 1885 while (bytes > 0 && ret == firstret) { 1886 offset += num; 1887 bytes -= num; 1888 1889 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES); 1890 ret = bdrv_is_allocated(bs, offset, num_checked, &num); 1891 if (ret == firstret && num) { 1892 *pnum += num; 1893 } else { 1894 break; 1895 } 1896 } 1897 1898 return firstret; 1899 } 1900 1901 static int map_f(BlockBackend *blk, int argc, char **argv) 1902 { 1903 int64_t offset, bytes; 1904 char s1[64], s2[64]; 1905 int64_t num; 1906 int ret; 1907 const char *retstr; 1908 1909 offset = 0; 1910 bytes = blk_getlength(blk); 1911 if (bytes < 0) { 1912 error_report("Failed to query image length: %s", strerror(-bytes)); 1913 return bytes; 1914 } 1915 1916 while (bytes) { 1917 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num); 1918 if (ret < 0) { 1919 error_report("Failed to get allocation status: %s", strerror(-ret)); 1920 return ret; 1921 } else if (!num) { 1922 error_report("Unexpected end of image"); 1923 return -EIO; 1924 } 1925 1926 retstr = ret ? " allocated" : "not allocated"; 1927 cvtstr(num, s1, sizeof(s1)); 1928 cvtstr(offset, s2, sizeof(s2)); 1929 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n", 1930 s1, num, retstr, s2, offset); 1931 1932 offset += num; 1933 bytes -= num; 1934 } 1935 1936 return 0; 1937 } 1938 1939 static const cmdinfo_t map_cmd = { 1940 .name = "map", 1941 .argmin = 0, 1942 .argmax = 0, 1943 .cfunc = map_f, 1944 .args = "", 1945 .oneline = "prints the allocated areas of a file", 1946 }; 1947 1948 static void reopen_help(void) 1949 { 1950 printf( 1951 "\n" 1952 " Changes the open options of an already opened image\n" 1953 "\n" 1954 " Example:\n" 1955 " 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n" 1956 "\n" 1957 " -r, -- Reopen the image read-only\n" 1958 " -w, -- Reopen the image read-write\n" 1959 " -c, -- Change the cache mode to the given value\n" 1960 " -o, -- Changes block driver options (cf. 'open' command)\n" 1961 "\n"); 1962 } 1963 1964 static int reopen_f(BlockBackend *blk, int argc, char **argv); 1965 1966 static QemuOptsList reopen_opts = { 1967 .name = "reopen", 1968 .merge_lists = true, 1969 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head), 1970 .desc = { 1971 /* no elements => accept any params */ 1972 { /* end of list */ } 1973 }, 1974 }; 1975 1976 static const cmdinfo_t reopen_cmd = { 1977 .name = "reopen", 1978 .argmin = 0, 1979 .argmax = -1, 1980 .cfunc = reopen_f, 1981 .args = "[(-r|-w)] [-c cache] [-o options]", 1982 .oneline = "reopens an image with new options", 1983 .help = reopen_help, 1984 }; 1985 1986 static int reopen_f(BlockBackend *blk, int argc, char **argv) 1987 { 1988 BlockDriverState *bs = blk_bs(blk); 1989 QemuOpts *qopts; 1990 QDict *opts; 1991 int c; 1992 int flags = bs->open_flags; 1993 bool writethrough = !blk_enable_write_cache(blk); 1994 bool has_rw_option = false; 1995 bool has_cache_option = false; 1996 1997 BlockReopenQueue *brq; 1998 Error *local_err = NULL; 1999 2000 while ((c = getopt(argc, argv, "c:o:rw")) != -1) { 2001 switch (c) { 2002 case 'c': 2003 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) { 2004 error_report("Invalid cache option: %s", optarg); 2005 return -EINVAL; 2006 } 2007 has_cache_option = true; 2008 break; 2009 case 'o': 2010 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) { 2011 qemu_opts_reset(&reopen_opts); 2012 return -EINVAL; 2013 } 2014 break; 2015 case 'r': 2016 if (has_rw_option) { 2017 error_report("Only one -r/-w option may be given"); 2018 return -EINVAL; 2019 } 2020 flags &= ~BDRV_O_RDWR; 2021 has_rw_option = true; 2022 break; 2023 case 'w': 2024 if (has_rw_option) { 2025 error_report("Only one -r/-w option may be given"); 2026 return -EINVAL; 2027 } 2028 flags |= BDRV_O_RDWR; 2029 has_rw_option = true; 2030 break; 2031 default: 2032 qemu_opts_reset(&reopen_opts); 2033 qemuio_command_usage(&reopen_cmd); 2034 return -EINVAL; 2035 } 2036 } 2037 2038 if (optind != argc) { 2039 qemu_opts_reset(&reopen_opts); 2040 qemuio_command_usage(&reopen_cmd); 2041 return -EINVAL; 2042 } 2043 2044 if (!writethrough != blk_enable_write_cache(blk) && 2045 blk_get_attached_dev(blk)) 2046 { 2047 error_report("Cannot change cache.writeback: Device attached"); 2048 qemu_opts_reset(&reopen_opts); 2049 return -EBUSY; 2050 } 2051 2052 if (!(flags & BDRV_O_RDWR)) { 2053 uint64_t orig_perm, orig_shared_perm; 2054 2055 bdrv_drain(bs); 2056 2057 blk_get_perm(blk, &orig_perm, &orig_shared_perm); 2058 blk_set_perm(blk, 2059 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED), 2060 orig_shared_perm, 2061 &error_abort); 2062 } 2063 2064 qopts = qemu_opts_find(&reopen_opts, NULL); 2065 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new(); 2066 qemu_opts_reset(&reopen_opts); 2067 2068 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) { 2069 if (has_rw_option) { 2070 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'"); 2071 qobject_unref(opts); 2072 return -EINVAL; 2073 } 2074 } else { 2075 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR)); 2076 } 2077 2078 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) || 2079 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) { 2080 if (has_cache_option) { 2081 error_report("Cannot set both -c and the cache options"); 2082 qobject_unref(opts); 2083 return -EINVAL; 2084 } 2085 } else { 2086 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE); 2087 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH); 2088 } 2089 2090 bdrv_subtree_drained_begin(bs); 2091 brq = bdrv_reopen_queue(NULL, bs, opts, true); 2092 bdrv_reopen_multiple(brq, &local_err); 2093 bdrv_subtree_drained_end(bs); 2094 2095 if (local_err) { 2096 error_report_err(local_err); 2097 return -EINVAL; 2098 } 2099 2100 blk_set_enable_write_cache(blk, !writethrough); 2101 return 0; 2102 } 2103 2104 static int break_f(BlockBackend *blk, int argc, char **argv) 2105 { 2106 int ret; 2107 2108 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]); 2109 if (ret < 0) { 2110 printf("Could not set breakpoint: %s\n", strerror(-ret)); 2111 return ret; 2112 } 2113 2114 return 0; 2115 } 2116 2117 static int remove_break_f(BlockBackend *blk, int argc, char **argv) 2118 { 2119 int ret; 2120 2121 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]); 2122 if (ret < 0) { 2123 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret)); 2124 return ret; 2125 } 2126 2127 return 0; 2128 } 2129 2130 static const cmdinfo_t break_cmd = { 2131 .name = "break", 2132 .argmin = 2, 2133 .argmax = 2, 2134 .cfunc = break_f, 2135 .args = "event tag", 2136 .oneline = "sets a breakpoint on event and tags the stopped " 2137 "request as tag", 2138 }; 2139 2140 static const cmdinfo_t remove_break_cmd = { 2141 .name = "remove_break", 2142 .argmin = 1, 2143 .argmax = 1, 2144 .cfunc = remove_break_f, 2145 .args = "tag", 2146 .oneline = "remove a breakpoint by tag", 2147 }; 2148 2149 static int resume_f(BlockBackend *blk, int argc, char **argv) 2150 { 2151 int ret; 2152 2153 ret = bdrv_debug_resume(blk_bs(blk), argv[1]); 2154 if (ret < 0) { 2155 printf("Could not resume request: %s\n", strerror(-ret)); 2156 return ret; 2157 } 2158 2159 return 0; 2160 } 2161 2162 static const cmdinfo_t resume_cmd = { 2163 .name = "resume", 2164 .argmin = 1, 2165 .argmax = 1, 2166 .cfunc = resume_f, 2167 .args = "tag", 2168 .oneline = "resumes the request tagged as tag", 2169 }; 2170 2171 static int wait_break_f(BlockBackend *blk, int argc, char **argv) 2172 { 2173 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) { 2174 aio_poll(blk_get_aio_context(blk), true); 2175 } 2176 return 0; 2177 } 2178 2179 static const cmdinfo_t wait_break_cmd = { 2180 .name = "wait_break", 2181 .argmin = 1, 2182 .argmax = 1, 2183 .cfunc = wait_break_f, 2184 .args = "tag", 2185 .oneline = "waits for the suspension of a request", 2186 }; 2187 2188 static int abort_f(BlockBackend *blk, int argc, char **argv) 2189 { 2190 abort(); 2191 } 2192 2193 static const cmdinfo_t abort_cmd = { 2194 .name = "abort", 2195 .cfunc = abort_f, 2196 .flags = CMD_NOFILE_OK, 2197 .oneline = "simulate a program crash using abort(3)", 2198 }; 2199 2200 static void sigraise_help(void) 2201 { 2202 printf( 2203 "\n" 2204 " raises the given signal\n" 2205 "\n" 2206 " Example:\n" 2207 " 'sigraise %i' - raises SIGTERM\n" 2208 "\n" 2209 " Invokes raise(signal), where \"signal\" is the mandatory integer argument\n" 2210 " given to sigraise.\n" 2211 "\n", SIGTERM); 2212 } 2213 2214 static int sigraise_f(BlockBackend *blk, int argc, char **argv); 2215 2216 static const cmdinfo_t sigraise_cmd = { 2217 .name = "sigraise", 2218 .cfunc = sigraise_f, 2219 .argmin = 1, 2220 .argmax = 1, 2221 .flags = CMD_NOFILE_OK, 2222 .args = "signal", 2223 .oneline = "raises a signal", 2224 .help = sigraise_help, 2225 }; 2226 2227 static int sigraise_f(BlockBackend *blk, int argc, char **argv) 2228 { 2229 int64_t sig = cvtnum(argv[1]); 2230 if (sig < 0) { 2231 print_cvtnum_err(sig, argv[1]); 2232 return sig; 2233 } else if (sig > NSIG) { 2234 printf("signal argument '%s' is too large to be a valid signal\n", 2235 argv[1]); 2236 return -EINVAL; 2237 } 2238 2239 /* Using raise() to kill this process does not necessarily flush all open 2240 * streams. At least stdout and stderr (although the latter should be 2241 * non-buffered anyway) should be flushed, though. */ 2242 fflush(stdout); 2243 fflush(stderr); 2244 2245 raise(sig); 2246 2247 return 0; 2248 } 2249 2250 static void sleep_cb(void *opaque) 2251 { 2252 bool *expired = opaque; 2253 *expired = true; 2254 } 2255 2256 static int sleep_f(BlockBackend *blk, int argc, char **argv) 2257 { 2258 char *endptr; 2259 long ms; 2260 struct QEMUTimer *timer; 2261 bool expired = false; 2262 2263 ms = strtol(argv[1], &endptr, 0); 2264 if (ms < 0 || *endptr != '\0') { 2265 printf("%s is not a valid number\n", argv[1]); 2266 return -EINVAL; 2267 } 2268 2269 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired); 2270 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms); 2271 2272 while (!expired) { 2273 main_loop_wait(false); 2274 } 2275 2276 timer_free(timer); 2277 return 0; 2278 } 2279 2280 static const cmdinfo_t sleep_cmd = { 2281 .name = "sleep", 2282 .argmin = 1, 2283 .argmax = 1, 2284 .cfunc = sleep_f, 2285 .flags = CMD_NOFILE_OK, 2286 .oneline = "waits for the given value in milliseconds", 2287 }; 2288 2289 static void help_oneline(const char *cmd, const cmdinfo_t *ct) 2290 { 2291 if (cmd) { 2292 printf("%s ", cmd); 2293 } else { 2294 printf("%s ", ct->name); 2295 if (ct->altname) { 2296 printf("(or %s) ", ct->altname); 2297 } 2298 } 2299 2300 if (ct->args) { 2301 printf("%s ", ct->args); 2302 } 2303 printf("-- %s\n", ct->oneline); 2304 } 2305 2306 static void help_onecmd(const char *cmd, const cmdinfo_t *ct) 2307 { 2308 help_oneline(cmd, ct); 2309 if (ct->help) { 2310 ct->help(); 2311 } 2312 } 2313 2314 static void help_all(void) 2315 { 2316 const cmdinfo_t *ct; 2317 2318 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) { 2319 help_oneline(ct->name, ct); 2320 } 2321 printf("\nUse 'help commandname' for extended help.\n"); 2322 } 2323 2324 static int help_f(BlockBackend *blk, int argc, char **argv) 2325 { 2326 const cmdinfo_t *ct; 2327 2328 if (argc == 1) { 2329 help_all(); 2330 return 0; 2331 } 2332 2333 ct = find_command(argv[1]); 2334 if (ct == NULL) { 2335 printf("command %s not found\n", argv[1]); 2336 return -EINVAL; 2337 } 2338 2339 help_onecmd(argv[1], ct); 2340 return 0; 2341 } 2342 2343 static const cmdinfo_t help_cmd = { 2344 .name = "help", 2345 .altname = "?", 2346 .cfunc = help_f, 2347 .argmin = 0, 2348 .argmax = 1, 2349 .flags = CMD_FLAG_GLOBAL, 2350 .args = "[command]", 2351 .oneline = "help for one or all commands", 2352 }; 2353 2354 int qemuio_command(BlockBackend *blk, const char *cmd) 2355 { 2356 AioContext *ctx; 2357 char *input; 2358 const cmdinfo_t *ct; 2359 char **v; 2360 int c; 2361 int ret = 0; 2362 2363 input = g_strdup(cmd); 2364 v = breakline(input, &c); 2365 if (c) { 2366 ct = find_command(v[0]); 2367 if (ct) { 2368 ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context(); 2369 aio_context_acquire(ctx); 2370 ret = command(blk, ct, c, v); 2371 aio_context_release(ctx); 2372 } else { 2373 fprintf(stderr, "command \"%s\" not found\n", v[0]); 2374 ret = -EINVAL; 2375 } 2376 } 2377 g_free(input); 2378 g_free(v); 2379 2380 return ret; 2381 } 2382 2383 static void __attribute((constructor)) init_qemuio_commands(void) 2384 { 2385 /* initialize commands */ 2386 qemuio_add_command(&help_cmd); 2387 qemuio_add_command(&read_cmd); 2388 qemuio_add_command(&readv_cmd); 2389 qemuio_add_command(&write_cmd); 2390 qemuio_add_command(&writev_cmd); 2391 qemuio_add_command(&aio_read_cmd); 2392 qemuio_add_command(&aio_write_cmd); 2393 qemuio_add_command(&aio_flush_cmd); 2394 qemuio_add_command(&flush_cmd); 2395 qemuio_add_command(&truncate_cmd); 2396 qemuio_add_command(&length_cmd); 2397 qemuio_add_command(&info_cmd); 2398 qemuio_add_command(&discard_cmd); 2399 qemuio_add_command(&alloc_cmd); 2400 qemuio_add_command(&map_cmd); 2401 qemuio_add_command(&reopen_cmd); 2402 qemuio_add_command(&break_cmd); 2403 qemuio_add_command(&remove_break_cmd); 2404 qemuio_add_command(&resume_cmd); 2405 qemuio_add_command(&wait_break_cmd); 2406 qemuio_add_command(&abort_cmd); 2407 qemuio_add_command(&sleep_cmd); 2408 qemuio_add_command(&sigraise_cmd); 2409 } 2410