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