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