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