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