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