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