Statistics
| Branch: | Revision:

root / qemu-io-cmds.c @ feature-archipelago

History | View | Annotate | Download (54.3 kB)

1
/*
2
 * Command line utility to exercise the QEMU I/O path.
3
 *
4
 * Copyright (C) 2009 Red Hat, Inc.
5
 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
6
 *
7
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8
 * See the COPYING file in the top-level directory.
9
 */
10

    
11
#include "qemu-io.h"
12
#include "block/block_int.h"
13
#include "block/qapi.h"
14
#include "qemu/main-loop.h"
15
#include "qemu/timer.h"
16

    
17
#define CMD_NOFILE_OK   0x01
18

    
19
int qemuio_misalign;
20

    
21
static cmdinfo_t *cmdtab;
22
static int ncmds;
23

    
24
static int compare_cmdname(const void *a, const void *b)
25
{
26
    return strcmp(((const cmdinfo_t *)a)->name,
27
                  ((const cmdinfo_t *)b)->name);
28
}
29

    
30
void qemuio_add_command(const cmdinfo_t *ci)
31
{
32
    cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
33
    cmdtab[ncmds - 1] = *ci;
34
    qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
35
}
36

    
37
int qemuio_command_usage(const cmdinfo_t *ci)
38
{
39
    printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
40
    return 0;
41
}
42

    
43
static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
44
{
45
    if (ct->flags & CMD_FLAG_GLOBAL) {
46
        return 1;
47
    }
48
    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
49
        fprintf(stderr, "no file open, try 'help open'\n");
50
        return 0;
51
    }
52
    return 1;
53
}
54

    
55
static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
56
                   char **argv)
57
{
58
    char *cmd = argv[0];
59

    
60
    if (!init_check_command(bs, ct)) {
61
        return 0;
62
    }
63

    
64
    if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
65
        if (ct->argmax == -1) {
66
            fprintf(stderr,
67
                    "bad argument count %d to %s, expected at least %d arguments\n",
68
                    argc-1, cmd, ct->argmin);
69
        } else if (ct->argmin == ct->argmax) {
70
            fprintf(stderr,
71
                    "bad argument count %d to %s, expected %d arguments\n",
72
                    argc-1, cmd, ct->argmin);
73
        } else {
74
            fprintf(stderr,
75
                    "bad argument count %d to %s, expected between %d and %d arguments\n",
76
                    argc-1, cmd, ct->argmin, ct->argmax);
77
        }
78
        return 0;
79
    }
80
    optind = 0;
81
    return ct->cfunc(bs, argc, argv);
82
}
83

    
84
static const cmdinfo_t *find_command(const char *cmd)
85
{
86
    cmdinfo_t *ct;
87

    
88
    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
89
        if (strcmp(ct->name, cmd) == 0 ||
90
            (ct->altname && strcmp(ct->altname, cmd) == 0))
91
        {
92
            return (const cmdinfo_t *)ct;
93
        }
94
    }
95
    return NULL;
96
}
97

    
98
/* Invoke fn() for commands with a matching prefix */
99
void qemuio_complete_command(const char *input,
100
                             void (*fn)(const char *cmd, void *opaque),
101
                             void *opaque)
102
{
103
    cmdinfo_t *ct;
104
    size_t input_len = strlen(input);
105

    
106
    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
107
        if (strncmp(input, ct->name, input_len) == 0) {
108
            fn(ct->name, opaque);
109
        }
110
    }
111
}
112

    
113
static char **breakline(char *input, int *count)
114
{
115
    int c = 0;
116
    char *p;
117
    char **rval = g_malloc0(sizeof(char *));
118
    char **tmp;
119

    
120
    while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
121
        if (!*p) {
122
            continue;
123
        }
124
        c++;
125
        tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
126
        if (!tmp) {
127
            g_free(rval);
128
            rval = NULL;
129
            c = 0;
130
            break;
131
        } else {
132
            rval = tmp;
133
        }
134
        rval[c - 1] = p;
135
        rval[c] = NULL;
136
    }
137
    *count = c;
138
    return rval;
139
}
140

    
141
static int64_t cvtnum(const char *s)
142
{
143
    char *end;
144
    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
145
}
146

    
147
#define EXABYTES(x)     ((long long)(x) << 60)
148
#define PETABYTES(x)    ((long long)(x) << 50)
149
#define TERABYTES(x)    ((long long)(x) << 40)
150
#define GIGABYTES(x)    ((long long)(x) << 30)
151
#define MEGABYTES(x)    ((long long)(x) << 20)
152
#define KILOBYTES(x)    ((long long)(x) << 10)
153

    
154
#define TO_EXABYTES(x)  ((x) / EXABYTES(1))
155
#define TO_PETABYTES(x) ((x) / PETABYTES(1))
156
#define TO_TERABYTES(x) ((x) / TERABYTES(1))
157
#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
158
#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
159
#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
160

    
161
static void cvtstr(double value, char *str, size_t size)
162
{
163
    char *trim;
164
    const char *suffix;
165

    
166
    if (value >= EXABYTES(1)) {
167
        suffix = " EiB";
168
        snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
169
    } else if (value >= PETABYTES(1)) {
170
        suffix = " PiB";
171
        snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
172
    } else if (value >= TERABYTES(1)) {
173
        suffix = " TiB";
174
        snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
175
    } else if (value >= GIGABYTES(1)) {
176
        suffix = " GiB";
177
        snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
178
    } else if (value >= MEGABYTES(1)) {
179
        suffix = " MiB";
180
        snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
181
    } else if (value >= KILOBYTES(1)) {
182
        suffix = " KiB";
183
        snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
184
    } else {
185
        suffix = " bytes";
186
        snprintf(str, size - 6, "%f", value);
187
    }
188

    
189
    trim = strstr(str, ".000");
190
    if (trim) {
191
        strcpy(trim, suffix);
192
    } else {
193
        strcat(str, suffix);
194
    }
195
}
196

    
197

    
198

    
199
static struct timeval tsub(struct timeval t1, struct timeval t2)
200
{
201
    t1.tv_usec -= t2.tv_usec;
202
    if (t1.tv_usec < 0) {
203
        t1.tv_usec += 1000000;
204
        t1.tv_sec--;
205
    }
206
    t1.tv_sec -= t2.tv_sec;
207
    return t1;
208
}
209

    
210
static double tdiv(double value, struct timeval tv)
211
{
212
    return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
213
}
214

    
215
#define HOURS(sec)      ((sec) / (60 * 60))
216
#define MINUTES(sec)    (((sec) % (60 * 60)) / 60)
217
#define SECONDS(sec)    ((sec) % 60)
218

    
219
enum {
220
    DEFAULT_TIME        = 0x0,
221
    TERSE_FIXED_TIME    = 0x1,
222
    VERBOSE_FIXED_TIME  = 0x2,
223
};
224

    
225
static void timestr(struct timeval *tv, char *ts, size_t size, int format)
226
{
227
    double usec = (double)tv->tv_usec / 1000000.0;
228

    
229
    if (format & TERSE_FIXED_TIME) {
230
        if (!HOURS(tv->tv_sec)) {
231
            snprintf(ts, size, "%u:%02u.%02u",
232
                    (unsigned int) MINUTES(tv->tv_sec),
233
                    (unsigned int) SECONDS(tv->tv_sec),
234
                    (unsigned int) (usec * 100));
235
            return;
236
        }
237
        format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
238
    }
239

    
240
    if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
241
        snprintf(ts, size, "%u:%02u:%02u.%02u",
242
                (unsigned int) HOURS(tv->tv_sec),
243
                (unsigned int) MINUTES(tv->tv_sec),
244
                (unsigned int) SECONDS(tv->tv_sec),
245
                (unsigned int) (usec * 100));
246
    } else {
247
        snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
248
    }
249
}
250

    
251
/*
252
 * Parse the pattern argument to various sub-commands.
253
 *
254
 * Because the pattern is used as an argument to memset it must evaluate
255
 * to an unsigned integer that fits into a single byte.
256
 */
257
static int parse_pattern(const char *arg)
258
{
259
    char *endptr = NULL;
260
    long pattern;
261

    
262
    pattern = strtol(arg, &endptr, 0);
263
    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
264
        printf("%s is not a valid pattern byte\n", arg);
265
        return -1;
266
    }
267

    
268
    return pattern;
269
}
270

    
271
/*
272
 * Memory allocation helpers.
273
 *
274
 * Make sure memory is aligned by default, or purposefully misaligned if
275
 * that is specified on the command line.
276
 */
277

    
278
#define MISALIGN_OFFSET     16
279
static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
280
{
281
    void *buf;
282

    
283
    if (qemuio_misalign) {
284
        len += MISALIGN_OFFSET;
285
    }
286
    buf = qemu_blockalign(bs, len);
287
    memset(buf, pattern, len);
288
    if (qemuio_misalign) {
289
        buf += MISALIGN_OFFSET;
290
    }
291
    return buf;
292
}
293

    
294
static void qemu_io_free(void *p)
295
{
296
    if (qemuio_misalign) {
297
        p -= MISALIGN_OFFSET;
298
    }
299
    qemu_vfree(p);
300
}
301

    
302
static void dump_buffer(const void *buffer, int64_t offset, int len)
303
{
304
    int i, j;
305
    const uint8_t *p;
306

    
307
    for (i = 0, p = buffer; i < len; i += 16) {
308
        const uint8_t *s = p;
309

    
310
        printf("%08" PRIx64 ":  ", offset + i);
311
        for (j = 0; j < 16 && i + j < len; j++, p++) {
312
            printf("%02x ", *p);
313
        }
314
        printf(" ");
315
        for (j = 0; j < 16 && i + j < len; j++, s++) {
316
            if (isalnum(*s)) {
317
                printf("%c", *s);
318
            } else {
319
                printf(".");
320
            }
321
        }
322
        printf("\n");
323
    }
324
}
325

    
326
static void print_report(const char *op, struct timeval *t, int64_t offset,
327
                         int count, int total, int cnt, int Cflag)
328
{
329
    char s1[64], s2[64], ts[64];
330

    
331
    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
332
    if (!Cflag) {
333
        cvtstr((double)total, s1, sizeof(s1));
334
        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
335
        printf("%s %d/%d bytes at offset %" PRId64 "\n",
336
               op, total, count, offset);
337
        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
338
               s1, cnt, ts, s2, tdiv((double)cnt, *t));
339
    } else {/* bytes,ops,time,bytes/sec,ops/sec */
340
        printf("%d,%d,%s,%.3f,%.3f\n",
341
            total, cnt, ts,
342
            tdiv((double)total, *t),
343
            tdiv((double)cnt, *t));
344
    }
345
}
346

    
347
/*
348
 * Parse multiple length statements for vectored I/O, and construct an I/O
349
 * vector matching it.
350
 */
351
static void *
352
create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
353
             int pattern)
354
{
355
    size_t *sizes = g_new0(size_t, nr_iov);
356
    size_t count = 0;
357
    void *buf = NULL;
358
    void *p;
359
    int i;
360

    
361
    for (i = 0; i < nr_iov; i++) {
362
        char *arg = argv[i];
363
        int64_t len;
364

    
365
        len = cvtnum(arg);
366
        if (len < 0) {
367
            printf("non-numeric length argument -- %s\n", arg);
368
            goto fail;
369
        }
370

    
371
        /* should be SIZE_T_MAX, but that doesn't exist */
372
        if (len > INT_MAX) {
373
            printf("too large length argument -- %s\n", arg);
374
            goto fail;
375
        }
376

    
377
        if (len & 0x1ff) {
378
            printf("length argument %" PRId64
379
                   " is not sector aligned\n", len);
380
            goto fail;
381
        }
382

    
383
        sizes[i] = len;
384
        count += len;
385
    }
386

    
387
    qemu_iovec_init(qiov, nr_iov);
388

    
389
    buf = p = qemu_io_alloc(bs, count, pattern);
390

    
391
    for (i = 0; i < nr_iov; i++) {
392
        qemu_iovec_add(qiov, p, sizes[i]);
393
        p += sizes[i];
394
    }
395

    
396
fail:
397
    g_free(sizes);
398
    return buf;
399
}
400

    
401
static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
402
                   int *total)
403
{
404
    int ret;
405

    
406
    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
407
    if (ret < 0) {
408
        return ret;
409
    }
410
    *total = count;
411
    return 1;
412
}
413

    
414
static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
415
                    int *total)
416
{
417
    int ret;
418

    
419
    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
420
    if (ret < 0) {
421
        return ret;
422
    }
423
    *total = count;
424
    return 1;
425
}
426

    
427
static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
428
                    int *total)
429
{
430
    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
431
    if (*total < 0) {
432
        return *total;
433
    }
434
    return 1;
435
}
436

    
437
static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
438
                     int *total)
439
{
440
    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
441
    if (*total < 0) {
442
        return *total;
443
    }
444
    return 1;
445
}
446

    
447
typedef struct {
448
    BlockDriverState *bs;
449
    int64_t offset;
450
    int count;
451
    int *total;
452
    int ret;
453
    bool done;
454
} CoWriteZeroes;
455

    
456
static void coroutine_fn co_write_zeroes_entry(void *opaque)
457
{
458
    CoWriteZeroes *data = opaque;
459

    
460
    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
461
                                     data->count / BDRV_SECTOR_SIZE, 0);
462
    data->done = true;
463
    if (data->ret < 0) {
464
        *data->total = data->ret;
465
        return;
466
    }
467

    
468
    *data->total = data->count;
469
}
470

    
471
static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
472
                              int *total)
473
{
474
    Coroutine *co;
475
    CoWriteZeroes data = {
476
        .bs     = bs,
477
        .offset = offset,
478
        .count  = count,
479
        .total  = total,
480
        .done   = false,
481
    };
482

    
483
    co = qemu_coroutine_create(co_write_zeroes_entry);
484
    qemu_coroutine_enter(co, &data);
485
    while (!data.done) {
486
        qemu_aio_wait();
487
    }
488
    if (data.ret < 0) {
489
        return data.ret;
490
    } else {
491
        return 1;
492
    }
493
}
494

    
495
static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
496
                               int count, int *total)
497
{
498
    int ret;
499

    
500
    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
501
    if (ret < 0) {
502
        return ret;
503
    }
504
    *total = count;
505
    return 1;
506
}
507

    
508
static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
509
                           int count, int *total)
510
{
511
    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
512
    if (*total < 0) {
513
        return *total;
514
    }
515
    return 1;
516
}
517

    
518
static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
519
                           int count, int *total)
520
{
521
    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
522
    if (*total < 0) {
523
        return *total;
524
    }
525
    return 1;
526
}
527

    
528
#define NOT_DONE 0x7fffffff
529
static void aio_rw_done(void *opaque, int ret)
530
{
531
    *(int *)opaque = ret;
532
}
533

    
534
static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
535
                        int64_t offset, int *total)
536
{
537
    int async_ret = NOT_DONE;
538

    
539
    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
540
                   aio_rw_done, &async_ret);
541
    while (async_ret == NOT_DONE) {
542
        main_loop_wait(false);
543
    }
544

    
545
    *total = qiov->size;
546
    return async_ret < 0 ? async_ret : 1;
547
}
548

    
549
static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
550
                         int64_t offset, int *total)
551
{
552
    int async_ret = NOT_DONE;
553

    
554
    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
555
                    aio_rw_done, &async_ret);
556
    while (async_ret == NOT_DONE) {
557
        main_loop_wait(false);
558
    }
559

    
560
    *total = qiov->size;
561
    return async_ret < 0 ? async_ret : 1;
562
}
563

    
564
struct multiwrite_async_ret {
565
    int num_done;
566
    int error;
567
};
568

    
569
static void multiwrite_cb(void *opaque, int ret)
570
{
571
    struct multiwrite_async_ret *async_ret = opaque;
572

    
573
    async_ret->num_done++;
574
    if (ret < 0) {
575
        async_ret->error = ret;
576
    }
577
}
578

    
579
static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
580
                             int num_reqs, int *total)
581
{
582
    int i, ret;
583
    struct multiwrite_async_ret async_ret = {
584
        .num_done = 0,
585
        .error = 0,
586
    };
587

    
588
    *total = 0;
589
    for (i = 0; i < num_reqs; i++) {
590
        reqs[i].cb = multiwrite_cb;
591
        reqs[i].opaque = &async_ret;
592
        *total += reqs[i].qiov->size;
593
    }
594

    
595
    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
596
    if (ret < 0) {
597
        return ret;
598
    }
599

    
600
    while (async_ret.num_done < num_reqs) {
601
        main_loop_wait(false);
602
    }
603

    
604
    return async_ret.error < 0 ? async_ret.error : 1;
605
}
606

    
607
static void read_help(void)
608
{
609
    printf(
610
"\n"
611
" reads a range of bytes from the given offset\n"
612
"\n"
613
" Example:\n"
614
" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
615
"\n"
616
" Reads a segment of the currently open file, optionally dumping it to the\n"
617
" standard output stream (with -v option) for subsequent inspection.\n"
618
" -b, -- read from the VM state rather than the virtual disk\n"
619
" -C, -- report statistics in a machine parsable format\n"
620
" -l, -- length for pattern verification (only with -P)\n"
621
" -p, -- use bdrv_pread to read the file\n"
622
" -P, -- use a pattern to verify read data\n"
623
" -q, -- quiet mode, do not show I/O statistics\n"
624
" -s, -- start offset for pattern verification (only with -P)\n"
625
" -v, -- dump buffer to standard output\n"
626
"\n");
627
}
628

    
629
static int read_f(BlockDriverState *bs, int argc, char **argv);
630

    
631
static const cmdinfo_t read_cmd = {
632
    .name       = "read",
633
    .altname    = "r",
634
    .cfunc      = read_f,
635
    .argmin     = 2,
636
    .argmax     = -1,
637
    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
638
    .oneline    = "reads a number of bytes at a specified offset",
639
    .help       = read_help,
640
};
641

    
642
static int read_f(BlockDriverState *bs, int argc, char **argv)
643
{
644
    struct timeval t1, t2;
645
    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
646
    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
647
    int c, cnt;
648
    char *buf;
649
    int64_t offset;
650
    int count;
651
    /* Some compilers get confused and warn if this is not initialized.  */
652
    int total = 0;
653
    int pattern = 0, pattern_offset = 0, pattern_count = 0;
654

    
655
    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
656
        switch (c) {
657
        case 'b':
658
            bflag = 1;
659
            break;
660
        case 'C':
661
            Cflag = 1;
662
            break;
663
        case 'l':
664
            lflag = 1;
665
            pattern_count = cvtnum(optarg);
666
            if (pattern_count < 0) {
667
                printf("non-numeric length argument -- %s\n", optarg);
668
                return 0;
669
            }
670
            break;
671
        case 'p':
672
            pflag = 1;
673
            break;
674
        case 'P':
675
            Pflag = 1;
676
            pattern = parse_pattern(optarg);
677
            if (pattern < 0) {
678
                return 0;
679
            }
680
            break;
681
        case 'q':
682
            qflag = 1;
683
            break;
684
        case 's':
685
            sflag = 1;
686
            pattern_offset = cvtnum(optarg);
687
            if (pattern_offset < 0) {
688
                printf("non-numeric length argument -- %s\n", optarg);
689
                return 0;
690
            }
691
            break;
692
        case 'v':
693
            vflag = 1;
694
            break;
695
        default:
696
            return qemuio_command_usage(&read_cmd);
697
        }
698
    }
699

    
700
    if (optind != argc - 2) {
701
        return qemuio_command_usage(&read_cmd);
702
    }
703

    
704
    if (bflag && pflag) {
705
        printf("-b and -p cannot be specified at the same time\n");
706
        return 0;
707
    }
708

    
709
    offset = cvtnum(argv[optind]);
710
    if (offset < 0) {
711
        printf("non-numeric length argument -- %s\n", argv[optind]);
712
        return 0;
713
    }
714

    
715
    optind++;
716
    count = cvtnum(argv[optind]);
717
    if (count < 0) {
718
        printf("non-numeric length argument -- %s\n", argv[optind]);
719
        return 0;
720
    }
721

    
722
    if (!Pflag && (lflag || sflag)) {
723
        return qemuio_command_usage(&read_cmd);
724
    }
725

    
726
    if (!lflag) {
727
        pattern_count = count - pattern_offset;
728
    }
729

    
730
    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
731
        printf("pattern verification range exceeds end of read data\n");
732
        return 0;
733
    }
734

    
735
    if (!pflag) {
736
        if (offset & 0x1ff) {
737
            printf("offset %" PRId64 " is not sector aligned\n",
738
                   offset);
739
            return 0;
740
        }
741
        if (count & 0x1ff) {
742
            printf("count %d is not sector aligned\n",
743
                   count);
744
            return 0;
745
        }
746
    }
747

    
748
    buf = qemu_io_alloc(bs, count, 0xab);
749

    
750
    gettimeofday(&t1, NULL);
751
    if (pflag) {
752
        cnt = do_pread(bs, buf, offset, count, &total);
753
    } else if (bflag) {
754
        cnt = do_load_vmstate(bs, buf, offset, count, &total);
755
    } else {
756
        cnt = do_read(bs, buf, offset, count, &total);
757
    }
758
    gettimeofday(&t2, NULL);
759

    
760
    if (cnt < 0) {
761
        printf("read failed: %s\n", strerror(-cnt));
762
        goto out;
763
    }
764

    
765
    if (Pflag) {
766
        void *cmp_buf = g_malloc(pattern_count);
767
        memset(cmp_buf, pattern, pattern_count);
768
        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
769
            printf("Pattern verification failed at offset %"
770
                   PRId64 ", %d bytes\n",
771
                   offset + pattern_offset, pattern_count);
772
        }
773
        g_free(cmp_buf);
774
    }
775

    
776
    if (qflag) {
777
        goto out;
778
    }
779

    
780
    if (vflag) {
781
        dump_buffer(buf, offset, count);
782
    }
783

    
784
    /* Finally, report back -- -C gives a parsable format */
785
    t2 = tsub(t2, t1);
786
    print_report("read", &t2, offset, count, total, cnt, Cflag);
787

    
788
out:
789
    qemu_io_free(buf);
790

    
791
    return 0;
792
}
793

    
794
static void readv_help(void)
795
{
796
    printf(
797
"\n"
798
" reads a range of bytes from the given offset into multiple buffers\n"
799
"\n"
800
" Example:\n"
801
" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
802
"\n"
803
" Reads a segment of the currently open file, optionally dumping it to the\n"
804
" standard output stream (with -v option) for subsequent inspection.\n"
805
" Uses multiple iovec buffers if more than one byte range is specified.\n"
806
" -C, -- report statistics in a machine parsable format\n"
807
" -P, -- use a pattern to verify read data\n"
808
" -v, -- dump buffer to standard output\n"
809
" -q, -- quiet mode, do not show I/O statistics\n"
810
"\n");
811
}
812

    
813
static int readv_f(BlockDriverState *bs, int argc, char **argv);
814

    
815
static const cmdinfo_t readv_cmd = {
816
    .name       = "readv",
817
    .cfunc      = readv_f,
818
    .argmin     = 2,
819
    .argmax     = -1,
820
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
821
    .oneline    = "reads a number of bytes at a specified offset",
822
    .help       = readv_help,
823
};
824

    
825
static int readv_f(BlockDriverState *bs, int argc, char **argv)
826
{
827
    struct timeval t1, t2;
828
    int Cflag = 0, qflag = 0, vflag = 0;
829
    int c, cnt;
830
    char *buf;
831
    int64_t offset;
832
    /* Some compilers get confused and warn if this is not initialized.  */
833
    int total = 0;
834
    int nr_iov;
835
    QEMUIOVector qiov;
836
    int pattern = 0;
837
    int Pflag = 0;
838

    
839
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
840
        switch (c) {
841
        case 'C':
842
            Cflag = 1;
843
            break;
844
        case 'P':
845
            Pflag = 1;
846
            pattern = parse_pattern(optarg);
847
            if (pattern < 0) {
848
                return 0;
849
            }
850
            break;
851
        case 'q':
852
            qflag = 1;
853
            break;
854
        case 'v':
855
            vflag = 1;
856
            break;
857
        default:
858
            return qemuio_command_usage(&readv_cmd);
859
        }
860
    }
861

    
862
    if (optind > argc - 2) {
863
        return qemuio_command_usage(&readv_cmd);
864
    }
865

    
866

    
867
    offset = cvtnum(argv[optind]);
868
    if (offset < 0) {
869
        printf("non-numeric length argument -- %s\n", argv[optind]);
870
        return 0;
871
    }
872
    optind++;
873

    
874
    if (offset & 0x1ff) {
875
        printf("offset %" PRId64 " is not sector aligned\n",
876
               offset);
877
        return 0;
878
    }
879

    
880
    nr_iov = argc - optind;
881
    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
882
    if (buf == NULL) {
883
        return 0;
884
    }
885

    
886
    gettimeofday(&t1, NULL);
887
    cnt = do_aio_readv(bs, &qiov, offset, &total);
888
    gettimeofday(&t2, NULL);
889

    
890
    if (cnt < 0) {
891
        printf("readv failed: %s\n", strerror(-cnt));
892
        goto out;
893
    }
894

    
895
    if (Pflag) {
896
        void *cmp_buf = g_malloc(qiov.size);
897
        memset(cmp_buf, pattern, qiov.size);
898
        if (memcmp(buf, cmp_buf, qiov.size)) {
899
            printf("Pattern verification failed at offset %"
900
                   PRId64 ", %zd bytes\n", offset, qiov.size);
901
        }
902
        g_free(cmp_buf);
903
    }
904

    
905
    if (qflag) {
906
        goto out;
907
    }
908

    
909
    if (vflag) {
910
        dump_buffer(buf, offset, qiov.size);
911
    }
912

    
913
    /* Finally, report back -- -C gives a parsable format */
914
    t2 = tsub(t2, t1);
915
    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
916

    
917
out:
918
    qemu_iovec_destroy(&qiov);
919
    qemu_io_free(buf);
920
    return 0;
921
}
922

    
923
static void write_help(void)
924
{
925
    printf(
926
"\n"
927
" writes a range of bytes from the given offset\n"
928
"\n"
929
" Example:\n"
930
" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
931
"\n"
932
" Writes into a segment of the currently open file, using a buffer\n"
933
" filled with a set pattern (0xcdcdcdcd).\n"
934
" -b, -- write to the VM state rather than the virtual disk\n"
935
" -c, -- write compressed data with bdrv_write_compressed\n"
936
" -p, -- use bdrv_pwrite to write the file\n"
937
" -P, -- use different pattern to fill file\n"
938
" -C, -- report statistics in a machine parsable format\n"
939
" -q, -- quiet mode, do not show I/O statistics\n"
940
" -z, -- write zeroes using bdrv_co_write_zeroes\n"
941
"\n");
942
}
943

    
944
static int write_f(BlockDriverState *bs, int argc, char **argv);
945

    
946
static const cmdinfo_t write_cmd = {
947
    .name       = "write",
948
    .altname    = "w",
949
    .cfunc      = write_f,
950
    .argmin     = 2,
951
    .argmax     = -1,
952
    .args       = "[-bcCpqz] [-P pattern ] off len",
953
    .oneline    = "writes a number of bytes at a specified offset",
954
    .help       = write_help,
955
};
956

    
957
static int write_f(BlockDriverState *bs, int argc, char **argv)
958
{
959
    struct timeval t1, t2;
960
    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
961
    int cflag = 0;
962
    int c, cnt;
963
    char *buf = NULL;
964
    int64_t offset;
965
    int count;
966
    /* Some compilers get confused and warn if this is not initialized.  */
967
    int total = 0;
968
    int pattern = 0xcd;
969

    
970
    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
971
        switch (c) {
972
        case 'b':
973
            bflag = 1;
974
            break;
975
        case 'c':
976
            cflag = 1;
977
            break;
978
        case 'C':
979
            Cflag = 1;
980
            break;
981
        case 'p':
982
            pflag = 1;
983
            break;
984
        case 'P':
985
            Pflag = 1;
986
            pattern = parse_pattern(optarg);
987
            if (pattern < 0) {
988
                return 0;
989
            }
990
            break;
991
        case 'q':
992
            qflag = 1;
993
            break;
994
        case 'z':
995
            zflag = 1;
996
            break;
997
        default:
998
            return qemuio_command_usage(&write_cmd);
999
        }
1000
    }
1001

    
1002
    if (optind != argc - 2) {
1003
        return qemuio_command_usage(&write_cmd);
1004
    }
1005

    
1006
    if (bflag + pflag + zflag > 1) {
1007
        printf("-b, -p, or -z cannot be specified at the same time\n");
1008
        return 0;
1009
    }
1010

    
1011
    if (zflag && Pflag) {
1012
        printf("-z and -P cannot be specified at the same time\n");
1013
        return 0;
1014
    }
1015

    
1016
    offset = cvtnum(argv[optind]);
1017
    if (offset < 0) {
1018
        printf("non-numeric length argument -- %s\n", argv[optind]);
1019
        return 0;
1020
    }
1021

    
1022
    optind++;
1023
    count = cvtnum(argv[optind]);
1024
    if (count < 0) {
1025
        printf("non-numeric length argument -- %s\n", argv[optind]);
1026
        return 0;
1027
    }
1028

    
1029
    if (!pflag) {
1030
        if (offset & 0x1ff) {
1031
            printf("offset %" PRId64 " is not sector aligned\n",
1032
                   offset);
1033
            return 0;
1034
        }
1035

    
1036
        if (count & 0x1ff) {
1037
            printf("count %d is not sector aligned\n",
1038
                   count);
1039
            return 0;
1040
        }
1041
    }
1042

    
1043
    if (!zflag) {
1044
        buf = qemu_io_alloc(bs, count, pattern);
1045
    }
1046

    
1047
    gettimeofday(&t1, NULL);
1048
    if (pflag) {
1049
        cnt = do_pwrite(bs, buf, offset, count, &total);
1050
    } else if (bflag) {
1051
        cnt = do_save_vmstate(bs, buf, offset, count, &total);
1052
    } else if (zflag) {
1053
        cnt = do_co_write_zeroes(bs, offset, count, &total);
1054
    } else if (cflag) {
1055
        cnt = do_write_compressed(bs, buf, offset, count, &total);
1056
    } else {
1057
        cnt = do_write(bs, buf, offset, count, &total);
1058
    }
1059
    gettimeofday(&t2, NULL);
1060

    
1061
    if (cnt < 0) {
1062
        printf("write failed: %s\n", strerror(-cnt));
1063
        goto out;
1064
    }
1065

    
1066
    if (qflag) {
1067
        goto out;
1068
    }
1069

    
1070
    /* Finally, report back -- -C gives a parsable format */
1071
    t2 = tsub(t2, t1);
1072
    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1073

    
1074
out:
1075
    if (!zflag) {
1076
        qemu_io_free(buf);
1077
    }
1078

    
1079
    return 0;
1080
}
1081

    
1082
static void
1083
writev_help(void)
1084
{
1085
    printf(
1086
"\n"
1087
" writes a range of bytes from the given offset source from multiple buffers\n"
1088
"\n"
1089
" Example:\n"
1090
" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1091
"\n"
1092
" Writes into a segment of the currently open file, using a buffer\n"
1093
" filled with a set pattern (0xcdcdcdcd).\n"
1094
" -P, -- use different pattern to fill file\n"
1095
" -C, -- report statistics in a machine parsable format\n"
1096
" -q, -- quiet mode, do not show I/O statistics\n"
1097
"\n");
1098
}
1099

    
1100
static int writev_f(BlockDriverState *bs, int argc, char **argv);
1101

    
1102
static const cmdinfo_t writev_cmd = {
1103
    .name       = "writev",
1104
    .cfunc      = writev_f,
1105
    .argmin     = 2,
1106
    .argmax     = -1,
1107
    .args       = "[-Cq] [-P pattern ] off len [len..]",
1108
    .oneline    = "writes a number of bytes at a specified offset",
1109
    .help       = writev_help,
1110
};
1111

    
1112
static int writev_f(BlockDriverState *bs, int argc, char **argv)
1113
{
1114
    struct timeval t1, t2;
1115
    int Cflag = 0, qflag = 0;
1116
    int c, cnt;
1117
    char *buf;
1118
    int64_t offset;
1119
    /* Some compilers get confused and warn if this is not initialized.  */
1120
    int total = 0;
1121
    int nr_iov;
1122
    int pattern = 0xcd;
1123
    QEMUIOVector qiov;
1124

    
1125
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1126
        switch (c) {
1127
        case 'C':
1128
            Cflag = 1;
1129
            break;
1130
        case 'q':
1131
            qflag = 1;
1132
            break;
1133
        case 'P':
1134
            pattern = parse_pattern(optarg);
1135
            if (pattern < 0) {
1136
                return 0;
1137
            }
1138
            break;
1139
        default:
1140
            return qemuio_command_usage(&writev_cmd);
1141
        }
1142
    }
1143

    
1144
    if (optind > argc - 2) {
1145
        return qemuio_command_usage(&writev_cmd);
1146
    }
1147

    
1148
    offset = cvtnum(argv[optind]);
1149
    if (offset < 0) {
1150
        printf("non-numeric length argument -- %s\n", argv[optind]);
1151
        return 0;
1152
    }
1153
    optind++;
1154

    
1155
    if (offset & 0x1ff) {
1156
        printf("offset %" PRId64 " is not sector aligned\n",
1157
               offset);
1158
        return 0;
1159
    }
1160

    
1161
    nr_iov = argc - optind;
1162
    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
1163
    if (buf == NULL) {
1164
        return 0;
1165
    }
1166

    
1167
    gettimeofday(&t1, NULL);
1168
    cnt = do_aio_writev(bs, &qiov, offset, &total);
1169
    gettimeofday(&t2, NULL);
1170

    
1171
    if (cnt < 0) {
1172
        printf("writev failed: %s\n", strerror(-cnt));
1173
        goto out;
1174
    }
1175

    
1176
    if (qflag) {
1177
        goto out;
1178
    }
1179

    
1180
    /* Finally, report back -- -C gives a parsable format */
1181
    t2 = tsub(t2, t1);
1182
    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1183
out:
1184
    qemu_iovec_destroy(&qiov);
1185
    qemu_io_free(buf);
1186
    return 0;
1187
}
1188

    
1189
static void multiwrite_help(void)
1190
{
1191
    printf(
1192
"\n"
1193
" writes a range of bytes from the given offset source from multiple buffers,\n"
1194
" in a batch of requests that may be merged by qemu\n"
1195
"\n"
1196
" Example:\n"
1197
" 'multiwrite 512 1k 1k ; 4k 1k'\n"
1198
"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
1199
"\n"
1200
" Writes into a segment of the currently open file, using a buffer\n"
1201
" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
1202
" by one for each request contained in the multiwrite command.\n"
1203
" -P, -- use different pattern to fill file\n"
1204
" -C, -- report statistics in a machine parsable format\n"
1205
" -q, -- quiet mode, do not show I/O statistics\n"
1206
"\n");
1207
}
1208

    
1209
static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
1210

    
1211
static const cmdinfo_t multiwrite_cmd = {
1212
    .name       = "multiwrite",
1213
    .cfunc      = multiwrite_f,
1214
    .argmin     = 2,
1215
    .argmax     = -1,
1216
    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
1217
    .oneline    = "issues multiple write requests at once",
1218
    .help       = multiwrite_help,
1219
};
1220

    
1221
static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
1222
{
1223
    struct timeval t1, t2;
1224
    int Cflag = 0, qflag = 0;
1225
    int c, cnt;
1226
    char **buf;
1227
    int64_t offset, first_offset = 0;
1228
    /* Some compilers get confused and warn if this is not initialized.  */
1229
    int total = 0;
1230
    int nr_iov;
1231
    int nr_reqs;
1232
    int pattern = 0xcd;
1233
    QEMUIOVector *qiovs;
1234
    int i;
1235
    BlockRequest *reqs;
1236

    
1237
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1238
        switch (c) {
1239
        case 'C':
1240
            Cflag = 1;
1241
            break;
1242
        case 'q':
1243
            qflag = 1;
1244
            break;
1245
        case 'P':
1246
            pattern = parse_pattern(optarg);
1247
            if (pattern < 0) {
1248
                return 0;
1249
            }
1250
            break;
1251
        default:
1252
            return qemuio_command_usage(&writev_cmd);
1253
        }
1254
    }
1255

    
1256
    if (optind > argc - 2) {
1257
        return qemuio_command_usage(&writev_cmd);
1258
    }
1259

    
1260
    nr_reqs = 1;
1261
    for (i = optind; i < argc; i++) {
1262
        if (!strcmp(argv[i], ";")) {
1263
            nr_reqs++;
1264
        }
1265
    }
1266

    
1267
    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1268
    buf = g_malloc0(nr_reqs * sizeof(*buf));
1269
    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1270

    
1271
    for (i = 0; i < nr_reqs && optind < argc; i++) {
1272
        int j;
1273

    
1274
        /* Read the offset of the request */
1275
        offset = cvtnum(argv[optind]);
1276
        if (offset < 0) {
1277
            printf("non-numeric offset argument -- %s\n", argv[optind]);
1278
            goto out;
1279
        }
1280
        optind++;
1281

    
1282
        if (offset & 0x1ff) {
1283
            printf("offset %lld is not sector aligned\n",
1284
                   (long long)offset);
1285
            goto out;
1286
        }
1287

    
1288
        if (i == 0) {
1289
            first_offset = offset;
1290
        }
1291

    
1292
        /* Read lengths for qiov entries */
1293
        for (j = optind; j < argc; j++) {
1294
            if (!strcmp(argv[j], ";")) {
1295
                break;
1296
            }
1297
        }
1298

    
1299
        nr_iov = j - optind;
1300

    
1301
        /* Build request */
1302
        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
1303
        if (buf[i] == NULL) {
1304
            goto out;
1305
        }
1306

    
1307
        reqs[i].qiov = &qiovs[i];
1308
        reqs[i].sector = offset >> 9;
1309
        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1310

    
1311
        optind = j + 1;
1312

    
1313
        pattern++;
1314
    }
1315

    
1316
    /* If there were empty requests at the end, ignore them */
1317
    nr_reqs = i;
1318

    
1319
    gettimeofday(&t1, NULL);
1320
    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
1321
    gettimeofday(&t2, NULL);
1322

    
1323
    if (cnt < 0) {
1324
        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1325
        goto out;
1326
    }
1327

    
1328
    if (qflag) {
1329
        goto out;
1330
    }
1331

    
1332
    /* Finally, report back -- -C gives a parsable format */
1333
    t2 = tsub(t2, t1);
1334
    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1335
out:
1336
    for (i = 0; i < nr_reqs; i++) {
1337
        qemu_io_free(buf[i]);
1338
        if (reqs[i].qiov != NULL) {
1339
            qemu_iovec_destroy(&qiovs[i]);
1340
        }
1341
    }
1342
    g_free(buf);
1343
    g_free(reqs);
1344
    g_free(qiovs);
1345
    return 0;
1346
}
1347

    
1348
struct aio_ctx {
1349
    QEMUIOVector qiov;
1350
    int64_t offset;
1351
    char *buf;
1352
    int qflag;
1353
    int vflag;
1354
    int Cflag;
1355
    int Pflag;
1356
    int pattern;
1357
    struct timeval t1;
1358
};
1359

    
1360
static void aio_write_done(void *opaque, int ret)
1361
{
1362
    struct aio_ctx *ctx = opaque;
1363
    struct timeval t2;
1364

    
1365
    gettimeofday(&t2, NULL);
1366

    
1367

    
1368
    if (ret < 0) {
1369
        printf("aio_write failed: %s\n", strerror(-ret));
1370
        goto out;
1371
    }
1372

    
1373
    if (ctx->qflag) {
1374
        goto out;
1375
    }
1376

    
1377
    /* Finally, report back -- -C gives a parsable format */
1378
    t2 = tsub(t2, ctx->t1);
1379
    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1380
                 ctx->qiov.size, 1, ctx->Cflag);
1381
out:
1382
    qemu_io_free(ctx->buf);
1383
    qemu_iovec_destroy(&ctx->qiov);
1384
    g_free(ctx);
1385
}
1386

    
1387
static void aio_read_done(void *opaque, int ret)
1388
{
1389
    struct aio_ctx *ctx = opaque;
1390
    struct timeval t2;
1391

    
1392
    gettimeofday(&t2, NULL);
1393

    
1394
    if (ret < 0) {
1395
        printf("readv failed: %s\n", strerror(-ret));
1396
        goto out;
1397
    }
1398

    
1399
    if (ctx->Pflag) {
1400
        void *cmp_buf = g_malloc(ctx->qiov.size);
1401

    
1402
        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1403
        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1404
            printf("Pattern verification failed at offset %"
1405
                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1406
        }
1407
        g_free(cmp_buf);
1408
    }
1409

    
1410
    if (ctx->qflag) {
1411
        goto out;
1412
    }
1413

    
1414
    if (ctx->vflag) {
1415
        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1416
    }
1417

    
1418
    /* Finally, report back -- -C gives a parsable format */
1419
    t2 = tsub(t2, ctx->t1);
1420
    print_report("read", &t2, ctx->offset, ctx->qiov.size,
1421
                 ctx->qiov.size, 1, ctx->Cflag);
1422
out:
1423
    qemu_io_free(ctx->buf);
1424
    qemu_iovec_destroy(&ctx->qiov);
1425
    g_free(ctx);
1426
}
1427

    
1428
static void aio_read_help(void)
1429
{
1430
    printf(
1431
"\n"
1432
" asynchronously reads a range of bytes from the given offset\n"
1433
"\n"
1434
" Example:\n"
1435
" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1436
"\n"
1437
" Reads a segment of the currently open file, optionally dumping it to the\n"
1438
" standard output stream (with -v option) for subsequent inspection.\n"
1439
" The read is performed asynchronously and the aio_flush command must be\n"
1440
" used to ensure all outstanding aio requests have been completed.\n"
1441
" -C, -- report statistics in a machine parsable format\n"
1442
" -P, -- use a pattern to verify read data\n"
1443
" -v, -- dump buffer to standard output\n"
1444
" -q, -- quiet mode, do not show I/O statistics\n"
1445
"\n");
1446
}
1447

    
1448
static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1449

    
1450
static const cmdinfo_t aio_read_cmd = {
1451
    .name       = "aio_read",
1452
    .cfunc      = aio_read_f,
1453
    .argmin     = 2,
1454
    .argmax     = -1,
1455
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
1456
    .oneline    = "asynchronously reads a number of bytes",
1457
    .help       = aio_read_help,
1458
};
1459

    
1460
static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
1461
{
1462
    int nr_iov, c;
1463
    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1464

    
1465
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1466
        switch (c) {
1467
        case 'C':
1468
            ctx->Cflag = 1;
1469
            break;
1470
        case 'P':
1471
            ctx->Pflag = 1;
1472
            ctx->pattern = parse_pattern(optarg);
1473
            if (ctx->pattern < 0) {
1474
                g_free(ctx);
1475
                return 0;
1476
            }
1477
            break;
1478
        case 'q':
1479
            ctx->qflag = 1;
1480
            break;
1481
        case 'v':
1482
            ctx->vflag = 1;
1483
            break;
1484
        default:
1485
            g_free(ctx);
1486
            return qemuio_command_usage(&aio_read_cmd);
1487
        }
1488
    }
1489

    
1490
    if (optind > argc - 2) {
1491
        g_free(ctx);
1492
        return qemuio_command_usage(&aio_read_cmd);
1493
    }
1494

    
1495
    ctx->offset = cvtnum(argv[optind]);
1496
    if (ctx->offset < 0) {
1497
        printf("non-numeric length argument -- %s\n", argv[optind]);
1498
        g_free(ctx);
1499
        return 0;
1500
    }
1501
    optind++;
1502

    
1503
    if (ctx->offset & 0x1ff) {
1504
        printf("offset %" PRId64 " is not sector aligned\n",
1505
               ctx->offset);
1506
        g_free(ctx);
1507
        return 0;
1508
    }
1509

    
1510
    nr_iov = argc - optind;
1511
    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1512
    if (ctx->buf == NULL) {
1513
        g_free(ctx);
1514
        return 0;
1515
    }
1516

    
1517
    gettimeofday(&ctx->t1, NULL);
1518
    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1519
                   ctx->qiov.size >> 9, aio_read_done, ctx);
1520
    return 0;
1521
}
1522

    
1523
static void aio_write_help(void)
1524
{
1525
    printf(
1526
"\n"
1527
" asynchronously writes a range of bytes from the given offset source\n"
1528
" from multiple buffers\n"
1529
"\n"
1530
" Example:\n"
1531
" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1532
"\n"
1533
" Writes into a segment of the currently open file, using a buffer\n"
1534
" filled with a set pattern (0xcdcdcdcd).\n"
1535
" The write is performed asynchronously and the aio_flush command must be\n"
1536
" used to ensure all outstanding aio requests have been completed.\n"
1537
" -P, -- use different pattern to fill file\n"
1538
" -C, -- report statistics in a machine parsable format\n"
1539
" -q, -- quiet mode, do not show I/O statistics\n"
1540
"\n");
1541
}
1542

    
1543
static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1544

    
1545
static const cmdinfo_t aio_write_cmd = {
1546
    .name       = "aio_write",
1547
    .cfunc      = aio_write_f,
1548
    .argmin     = 2,
1549
    .argmax     = -1,
1550
    .args       = "[-Cq] [-P pattern ] off len [len..]",
1551
    .oneline    = "asynchronously writes a number of bytes",
1552
    .help       = aio_write_help,
1553
};
1554

    
1555
static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
1556
{
1557
    int nr_iov, c;
1558
    int pattern = 0xcd;
1559
    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1560

    
1561
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1562
        switch (c) {
1563
        case 'C':
1564
            ctx->Cflag = 1;
1565
            break;
1566
        case 'q':
1567
            ctx->qflag = 1;
1568
            break;
1569
        case 'P':
1570
            pattern = parse_pattern(optarg);
1571
            if (pattern < 0) {
1572
                g_free(ctx);
1573
                return 0;
1574
            }
1575
            break;
1576
        default:
1577
            g_free(ctx);
1578
            return qemuio_command_usage(&aio_write_cmd);
1579
        }
1580
    }
1581

    
1582
    if (optind > argc - 2) {
1583
        g_free(ctx);
1584
        return qemuio_command_usage(&aio_write_cmd);
1585
    }
1586

    
1587
    ctx->offset = cvtnum(argv[optind]);
1588
    if (ctx->offset < 0) {
1589
        printf("non-numeric length argument -- %s\n", argv[optind]);
1590
        g_free(ctx);
1591
        return 0;
1592
    }
1593
    optind++;
1594

    
1595
    if (ctx->offset & 0x1ff) {
1596
        printf("offset %" PRId64 " is not sector aligned\n",
1597
               ctx->offset);
1598
        g_free(ctx);
1599
        return 0;
1600
    }
1601

    
1602
    nr_iov = argc - optind;
1603
    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
1604
    if (ctx->buf == NULL) {
1605
        g_free(ctx);
1606
        return 0;
1607
    }
1608

    
1609
    gettimeofday(&ctx->t1, NULL);
1610
    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1611
                    ctx->qiov.size >> 9, aio_write_done, ctx);
1612
    return 0;
1613
}
1614

    
1615
static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1616
{
1617
    bdrv_drain_all();
1618
    return 0;
1619
}
1620

    
1621
static const cmdinfo_t aio_flush_cmd = {
1622
    .name       = "aio_flush",
1623
    .cfunc      = aio_flush_f,
1624
    .oneline    = "completes all outstanding aio requests"
1625
};
1626

    
1627
static int flush_f(BlockDriverState *bs, int argc, char **argv)
1628
{
1629
    bdrv_flush(bs);
1630
    return 0;
1631
}
1632

    
1633
static const cmdinfo_t flush_cmd = {
1634
    .name       = "flush",
1635
    .altname    = "f",
1636
    .cfunc      = flush_f,
1637
    .oneline    = "flush all in-core file state to disk",
1638
};
1639

    
1640
static int truncate_f(BlockDriverState *bs, int argc, char **argv)
1641
{
1642
    int64_t offset;
1643
    int ret;
1644

    
1645
    offset = cvtnum(argv[1]);
1646
    if (offset < 0) {
1647
        printf("non-numeric truncate argument -- %s\n", argv[1]);
1648
        return 0;
1649
    }
1650

    
1651
    ret = bdrv_truncate(bs, offset);
1652
    if (ret < 0) {
1653
        printf("truncate: %s\n", strerror(-ret));
1654
        return 0;
1655
    }
1656

    
1657
    return 0;
1658
}
1659

    
1660
static const cmdinfo_t truncate_cmd = {
1661
    .name       = "truncate",
1662
    .altname    = "t",
1663
    .cfunc      = truncate_f,
1664
    .argmin     = 1,
1665
    .argmax     = 1,
1666
    .args       = "off",
1667
    .oneline    = "truncates the current file at the given offset",
1668
};
1669

    
1670
static int length_f(BlockDriverState *bs, int argc, char **argv)
1671
{
1672
    int64_t size;
1673
    char s1[64];
1674

    
1675
    size = bdrv_getlength(bs);
1676
    if (size < 0) {
1677
        printf("getlength: %s\n", strerror(-size));
1678
        return 0;
1679
    }
1680

    
1681
    cvtstr(size, s1, sizeof(s1));
1682
    printf("%s\n", s1);
1683
    return 0;
1684
}
1685

    
1686

    
1687
static const cmdinfo_t length_cmd = {
1688
    .name   = "length",
1689
    .altname    = "l",
1690
    .cfunc      = length_f,
1691
    .oneline    = "gets the length of the current file",
1692
};
1693

    
1694

    
1695
static int info_f(BlockDriverState *bs, int argc, char **argv)
1696
{
1697
    BlockDriverInfo bdi;
1698
    ImageInfoSpecific *spec_info;
1699
    char s1[64], s2[64];
1700
    int ret;
1701

    
1702
    if (bs->drv && bs->drv->format_name) {
1703
        printf("format name: %s\n", bs->drv->format_name);
1704
    }
1705
    if (bs->drv && bs->drv->protocol_name) {
1706
        printf("format name: %s\n", bs->drv->protocol_name);
1707
    }
1708

    
1709
    ret = bdrv_get_info(bs, &bdi);
1710
    if (ret) {
1711
        return 0;
1712
    }
1713

    
1714
    cvtstr(bdi.cluster_size, s1, sizeof(s1));
1715
    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1716

    
1717
    printf("cluster size: %s\n", s1);
1718
    printf("vm state offset: %s\n", s2);
1719

    
1720
    spec_info = bdrv_get_specific_info(bs);
1721
    if (spec_info) {
1722
        printf("Format specific information:\n");
1723
        bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
1724
        qapi_free_ImageInfoSpecific(spec_info);
1725
    }
1726

    
1727
    return 0;
1728
}
1729

    
1730

    
1731

    
1732
static const cmdinfo_t info_cmd = {
1733
    .name       = "info",
1734
    .altname    = "i",
1735
    .cfunc      = info_f,
1736
    .oneline    = "prints information about the current file",
1737
};
1738

    
1739
static void discard_help(void)
1740
{
1741
    printf(
1742
"\n"
1743
" discards a range of bytes from the given offset\n"
1744
"\n"
1745
" Example:\n"
1746
" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1747
"\n"
1748
" Discards a segment of the currently open file.\n"
1749
" -C, -- report statistics in a machine parsable format\n"
1750
" -q, -- quiet mode, do not show I/O statistics\n"
1751
"\n");
1752
}
1753

    
1754
static int discard_f(BlockDriverState *bs, int argc, char **argv);
1755

    
1756
static const cmdinfo_t discard_cmd = {
1757
    .name       = "discard",
1758
    .altname    = "d",
1759
    .cfunc      = discard_f,
1760
    .argmin     = 2,
1761
    .argmax     = -1,
1762
    .args       = "[-Cq] off len",
1763
    .oneline    = "discards a number of bytes at a specified offset",
1764
    .help       = discard_help,
1765
};
1766

    
1767
static int discard_f(BlockDriverState *bs, int argc, char **argv)
1768
{
1769
    struct timeval t1, t2;
1770
    int Cflag = 0, qflag = 0;
1771
    int c, ret;
1772
    int64_t offset;
1773
    int count;
1774

    
1775
    while ((c = getopt(argc, argv, "Cq")) != EOF) {
1776
        switch (c) {
1777
        case 'C':
1778
            Cflag = 1;
1779
            break;
1780
        case 'q':
1781
            qflag = 1;
1782
            break;
1783
        default:
1784
            return qemuio_command_usage(&discard_cmd);
1785
        }
1786
    }
1787

    
1788
    if (optind != argc - 2) {
1789
        return qemuio_command_usage(&discard_cmd);
1790
    }
1791

    
1792
    offset = cvtnum(argv[optind]);
1793
    if (offset < 0) {
1794
        printf("non-numeric length argument -- %s\n", argv[optind]);
1795
        return 0;
1796
    }
1797

    
1798
    optind++;
1799
    count = cvtnum(argv[optind]);
1800
    if (count < 0) {
1801
        printf("non-numeric length argument -- %s\n", argv[optind]);
1802
        return 0;
1803
    }
1804

    
1805
    gettimeofday(&t1, NULL);
1806
    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1807
                       count >> BDRV_SECTOR_BITS);
1808
    gettimeofday(&t2, NULL);
1809

    
1810
    if (ret < 0) {
1811
        printf("discard failed: %s\n", strerror(-ret));
1812
        goto out;
1813
    }
1814

    
1815
    /* Finally, report back -- -C gives a parsable format */
1816
    if (!qflag) {
1817
        t2 = tsub(t2, t1);
1818
        print_report("discard", &t2, offset, count, count, 1, Cflag);
1819
    }
1820

    
1821
out:
1822
    return 0;
1823
}
1824

    
1825
static int alloc_f(BlockDriverState *bs, int argc, char **argv)
1826
{
1827
    int64_t offset, sector_num;
1828
    int nb_sectors, remaining;
1829
    char s1[64];
1830
    int num, sum_alloc;
1831
    int ret;
1832

    
1833
    offset = cvtnum(argv[1]);
1834
    if (offset < 0) {
1835
        printf("non-numeric offset argument -- %s\n", argv[1]);
1836
        return 0;
1837
    } else if (offset & 0x1ff) {
1838
        printf("offset %" PRId64 " is not sector aligned\n",
1839
               offset);
1840
        return 0;
1841
    }
1842

    
1843
    if (argc == 3) {
1844
        nb_sectors = cvtnum(argv[2]);
1845
        if (nb_sectors < 0) {
1846
            printf("non-numeric length argument -- %s\n", argv[2]);
1847
            return 0;
1848
        }
1849
    } else {
1850
        nb_sectors = 1;
1851
    }
1852

    
1853
    remaining = nb_sectors;
1854
    sum_alloc = 0;
1855
    sector_num = offset >> 9;
1856
    while (remaining) {
1857
        ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1858
        if (ret < 0) {
1859
            printf("is_allocated failed: %s\n", strerror(-ret));
1860
            return 0;
1861
        }
1862
        sector_num += num;
1863
        remaining -= num;
1864
        if (ret) {
1865
            sum_alloc += num;
1866
        }
1867
        if (num == 0) {
1868
            nb_sectors -= remaining;
1869
            remaining = 0;
1870
        }
1871
    }
1872

    
1873
    cvtstr(offset, s1, sizeof(s1));
1874

    
1875
    printf("%d/%d sectors allocated at offset %s\n",
1876
           sum_alloc, nb_sectors, s1);
1877
    return 0;
1878
}
1879

    
1880
static const cmdinfo_t alloc_cmd = {
1881
    .name       = "alloc",
1882
    .altname    = "a",
1883
    .argmin     = 1,
1884
    .argmax     = 2,
1885
    .cfunc      = alloc_f,
1886
    .args       = "off [sectors]",
1887
    .oneline    = "checks if a sector is present in the file",
1888
};
1889

    
1890

    
1891
static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
1892
                            int64_t nb_sectors, int64_t *pnum)
1893
{
1894
    int num, num_checked;
1895
    int ret, firstret;
1896

    
1897
    num_checked = MIN(nb_sectors, INT_MAX);
1898
    ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1899
    if (ret < 0) {
1900
        return ret;
1901
    }
1902

    
1903
    firstret = ret;
1904
    *pnum = num;
1905

    
1906
    while (nb_sectors > 0 && ret == firstret) {
1907
        sector_num += num;
1908
        nb_sectors -= num;
1909

    
1910
        num_checked = MIN(nb_sectors, INT_MAX);
1911
        ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1912
        if (ret == firstret) {
1913
            *pnum += num;
1914
        } else {
1915
            break;
1916
        }
1917
    }
1918

    
1919
    return firstret;
1920
}
1921

    
1922
static int map_f(BlockDriverState *bs, int argc, char **argv)
1923
{
1924
    int64_t offset;
1925
    int64_t nb_sectors;
1926
    char s1[64];
1927
    int64_t num;
1928
    int ret;
1929
    const char *retstr;
1930

    
1931
    offset = 0;
1932
    nb_sectors = bs->total_sectors;
1933

    
1934
    do {
1935
        ret = map_is_allocated(bs, offset, nb_sectors, &num);
1936
        if (ret < 0) {
1937
            error_report("Failed to get allocation status: %s", strerror(-ret));
1938
            return 0;
1939
        }
1940

    
1941
        retstr = ret ? "    allocated" : "not allocated";
1942
        cvtstr(offset << 9ULL, s1, sizeof(s1));
1943
        printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
1944
               "at offset %s (%d)\n",
1945
               offset << 9ULL, num, nb_sectors, retstr, s1, ret);
1946

    
1947
        offset += num;
1948
        nb_sectors -= num;
1949
    } while (offset < bs->total_sectors);
1950

    
1951
    return 0;
1952
}
1953

    
1954
static const cmdinfo_t map_cmd = {
1955
       .name           = "map",
1956
       .argmin         = 0,
1957
       .argmax         = 0,
1958
       .cfunc          = map_f,
1959
       .args           = "",
1960
       .oneline        = "prints the allocated areas of a file",
1961
};
1962

    
1963
static int break_f(BlockDriverState *bs, int argc, char **argv)
1964
{
1965
    int ret;
1966

    
1967
    ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1968
    if (ret < 0) {
1969
        printf("Could not set breakpoint: %s\n", strerror(-ret));
1970
    }
1971

    
1972
    return 0;
1973
}
1974

    
1975
static int remove_break_f(BlockDriverState *bs, int argc, char **argv)
1976
{
1977
    int ret;
1978

    
1979
    ret = bdrv_debug_remove_breakpoint(bs, argv[1]);
1980
    if (ret < 0) {
1981
        printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
1982
    }
1983

    
1984
    return 0;
1985
}
1986

    
1987
static const cmdinfo_t break_cmd = {
1988
       .name           = "break",
1989
       .argmin         = 2,
1990
       .argmax         = 2,
1991
       .cfunc          = break_f,
1992
       .args           = "event tag",
1993
       .oneline        = "sets a breakpoint on event and tags the stopped "
1994
                         "request as tag",
1995
};
1996

    
1997
static const cmdinfo_t remove_break_cmd = {
1998
       .name           = "remove_break",
1999
       .argmin         = 1,
2000
       .argmax         = 1,
2001
       .cfunc          = remove_break_f,
2002
       .args           = "tag",
2003
       .oneline        = "remove a breakpoint by tag",
2004
};
2005

    
2006
static int resume_f(BlockDriverState *bs, int argc, char **argv)
2007
{
2008
    int ret;
2009

    
2010
    ret = bdrv_debug_resume(bs, argv[1]);
2011
    if (ret < 0) {
2012
        printf("Could not resume request: %s\n", strerror(-ret));
2013
    }
2014

    
2015
    return 0;
2016
}
2017

    
2018
static const cmdinfo_t resume_cmd = {
2019
       .name           = "resume",
2020
       .argmin         = 1,
2021
       .argmax         = 1,
2022
       .cfunc          = resume_f,
2023
       .args           = "tag",
2024
       .oneline        = "resumes the request tagged as tag",
2025
};
2026

    
2027
static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
2028
{
2029
    while (!bdrv_debug_is_suspended(bs, argv[1])) {
2030
        qemu_aio_wait();
2031
    }
2032

    
2033
    return 0;
2034
}
2035

    
2036
static const cmdinfo_t wait_break_cmd = {
2037
       .name           = "wait_break",
2038
       .argmin         = 1,
2039
       .argmax         = 1,
2040
       .cfunc          = wait_break_f,
2041
       .args           = "tag",
2042
       .oneline        = "waits for the suspension of a request",
2043
};
2044

    
2045
static int abort_f(BlockDriverState *bs, int argc, char **argv)
2046
{
2047
    abort();
2048
}
2049

    
2050
static const cmdinfo_t abort_cmd = {
2051
       .name           = "abort",
2052
       .cfunc          = abort_f,
2053
       .flags          = CMD_NOFILE_OK,
2054
       .oneline        = "simulate a program crash using abort(3)",
2055
};
2056

    
2057
static void sleep_cb(void *opaque)
2058
{
2059
    bool *expired = opaque;
2060
    *expired = true;
2061
}
2062

    
2063
static int sleep_f(BlockDriverState *bs, int argc, char **argv)
2064
{
2065
    char *endptr;
2066
    long ms;
2067
    struct QEMUTimer *timer;
2068
    bool expired = false;
2069

    
2070
    ms = strtol(argv[1], &endptr, 0);
2071
    if (ms < 0 || *endptr != '\0') {
2072
        printf("%s is not a valid number\n", argv[1]);
2073
        return 0;
2074
    }
2075

    
2076
    timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2077
    timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2078

    
2079
    while (!expired) {
2080
        main_loop_wait(false);
2081
    }
2082

    
2083
    timer_free(timer);
2084

    
2085
    return 0;
2086
}
2087

    
2088
static const cmdinfo_t sleep_cmd = {
2089
       .name           = "sleep",
2090
       .argmin         = 1,
2091
       .argmax         = 1,
2092
       .cfunc          = sleep_f,
2093
       .flags          = CMD_NOFILE_OK,
2094
       .oneline        = "waits for the given value in milliseconds",
2095
};
2096

    
2097
static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2098
{
2099
    if (cmd) {
2100
        printf("%s ", cmd);
2101
    } else {
2102
        printf("%s ", ct->name);
2103
        if (ct->altname) {
2104
            printf("(or %s) ", ct->altname);
2105
        }
2106
    }
2107

    
2108
    if (ct->args) {
2109
        printf("%s ", ct->args);
2110
    }
2111
    printf("-- %s\n", ct->oneline);
2112
}
2113

    
2114
static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2115
{
2116
    help_oneline(cmd, ct);
2117
    if (ct->help) {
2118
        ct->help();
2119
    }
2120
}
2121

    
2122
static void help_all(void)
2123
{
2124
    const cmdinfo_t *ct;
2125

    
2126
    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2127
        help_oneline(ct->name, ct);
2128
    }
2129
    printf("\nUse 'help commandname' for extended help.\n");
2130
}
2131

    
2132
static int help_f(BlockDriverState *bs, int argc, char **argv)
2133
{
2134
    const cmdinfo_t *ct;
2135

    
2136
    if (argc == 1) {
2137
        help_all();
2138
        return 0;
2139
    }
2140

    
2141
    ct = find_command(argv[1]);
2142
    if (ct == NULL) {
2143
        printf("command %s not found\n", argv[1]);
2144
        return 0;
2145
    }
2146

    
2147
    help_onecmd(argv[1], ct);
2148
    return 0;
2149
}
2150

    
2151
static const cmdinfo_t help_cmd = {
2152
    .name       = "help",
2153
    .altname    = "?",
2154
    .cfunc      = help_f,
2155
    .argmin     = 0,
2156
    .argmax     = 1,
2157
    .flags      = CMD_FLAG_GLOBAL,
2158
    .args       = "[command]",
2159
    .oneline    = "help for one or all commands",
2160
};
2161

    
2162
bool qemuio_command(BlockDriverState *bs, const char *cmd)
2163
{
2164
    char *input;
2165
    const cmdinfo_t *ct;
2166
    char **v;
2167
    int c;
2168
    bool done = false;
2169

    
2170
    input = g_strdup(cmd);
2171
    v = breakline(input, &c);
2172
    if (c) {
2173
        ct = find_command(v[0]);
2174
        if (ct) {
2175
            done = command(bs, ct, c, v);
2176
        } else {
2177
            fprintf(stderr, "command \"%s\" not found\n", v[0]);
2178
        }
2179
    }
2180
    g_free(input);
2181
    g_free(v);
2182

    
2183
    return done;
2184
}
2185

    
2186
static void __attribute((constructor)) init_qemuio_commands(void)
2187
{
2188
    /* initialize commands */
2189
    qemuio_add_command(&help_cmd);
2190
    qemuio_add_command(&read_cmd);
2191
    qemuio_add_command(&readv_cmd);
2192
    qemuio_add_command(&write_cmd);
2193
    qemuio_add_command(&writev_cmd);
2194
    qemuio_add_command(&multiwrite_cmd);
2195
    qemuio_add_command(&aio_read_cmd);
2196
    qemuio_add_command(&aio_write_cmd);
2197
    qemuio_add_command(&aio_flush_cmd);
2198
    qemuio_add_command(&flush_cmd);
2199
    qemuio_add_command(&truncate_cmd);
2200
    qemuio_add_command(&length_cmd);
2201
    qemuio_add_command(&info_cmd);
2202
    qemuio_add_command(&discard_cmd);
2203
    qemuio_add_command(&alloc_cmd);
2204
    qemuio_add_command(&map_cmd);
2205
    qemuio_add_command(&break_cmd);
2206
    qemuio_add_command(&remove_break_cmd);
2207
    qemuio_add_command(&resume_cmd);
2208
    qemuio_add_command(&wait_break_cmd);
2209
    qemuio_add_command(&abort_cmd);
2210
    qemuio_add_command(&sleep_cmd);
2211
}