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