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