qemu/qemu-io-cmds.c
<<
>>
Prefs
   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
  18int qemuio_misalign;
  19
  20static cmdinfo_t *cmdtab;
  21static int ncmds;
  22
  23static 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
  29void 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
  36int 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
  42static 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
  54static 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
  83static 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
  97static 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
 125static 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
 145static 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
 183static 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
 194static 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
 203enum {
 204    DEFAULT_TIME        = 0x0,
 205    TERSE_FIXED_TIME    = 0x1,
 206    VERBOSE_FIXED_TIME  = 0x2,
 207};
 208
 209static 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 */
 241static 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
 263static 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
 278static void qemu_io_free(void *p)
 279{
 280    if (qemuio_misalign) {
 281        p -= MISALIGN_OFFSET;
 282    }
 283    qemu_vfree(p);
 284}
 285
 286static 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
 310static 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 */
 335static void *
 336create_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
 380fail:
 381    g_free(sizes);
 382    return buf;
 383}
 384
 385static 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
 398static 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
 411static 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
 421static 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
 431typedef struct {
 432    BlockDriverState *bs;
 433    int64_t offset;
 434    int count;
 435    int *total;
 436    int ret;
 437    bool done;
 438} CoWriteZeroes;
 439
 440static 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);
 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
 455static 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
 479static 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
 492static 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
 502static 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
 513static void aio_rw_done(void *opaque, int ret)
 514{
 515    *(int *)opaque = ret;
 516}
 517
 518static 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
 533static 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
 548struct multiwrite_async_ret {
 549    int num_done;
 550    int error;
 551};
 552
 553static 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
 563static 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
 591static 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
 613static int read_f(BlockDriverState *bs, int argc, char **argv);
 614
 615static 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
 626static 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
 772out:
 773    qemu_io_free(buf);
 774
 775    return 0;
 776}
 777
 778static 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
 797static int readv_f(BlockDriverState *bs, int argc, char **argv);
 798
 799static 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
 809static 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
 901out:
 902    qemu_iovec_destroy(&qiov);
 903    qemu_io_free(buf);
 904    return 0;
 905}
 906
 907static 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
 928static int write_f(BlockDriverState *bs, int argc, char **argv);
 929
 930static 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
 941static 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
1058out:
1059    if (!zflag) {
1060        qemu_io_free(buf);
1061    }
1062
1063    return 0;
1064}
1065
1066static void
1067writev_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
1084static int writev_f(BlockDriverState *bs, int argc, char **argv);
1085
1086static 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
1096static 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);
1167out:
1168    qemu_iovec_destroy(&qiov);
1169    qemu_io_free(buf);
1170    return 0;
1171}
1172
1173static 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
1193static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
1194
1195static 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
1205static 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);
1319out:
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
1332struct 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
1344static 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);
1365out:
1366    qemu_io_free(ctx->buf);
1367    qemu_iovec_destroy(&ctx->qiov);
1368    g_free(ctx);
1369}
1370
1371static 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);
1406out:
1407    qemu_io_free(ctx->buf);
1408    qemu_iovec_destroy(&ctx->qiov);
1409    g_free(ctx);
1410}
1411
1412static 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
1432static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1433
1434static 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
1444static 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
1507static 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
1527static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1528
1529static 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
1539static 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
1599static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1600{
1601    bdrv_drain_all();
1602    return 0;
1603}
1604
1605static const cmdinfo_t aio_flush_cmd = {
1606    .name       = "aio_flush",
1607    .cfunc      = aio_flush_f,
1608    .oneline    = "completes all outstanding aio requests"
1609};
1610
1611static int flush_f(BlockDriverState *bs, int argc, char **argv)
1612{
1613    bdrv_flush(bs);
1614    return 0;
1615}
1616
1617static 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
1624static 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
1644static 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
1654static 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
1671static 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
1679static 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
1716static 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
1723static 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
1738static int discard_f(BlockDriverState *bs, int argc, char **argv);
1739
1740static 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
1751static 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
1805out:
1806    return 0;
1807}
1808
1809static 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
1864static 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
1875static 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
1906static 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
1938static 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
1947static 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
1959static const cmdinfo_t break_cmd = {
1960       .name           = "break",
1961       .argmin         = 2,
1962       .argmax         = 2,
1963       .cfunc          = break_f,
1964       .args           = "event tag",
1965       .oneline        = "sets a breakpoint on event and tags the stopped "
1966                         "request as tag",
1967};
1968
1969static int resume_f(BlockDriverState *bs, int argc, char **argv)
1970{
1971    int ret;
1972
1973    ret = bdrv_debug_resume(bs, argv[1]);
1974    if (ret < 0) {
1975        printf("Could not resume request: %s\n", strerror(-ret));
1976    }
1977
1978    return 0;
1979}
1980
1981static const cmdinfo_t resume_cmd = {
1982       .name           = "resume",
1983       .argmin         = 1,
1984       .argmax         = 1,
1985       .cfunc          = resume_f,
1986       .args           = "tag",
1987       .oneline        = "resumes the request tagged as tag",
1988};
1989
1990static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
1991{
1992    while (!bdrv_debug_is_suspended(bs, argv[1])) {
1993        qemu_aio_wait();
1994    }
1995
1996    return 0;
1997}
1998
1999static const cmdinfo_t wait_break_cmd = {
2000       .name           = "wait_break",
2001       .argmin         = 1,
2002       .argmax         = 1,
2003       .cfunc          = wait_break_f,
2004       .args           = "tag",
2005       .oneline        = "waits for the suspension of a request",
2006};
2007
2008static int abort_f(BlockDriverState *bs, int argc, char **argv)
2009{
2010    abort();
2011}
2012
2013static const cmdinfo_t abort_cmd = {
2014       .name           = "abort",
2015       .cfunc          = abort_f,
2016       .flags          = CMD_NOFILE_OK,
2017       .oneline        = "simulate a program crash using abort(3)",
2018};
2019
2020static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2021{
2022    if (cmd) {
2023        printf("%s ", cmd);
2024    } else {
2025        printf("%s ", ct->name);
2026        if (ct->altname) {
2027            printf("(or %s) ", ct->altname);
2028        }
2029    }
2030
2031    if (ct->args) {
2032        printf("%s ", ct->args);
2033    }
2034    printf("-- %s\n", ct->oneline);
2035}
2036
2037static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2038{
2039    help_oneline(cmd, ct);
2040    if (ct->help) {
2041        ct->help();
2042    }
2043}
2044
2045static void help_all(void)
2046{
2047    const cmdinfo_t *ct;
2048
2049    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2050        help_oneline(ct->name, ct);
2051    }
2052    printf("\nUse 'help commandname' for extended help.\n");
2053}
2054
2055static int help_f(BlockDriverState *bs, int argc, char **argv)
2056{
2057    const cmdinfo_t *ct;
2058
2059    if (argc == 1) {
2060        help_all();
2061        return 0;
2062    }
2063
2064    ct = find_command(argv[1]);
2065    if (ct == NULL) {
2066        printf("command %s not found\n", argv[1]);
2067        return 0;
2068    }
2069
2070    help_onecmd(argv[1], ct);
2071    return 0;
2072}
2073
2074static const cmdinfo_t help_cmd = {
2075    .name       = "help",
2076    .altname    = "?",
2077    .cfunc      = help_f,
2078    .argmin     = 0,
2079    .argmax     = 1,
2080    .flags      = CMD_FLAG_GLOBAL,
2081    .args       = "[command]",
2082    .oneline    = "help for one or all commands",
2083};
2084
2085bool qemuio_command(BlockDriverState *bs, const char *cmd)
2086{
2087    char *input;
2088    const cmdinfo_t *ct;
2089    char **v;
2090    int c;
2091    bool done = false;
2092
2093    input = g_strdup(cmd);
2094    v = breakline(input, &c);
2095    if (c) {
2096        ct = find_command(v[0]);
2097        if (ct) {
2098            done = command(bs, ct, c, v);
2099        } else {
2100            fprintf(stderr, "command \"%s\" not found\n", v[0]);
2101        }
2102    }
2103    g_free(input);
2104    g_free(v);
2105
2106    return done;
2107}
2108
2109static void __attribute((constructor)) init_qemuio_commands(void)
2110{
2111    /* initialize commands */
2112    qemuio_add_command(&help_cmd);
2113    qemuio_add_command(&read_cmd);
2114    qemuio_add_command(&readv_cmd);
2115    qemuio_add_command(&write_cmd);
2116    qemuio_add_command(&writev_cmd);
2117    qemuio_add_command(&multiwrite_cmd);
2118    qemuio_add_command(&aio_read_cmd);
2119    qemuio_add_command(&aio_write_cmd);
2120    qemuio_add_command(&aio_flush_cmd);
2121    qemuio_add_command(&flush_cmd);
2122    qemuio_add_command(&truncate_cmd);
2123    qemuio_add_command(&length_cmd);
2124    qemuio_add_command(&info_cmd);
2125    qemuio_add_command(&discard_cmd);
2126    qemuio_add_command(&alloc_cmd);
2127    qemuio_add_command(&map_cmd);
2128    qemuio_add_command(&break_cmd);
2129    qemuio_add_command(&resume_cmd);
2130    qemuio_add_command(&wait_break_cmd);
2131    qemuio_add_command(&abort_cmd);
2132}
2133