Statistics
| Branch: | Revision:

root / qemu-io-cmds.c @ 6a1751b7

History | View | Annotate | Download (51.9 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 "qemu/main-loop.h"
14

    
15
#define CMD_NOFILE_OK   0x01
16

    
17
int qemuio_misalign;
18

    
19
static cmdinfo_t *cmdtab;
20
static int ncmds;
21

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

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

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

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

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

    
58
    if (!init_check_command(bs, ct)) {
59
        return 0;
60
    }
61

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

    
82
static const cmdinfo_t *find_command(const char *cmd)
83
{
84
    cmdinfo_t *ct;
85

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

    
96
static char **breakline(char *input, int *count)
97
{
98
    int c = 0;
99
    char *p;
100
    char **rval = g_malloc0(sizeof(char *));
101
    char **tmp;
102

    
103
    while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
104
        if (!*p) {
105
            continue;
106
        }
107
        c++;
108
        tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
109
        if (!tmp) {
110
            g_free(rval);
111
            rval = NULL;
112
            c = 0;
113
            break;
114
        } else {
115
            rval = tmp;
116
        }
117
        rval[c - 1] = p;
118
        rval[c] = NULL;
119
    }
120
    *count = c;
121
    return rval;
122
}
123

    
124
static int64_t cvtnum(const char *s)
125
{
126
    char *end;
127
    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
128
}
129

    
130
#define EXABYTES(x)     ((long long)(x) << 60)
131
#define PETABYTES(x)    ((long long)(x) << 50)
132
#define TERABYTES(x)    ((long long)(x) << 40)
133
#define GIGABYTES(x)    ((long long)(x) << 30)
134
#define MEGABYTES(x)    ((long long)(x) << 20)
135
#define KILOBYTES(x)    ((long long)(x) << 10)
136

    
137
#define TO_EXABYTES(x)  ((x) / EXABYTES(1))
138
#define TO_PETABYTES(x) ((x) / PETABYTES(1))
139
#define TO_TERABYTES(x) ((x) / TERABYTES(1))
140
#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
141
#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
142
#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
143

    
144
static void cvtstr(double value, char *str, size_t size)
145
{
146
    char *trim;
147
    const char *suffix;
148

    
149
    if (value >= EXABYTES(1)) {
150
        suffix = " EiB";
151
        snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
152
    } else if (value >= PETABYTES(1)) {
153
        suffix = " PiB";
154
        snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
155
    } else if (value >= TERABYTES(1)) {
156
        suffix = " TiB";
157
        snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
158
    } else if (value >= GIGABYTES(1)) {
159
        suffix = " GiB";
160
        snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
161
    } else if (value >= MEGABYTES(1)) {
162
        suffix = " MiB";
163
        snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
164
    } else if (value >= KILOBYTES(1)) {
165
        suffix = " KiB";
166
        snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
167
    } else {
168
        suffix = " bytes";
169
        snprintf(str, size - 6, "%f", value);
170
    }
171

    
172
    trim = strstr(str, ".000");
173
    if (trim) {
174
        strcpy(trim, suffix);
175
    } else {
176
        strcat(str, suffix);
177
    }
178
}
179

    
180

    
181

    
182
static struct timeval tsub(struct timeval t1, struct timeval t2)
183
{
184
    t1.tv_usec -= t2.tv_usec;
185
    if (t1.tv_usec < 0) {
186
        t1.tv_usec += 1000000;
187
        t1.tv_sec--;
188
    }
189
    t1.tv_sec -= t2.tv_sec;
190
    return t1;
191
}
192

    
193
static double tdiv(double value, struct timeval tv)
194
{
195
    return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
196
}
197

    
198
#define HOURS(sec)      ((sec) / (60 * 60))
199
#define MINUTES(sec)    (((sec) % (60 * 60)) / 60)
200
#define SECONDS(sec)    ((sec) % 60)
201

    
202
enum {
203
    DEFAULT_TIME        = 0x0,
204
    TERSE_FIXED_TIME    = 0x1,
205
    VERBOSE_FIXED_TIME  = 0x2,
206
};
207

    
208
static void timestr(struct timeval *tv, char *ts, size_t size, int format)
209
{
210
    double usec = (double)tv->tv_usec / 1000000.0;
211

    
212
    if (format & TERSE_FIXED_TIME) {
213
        if (!HOURS(tv->tv_sec)) {
214
            snprintf(ts, size, "%u:%02u.%02u",
215
                    (unsigned int) MINUTES(tv->tv_sec),
216
                    (unsigned int) SECONDS(tv->tv_sec),
217
                    (unsigned int) (usec * 100));
218
            return;
219
        }
220
        format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
221
    }
222

    
223
    if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
224
        snprintf(ts, size, "%u:%02u:%02u.%02u",
225
                (unsigned int) HOURS(tv->tv_sec),
226
                (unsigned int) MINUTES(tv->tv_sec),
227
                (unsigned int) SECONDS(tv->tv_sec),
228
                (unsigned int) (usec * 100));
229
    } else {
230
        snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
231
    }
232
}
233

    
234
/*
235
 * Parse the pattern argument to various sub-commands.
236
 *
237
 * Because the pattern is used as an argument to memset it must evaluate
238
 * to an unsigned integer that fits into a single byte.
239
 */
240
static int parse_pattern(const char *arg)
241
{
242
    char *endptr = NULL;
243
    long pattern;
244

    
245
    pattern = strtol(arg, &endptr, 0);
246
    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
247
        printf("%s is not a valid pattern byte\n", arg);
248
        return -1;
249
    }
250

    
251
    return pattern;
252
}
253

    
254
/*
255
 * Memory allocation helpers.
256
 *
257
 * Make sure memory is aligned by default, or purposefully misaligned if
258
 * that is specified on the command line.
259
 */
260

    
261
#define MISALIGN_OFFSET     16
262
static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
263
{
264
    void *buf;
265

    
266
    if (qemuio_misalign) {
267
        len += MISALIGN_OFFSET;
268
    }
269
    buf = qemu_blockalign(bs, len);
270
    memset(buf, pattern, len);
271
    if (qemuio_misalign) {
272
        buf += MISALIGN_OFFSET;
273
    }
274
    return buf;
275
}
276

    
277
static void qemu_io_free(void *p)
278
{
279
    if (qemuio_misalign) {
280
        p -= MISALIGN_OFFSET;
281
    }
282
    qemu_vfree(p);
283
}
284

    
285
static void dump_buffer(const void *buffer, int64_t offset, int len)
286
{
287
    int i, j;
288
    const uint8_t *p;
289

    
290
    for (i = 0, p = buffer; i < len; i += 16) {
291
        const uint8_t *s = p;
292

    
293
        printf("%08" PRIx64 ":  ", offset + i);
294
        for (j = 0; j < 16 && i + j < len; j++, p++) {
295
            printf("%02x ", *p);
296
        }
297
        printf(" ");
298
        for (j = 0; j < 16 && i + j < len; j++, s++) {
299
            if (isalnum(*s)) {
300
                printf("%c", *s);
301
            } else {
302
                printf(".");
303
            }
304
        }
305
        printf("\n");
306
    }
307
}
308

    
309
static void print_report(const char *op, struct timeval *t, int64_t offset,
310
                         int count, int total, int cnt, int Cflag)
311
{
312
    char s1[64], s2[64], ts[64];
313

    
314
    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
315
    if (!Cflag) {
316
        cvtstr((double)total, s1, sizeof(s1));
317
        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
318
        printf("%s %d/%d bytes at offset %" PRId64 "\n",
319
               op, total, count, offset);
320
        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
321
               s1, cnt, ts, s2, tdiv((double)cnt, *t));
322
    } else {/* bytes,ops,time,bytes/sec,ops/sec */
323
        printf("%d,%d,%s,%.3f,%.3f\n",
324
            total, cnt, ts,
325
            tdiv((double)total, *t),
326
            tdiv((double)cnt, *t));
327
    }
328
}
329

    
330
/*
331
 * Parse multiple length statements for vectored I/O, and construct an I/O
332
 * vector matching it.
333
 */
334
static void *
335
create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
336
             int pattern)
337
{
338
    size_t *sizes = g_new0(size_t, nr_iov);
339
    size_t count = 0;
340
    void *buf = NULL;
341
    void *p;
342
    int i;
343

    
344
    for (i = 0; i < nr_iov; i++) {
345
        char *arg = argv[i];
346
        int64_t len;
347

    
348
        len = cvtnum(arg);
349
        if (len < 0) {
350
            printf("non-numeric length argument -- %s\n", arg);
351
            goto fail;
352
        }
353

    
354
        /* should be SIZE_T_MAX, but that doesn't exist */
355
        if (len > INT_MAX) {
356
            printf("too large length argument -- %s\n", arg);
357
            goto fail;
358
        }
359

    
360
        if (len & 0x1ff) {
361
            printf("length argument %" PRId64
362
                   " is not sector aligned\n", len);
363
            goto fail;
364
        }
365

    
366
        sizes[i] = len;
367
        count += len;
368
    }
369

    
370
    qemu_iovec_init(qiov, nr_iov);
371

    
372
    buf = p = qemu_io_alloc(bs, count, pattern);
373

    
374
    for (i = 0; i < nr_iov; i++) {
375
        qemu_iovec_add(qiov, p, sizes[i]);
376
        p += sizes[i];
377
    }
378

    
379
fail:
380
    g_free(sizes);
381
    return buf;
382
}
383

    
384
static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
385
                   int *total)
386
{
387
    int ret;
388

    
389
    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
390
    if (ret < 0) {
391
        return ret;
392
    }
393
    *total = count;
394
    return 1;
395
}
396

    
397
static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
398
                    int *total)
399
{
400
    int ret;
401

    
402
    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
403
    if (ret < 0) {
404
        return ret;
405
    }
406
    *total = count;
407
    return 1;
408
}
409

    
410
static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
411
                    int *total)
412
{
413
    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
414
    if (*total < 0) {
415
        return *total;
416
    }
417
    return 1;
418
}
419

    
420
static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
421
                     int *total)
422
{
423
    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
424
    if (*total < 0) {
425
        return *total;
426
    }
427
    return 1;
428
}
429

    
430
typedef struct {
431
    BlockDriverState *bs;
432
    int64_t offset;
433
    int count;
434
    int *total;
435
    int ret;
436
    bool done;
437
} CoWriteZeroes;
438

    
439
static void coroutine_fn co_write_zeroes_entry(void *opaque)
440
{
441
    CoWriteZeroes *data = opaque;
442

    
443
    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
444
                                     data->count / BDRV_SECTOR_SIZE);
445
    data->done = true;
446
    if (data->ret < 0) {
447
        *data->total = data->ret;
448
        return;
449
    }
450

    
451
    *data->total = data->count;
452
}
453

    
454
static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
455
                              int *total)
456
{
457
    Coroutine *co;
458
    CoWriteZeroes data = {
459
        .bs     = bs,
460
        .offset = offset,
461
        .count  = count,
462
        .total  = total,
463
        .done   = false,
464
    };
465

    
466
    co = qemu_coroutine_create(co_write_zeroes_entry);
467
    qemu_coroutine_enter(co, &data);
468
    while (!data.done) {
469
        qemu_aio_wait();
470
    }
471
    if (data.ret < 0) {
472
        return data.ret;
473
    } else {
474
        return 1;
475
    }
476
}
477

    
478
static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
479
                               int count, int *total)
480
{
481
    int ret;
482

    
483
    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
484
    if (ret < 0) {
485
        return ret;
486
    }
487
    *total = count;
488
    return 1;
489
}
490

    
491
static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
492
                           int count, int *total)
493
{
494
    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
495
    if (*total < 0) {
496
        return *total;
497
    }
498
    return 1;
499
}
500

    
501
static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
502
                           int count, int *total)
503
{
504
    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
505
    if (*total < 0) {
506
        return *total;
507
    }
508
    return 1;
509
}
510

    
511
#define NOT_DONE 0x7fffffff
512
static void aio_rw_done(void *opaque, int ret)
513
{
514
    *(int *)opaque = ret;
515
}
516

    
517
static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
518
                        int64_t offset, int *total)
519
{
520
    int async_ret = NOT_DONE;
521

    
522
    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
523
                   aio_rw_done, &async_ret);
524
    while (async_ret == NOT_DONE) {
525
        main_loop_wait(false);
526
    }
527

    
528
    *total = qiov->size;
529
    return async_ret < 0 ? async_ret : 1;
530
}
531

    
532
static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
533
                         int64_t offset, int *total)
534
{
535
    int async_ret = NOT_DONE;
536

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

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

    
547
struct multiwrite_async_ret {
548
    int num_done;
549
    int error;
550
};
551

    
552
static void multiwrite_cb(void *opaque, int ret)
553
{
554
    struct multiwrite_async_ret *async_ret = opaque;
555

    
556
    async_ret->num_done++;
557
    if (ret < 0) {
558
        async_ret->error = ret;
559
    }
560
}
561

    
562
static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
563
                             int num_reqs, int *total)
564
{
565
    int i, ret;
566
    struct multiwrite_async_ret async_ret = {
567
        .num_done = 0,
568
        .error = 0,
569
    };
570

    
571
    *total = 0;
572
    for (i = 0; i < num_reqs; i++) {
573
        reqs[i].cb = multiwrite_cb;
574
        reqs[i].opaque = &async_ret;
575
        *total += reqs[i].qiov->size;
576
    }
577

    
578
    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
579
    if (ret < 0) {
580
        return ret;
581
    }
582

    
583
    while (async_ret.num_done < num_reqs) {
584
        main_loop_wait(false);
585
    }
586

    
587
    return async_ret.error < 0 ? async_ret.error : 1;
588
}
589

    
590
static void read_help(void)
591
{
592
    printf(
593
"\n"
594
" reads a range of bytes from the given offset\n"
595
"\n"
596
" Example:\n"
597
" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
598
"\n"
599
" Reads a segment of the currently open file, optionally dumping it to the\n"
600
" standard output stream (with -v option) for subsequent inspection.\n"
601
" -b, -- read from the VM state rather than the virtual disk\n"
602
" -C, -- report statistics in a machine parsable format\n"
603
" -l, -- length for pattern verification (only with -P)\n"
604
" -p, -- use bdrv_pread to read the file\n"
605
" -P, -- use a pattern to verify read data\n"
606
" -q, -- quiet mode, do not show I/O statistics\n"
607
" -s, -- start offset for pattern verification (only with -P)\n"
608
" -v, -- dump buffer to standard output\n"
609
"\n");
610
}
611

    
612
static int read_f(BlockDriverState *bs, int argc, char **argv);
613

    
614
static const cmdinfo_t read_cmd = {
615
    .name       = "read",
616
    .altname    = "r",
617
    .cfunc      = read_f,
618
    .argmin     = 2,
619
    .argmax     = -1,
620
    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
621
    .oneline    = "reads a number of bytes at a specified offset",
622
    .help       = read_help,
623
};
624

    
625
static int read_f(BlockDriverState *bs, int argc, char **argv)
626
{
627
    struct timeval t1, t2;
628
    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
629
    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
630
    int c, cnt;
631
    char *buf;
632
    int64_t offset;
633
    int count;
634
    /* Some compilers get confused and warn if this is not initialized.  */
635
    int total = 0;
636
    int pattern = 0, pattern_offset = 0, pattern_count = 0;
637

    
638
    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
639
        switch (c) {
640
        case 'b':
641
            bflag = 1;
642
            break;
643
        case 'C':
644
            Cflag = 1;
645
            break;
646
        case 'l':
647
            lflag = 1;
648
            pattern_count = cvtnum(optarg);
649
            if (pattern_count < 0) {
650
                printf("non-numeric length argument -- %s\n", optarg);
651
                return 0;
652
            }
653
            break;
654
        case 'p':
655
            pflag = 1;
656
            break;
657
        case 'P':
658
            Pflag = 1;
659
            pattern = parse_pattern(optarg);
660
            if (pattern < 0) {
661
                return 0;
662
            }
663
            break;
664
        case 'q':
665
            qflag = 1;
666
            break;
667
        case 's':
668
            sflag = 1;
669
            pattern_offset = cvtnum(optarg);
670
            if (pattern_offset < 0) {
671
                printf("non-numeric length argument -- %s\n", optarg);
672
                return 0;
673
            }
674
            break;
675
        case 'v':
676
            vflag = 1;
677
            break;
678
        default:
679
            return qemuio_command_usage(&read_cmd);
680
        }
681
    }
682

    
683
    if (optind != argc - 2) {
684
        return qemuio_command_usage(&read_cmd);
685
    }
686

    
687
    if (bflag && pflag) {
688
        printf("-b and -p cannot be specified at the same time\n");
689
        return 0;
690
    }
691

    
692
    offset = cvtnum(argv[optind]);
693
    if (offset < 0) {
694
        printf("non-numeric length argument -- %s\n", argv[optind]);
695
        return 0;
696
    }
697

    
698
    optind++;
699
    count = cvtnum(argv[optind]);
700
    if (count < 0) {
701
        printf("non-numeric length argument -- %s\n", argv[optind]);
702
        return 0;
703
    }
704

    
705
    if (!Pflag && (lflag || sflag)) {
706
        return qemuio_command_usage(&read_cmd);
707
    }
708

    
709
    if (!lflag) {
710
        pattern_count = count - pattern_offset;
711
    }
712

    
713
    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
714
        printf("pattern verification range exceeds end of read data\n");
715
        return 0;
716
    }
717

    
718
    if (!pflag) {
719
        if (offset & 0x1ff) {
720
            printf("offset %" PRId64 " is not sector aligned\n",
721
                   offset);
722
            return 0;
723
        }
724
        if (count & 0x1ff) {
725
            printf("count %d is not sector aligned\n",
726
                   count);
727
            return 0;
728
        }
729
    }
730

    
731
    buf = qemu_io_alloc(bs, count, 0xab);
732

    
733
    gettimeofday(&t1, NULL);
734
    if (pflag) {
735
        cnt = do_pread(bs, buf, offset, count, &total);
736
    } else if (bflag) {
737
        cnt = do_load_vmstate(bs, buf, offset, count, &total);
738
    } else {
739
        cnt = do_read(bs, buf, offset, count, &total);
740
    }
741
    gettimeofday(&t2, NULL);
742

    
743
    if (cnt < 0) {
744
        printf("read failed: %s\n", strerror(-cnt));
745
        goto out;
746
    }
747

    
748
    if (Pflag) {
749
        void *cmp_buf = g_malloc(pattern_count);
750
        memset(cmp_buf, pattern, pattern_count);
751
        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
752
            printf("Pattern verification failed at offset %"
753
                   PRId64 ", %d bytes\n",
754
                   offset + pattern_offset, pattern_count);
755
        }
756
        g_free(cmp_buf);
757
    }
758

    
759
    if (qflag) {
760
        goto out;
761
    }
762

    
763
    if (vflag) {
764
        dump_buffer(buf, offset, count);
765
    }
766

    
767
    /* Finally, report back -- -C gives a parsable format */
768
    t2 = tsub(t2, t1);
769
    print_report("read", &t2, offset, count, total, cnt, Cflag);
770

    
771
out:
772
    qemu_io_free(buf);
773

    
774
    return 0;
775
}
776

    
777
static void readv_help(void)
778
{
779
    printf(
780
"\n"
781
" reads a range of bytes from the given offset into multiple buffers\n"
782
"\n"
783
" Example:\n"
784
" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
785
"\n"
786
" Reads a segment of the currently open file, optionally dumping it to the\n"
787
" standard output stream (with -v option) for subsequent inspection.\n"
788
" Uses multiple iovec buffers if more than one byte range is specified.\n"
789
" -C, -- report statistics in a machine parsable format\n"
790
" -P, -- use a pattern to verify read data\n"
791
" -v, -- dump buffer to standard output\n"
792
" -q, -- quiet mode, do not show I/O statistics\n"
793
"\n");
794
}
795

    
796
static int readv_f(BlockDriverState *bs, int argc, char **argv);
797

    
798
static const cmdinfo_t readv_cmd = {
799
    .name       = "readv",
800
    .cfunc      = readv_f,
801
    .argmin     = 2,
802
    .argmax     = -1,
803
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
804
    .oneline    = "reads a number of bytes at a specified offset",
805
    .help       = readv_help,
806
};
807

    
808
static int readv_f(BlockDriverState *bs, int argc, char **argv)
809
{
810
    struct timeval t1, t2;
811
    int Cflag = 0, qflag = 0, vflag = 0;
812
    int c, cnt;
813
    char *buf;
814
    int64_t offset;
815
    /* Some compilers get confused and warn if this is not initialized.  */
816
    int total = 0;
817
    int nr_iov;
818
    QEMUIOVector qiov;
819
    int pattern = 0;
820
    int Pflag = 0;
821

    
822
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
823
        switch (c) {
824
        case 'C':
825
            Cflag = 1;
826
            break;
827
        case 'P':
828
            Pflag = 1;
829
            pattern = parse_pattern(optarg);
830
            if (pattern < 0) {
831
                return 0;
832
            }
833
            break;
834
        case 'q':
835
            qflag = 1;
836
            break;
837
        case 'v':
838
            vflag = 1;
839
            break;
840
        default:
841
            return qemuio_command_usage(&readv_cmd);
842
        }
843
    }
844

    
845
    if (optind > argc - 2) {
846
        return qemuio_command_usage(&readv_cmd);
847
    }
848

    
849

    
850
    offset = cvtnum(argv[optind]);
851
    if (offset < 0) {
852
        printf("non-numeric length argument -- %s\n", argv[optind]);
853
        return 0;
854
    }
855
    optind++;
856

    
857
    if (offset & 0x1ff) {
858
        printf("offset %" PRId64 " is not sector aligned\n",
859
               offset);
860
        return 0;
861
    }
862

    
863
    nr_iov = argc - optind;
864
    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
865
    if (buf == NULL) {
866
        return 0;
867
    }
868

    
869
    gettimeofday(&t1, NULL);
870
    cnt = do_aio_readv(bs, &qiov, offset, &total);
871
    gettimeofday(&t2, NULL);
872

    
873
    if (cnt < 0) {
874
        printf("readv failed: %s\n", strerror(-cnt));
875
        goto out;
876
    }
877

    
878
    if (Pflag) {
879
        void *cmp_buf = g_malloc(qiov.size);
880
        memset(cmp_buf, pattern, qiov.size);
881
        if (memcmp(buf, cmp_buf, qiov.size)) {
882
            printf("Pattern verification failed at offset %"
883
                   PRId64 ", %zd bytes\n", offset, qiov.size);
884
        }
885
        g_free(cmp_buf);
886
    }
887

    
888
    if (qflag) {
889
        goto out;
890
    }
891

    
892
    if (vflag) {
893
        dump_buffer(buf, offset, qiov.size);
894
    }
895

    
896
    /* Finally, report back -- -C gives a parsable format */
897
    t2 = tsub(t2, t1);
898
    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
899

    
900
out:
901
    qemu_iovec_destroy(&qiov);
902
    qemu_io_free(buf);
903
    return 0;
904
}
905

    
906
static void write_help(void)
907
{
908
    printf(
909
"\n"
910
" writes a range of bytes from the given offset\n"
911
"\n"
912
" Example:\n"
913
" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
914
"\n"
915
" Writes into a segment of the currently open file, using a buffer\n"
916
" filled with a set pattern (0xcdcdcdcd).\n"
917
" -b, -- write to the VM state rather than the virtual disk\n"
918
" -c, -- write compressed data with bdrv_write_compressed\n"
919
" -p, -- use bdrv_pwrite to write the file\n"
920
" -P, -- use different pattern to fill file\n"
921
" -C, -- report statistics in a machine parsable format\n"
922
" -q, -- quiet mode, do not show I/O statistics\n"
923
" -z, -- write zeroes using bdrv_co_write_zeroes\n"
924
"\n");
925
}
926

    
927
static int write_f(BlockDriverState *bs, int argc, char **argv);
928

    
929
static const cmdinfo_t write_cmd = {
930
    .name       = "write",
931
    .altname    = "w",
932
    .cfunc      = write_f,
933
    .argmin     = 2,
934
    .argmax     = -1,
935
    .args       = "[-bcCpqz] [-P pattern ] off len",
936
    .oneline    = "writes a number of bytes at a specified offset",
937
    .help       = write_help,
938
};
939

    
940
static int write_f(BlockDriverState *bs, int argc, char **argv)
941
{
942
    struct timeval t1, t2;
943
    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
944
    int cflag = 0;
945
    int c, cnt;
946
    char *buf = NULL;
947
    int64_t offset;
948
    int count;
949
    /* Some compilers get confused and warn if this is not initialized.  */
950
    int total = 0;
951
    int pattern = 0xcd;
952

    
953
    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
954
        switch (c) {
955
        case 'b':
956
            bflag = 1;
957
            break;
958
        case 'c':
959
            cflag = 1;
960
            break;
961
        case 'C':
962
            Cflag = 1;
963
            break;
964
        case 'p':
965
            pflag = 1;
966
            break;
967
        case 'P':
968
            Pflag = 1;
969
            pattern = parse_pattern(optarg);
970
            if (pattern < 0) {
971
                return 0;
972
            }
973
            break;
974
        case 'q':
975
            qflag = 1;
976
            break;
977
        case 'z':
978
            zflag = 1;
979
            break;
980
        default:
981
            return qemuio_command_usage(&write_cmd);
982
        }
983
    }
984

    
985
    if (optind != argc - 2) {
986
        return qemuio_command_usage(&write_cmd);
987
    }
988

    
989
    if (bflag + pflag + zflag > 1) {
990
        printf("-b, -p, or -z cannot be specified at the same time\n");
991
        return 0;
992
    }
993

    
994
    if (zflag && Pflag) {
995
        printf("-z and -P cannot be specified at the same time\n");
996
        return 0;
997
    }
998

    
999
    offset = cvtnum(argv[optind]);
1000
    if (offset < 0) {
1001
        printf("non-numeric length argument -- %s\n", argv[optind]);
1002
        return 0;
1003
    }
1004

    
1005
    optind++;
1006
    count = cvtnum(argv[optind]);
1007
    if (count < 0) {
1008
        printf("non-numeric length argument -- %s\n", argv[optind]);
1009
        return 0;
1010
    }
1011

    
1012
    if (!pflag) {
1013
        if (offset & 0x1ff) {
1014
            printf("offset %" PRId64 " is not sector aligned\n",
1015
                   offset);
1016
            return 0;
1017
        }
1018

    
1019
        if (count & 0x1ff) {
1020
            printf("count %d is not sector aligned\n",
1021
                   count);
1022
            return 0;
1023
        }
1024
    }
1025

    
1026
    if (!zflag) {
1027
        buf = qemu_io_alloc(bs, count, pattern);
1028
    }
1029

    
1030
    gettimeofday(&t1, NULL);
1031
    if (pflag) {
1032
        cnt = do_pwrite(bs, buf, offset, count, &total);
1033
    } else if (bflag) {
1034
        cnt = do_save_vmstate(bs, buf, offset, count, &total);
1035
    } else if (zflag) {
1036
        cnt = do_co_write_zeroes(bs, offset, count, &total);
1037
    } else if (cflag) {
1038
        cnt = do_write_compressed(bs, buf, offset, count, &total);
1039
    } else {
1040
        cnt = do_write(bs, buf, offset, count, &total);
1041
    }
1042
    gettimeofday(&t2, NULL);
1043

    
1044
    if (cnt < 0) {
1045
        printf("write failed: %s\n", strerror(-cnt));
1046
        goto out;
1047
    }
1048

    
1049
    if (qflag) {
1050
        goto out;
1051
    }
1052

    
1053
    /* Finally, report back -- -C gives a parsable format */
1054
    t2 = tsub(t2, t1);
1055
    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1056

    
1057
out:
1058
    if (!zflag) {
1059
        qemu_io_free(buf);
1060
    }
1061

    
1062
    return 0;
1063
}
1064

    
1065
static void
1066
writev_help(void)
1067
{
1068
    printf(
1069
"\n"
1070
" writes a range of bytes from the given offset source from multiple buffers\n"
1071
"\n"
1072
" Example:\n"
1073
" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1074
"\n"
1075
" Writes into a segment of the currently open file, using a buffer\n"
1076
" filled with a set pattern (0xcdcdcdcd).\n"
1077
" -P, -- use different pattern to fill file\n"
1078
" -C, -- report statistics in a machine parsable format\n"
1079
" -q, -- quiet mode, do not show I/O statistics\n"
1080
"\n");
1081
}
1082

    
1083
static int writev_f(BlockDriverState *bs, int argc, char **argv);
1084

    
1085
static const cmdinfo_t writev_cmd = {
1086
    .name       = "writev",
1087
    .cfunc      = writev_f,
1088
    .argmin     = 2,
1089
    .argmax     = -1,
1090
    .args       = "[-Cq] [-P pattern ] off len [len..]",
1091
    .oneline    = "writes a number of bytes at a specified offset",
1092
    .help       = writev_help,
1093
};
1094

    
1095
static int writev_f(BlockDriverState *bs, int argc, char **argv)
1096
{
1097
    struct timeval t1, t2;
1098
    int Cflag = 0, qflag = 0;
1099
    int c, cnt;
1100
    char *buf;
1101
    int64_t offset;
1102
    /* Some compilers get confused and warn if this is not initialized.  */
1103
    int total = 0;
1104
    int nr_iov;
1105
    int pattern = 0xcd;
1106
    QEMUIOVector qiov;
1107

    
1108
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1109
        switch (c) {
1110
        case 'C':
1111
            Cflag = 1;
1112
            break;
1113
        case 'q':
1114
            qflag = 1;
1115
            break;
1116
        case 'P':
1117
            pattern = parse_pattern(optarg);
1118
            if (pattern < 0) {
1119
                return 0;
1120
            }
1121
            break;
1122
        default:
1123
            return qemuio_command_usage(&writev_cmd);
1124
        }
1125
    }
1126

    
1127
    if (optind > argc - 2) {
1128
        return qemuio_command_usage(&writev_cmd);
1129
    }
1130

    
1131
    offset = cvtnum(argv[optind]);
1132
    if (offset < 0) {
1133
        printf("non-numeric length argument -- %s\n", argv[optind]);
1134
        return 0;
1135
    }
1136
    optind++;
1137

    
1138
    if (offset & 0x1ff) {
1139
        printf("offset %" PRId64 " is not sector aligned\n",
1140
               offset);
1141
        return 0;
1142
    }
1143

    
1144
    nr_iov = argc - optind;
1145
    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
1146
    if (buf == NULL) {
1147
        return 0;
1148
    }
1149

    
1150
    gettimeofday(&t1, NULL);
1151
    cnt = do_aio_writev(bs, &qiov, offset, &total);
1152
    gettimeofday(&t2, NULL);
1153

    
1154
    if (cnt < 0) {
1155
        printf("writev failed: %s\n", strerror(-cnt));
1156
        goto out;
1157
    }
1158

    
1159
    if (qflag) {
1160
        goto out;
1161
    }
1162

    
1163
    /* Finally, report back -- -C gives a parsable format */
1164
    t2 = tsub(t2, t1);
1165
    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1166
out:
1167
    qemu_iovec_destroy(&qiov);
1168
    qemu_io_free(buf);
1169
    return 0;
1170
}
1171

    
1172
static void multiwrite_help(void)
1173
{
1174
    printf(
1175
"\n"
1176
" writes a range of bytes from the given offset source from multiple buffers,\n"
1177
" in a batch of requests that may be merged by qemu\n"
1178
"\n"
1179
" Example:\n"
1180
" 'multiwrite 512 1k 1k ; 4k 1k'\n"
1181
"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
1182
"\n"
1183
" Writes into a segment of the currently open file, using a buffer\n"
1184
" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
1185
" by one for each request contained in the multiwrite command.\n"
1186
" -P, -- use different pattern to fill file\n"
1187
" -C, -- report statistics in a machine parsable format\n"
1188
" -q, -- quiet mode, do not show I/O statistics\n"
1189
"\n");
1190
}
1191

    
1192
static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
1193

    
1194
static const cmdinfo_t multiwrite_cmd = {
1195
    .name       = "multiwrite",
1196
    .cfunc      = multiwrite_f,
1197
    .argmin     = 2,
1198
    .argmax     = -1,
1199
    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
1200
    .oneline    = "issues multiple write requests at once",
1201
    .help       = multiwrite_help,
1202
};
1203

    
1204
static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
1205
{
1206
    struct timeval t1, t2;
1207
    int Cflag = 0, qflag = 0;
1208
    int c, cnt;
1209
    char **buf;
1210
    int64_t offset, first_offset = 0;
1211
    /* Some compilers get confused and warn if this is not initialized.  */
1212
    int total = 0;
1213
    int nr_iov;
1214
    int nr_reqs;
1215
    int pattern = 0xcd;
1216
    QEMUIOVector *qiovs;
1217
    int i;
1218
    BlockRequest *reqs;
1219

    
1220
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1221
        switch (c) {
1222
        case 'C':
1223
            Cflag = 1;
1224
            break;
1225
        case 'q':
1226
            qflag = 1;
1227
            break;
1228
        case 'P':
1229
            pattern = parse_pattern(optarg);
1230
            if (pattern < 0) {
1231
                return 0;
1232
            }
1233
            break;
1234
        default:
1235
            return qemuio_command_usage(&writev_cmd);
1236
        }
1237
    }
1238

    
1239
    if (optind > argc - 2) {
1240
        return qemuio_command_usage(&writev_cmd);
1241
    }
1242

    
1243
    nr_reqs = 1;
1244
    for (i = optind; i < argc; i++) {
1245
        if (!strcmp(argv[i], ";")) {
1246
            nr_reqs++;
1247
        }
1248
    }
1249

    
1250
    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1251
    buf = g_malloc0(nr_reqs * sizeof(*buf));
1252
    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1253

    
1254
    for (i = 0; i < nr_reqs && optind < argc; i++) {
1255
        int j;
1256

    
1257
        /* Read the offset of the request */
1258
        offset = cvtnum(argv[optind]);
1259
        if (offset < 0) {
1260
            printf("non-numeric offset argument -- %s\n", argv[optind]);
1261
            goto out;
1262
        }
1263
        optind++;
1264

    
1265
        if (offset & 0x1ff) {
1266
            printf("offset %lld is not sector aligned\n",
1267
                   (long long)offset);
1268
            goto out;
1269
        }
1270

    
1271
        if (i == 0) {
1272
            first_offset = offset;
1273
        }
1274

    
1275
        /* Read lengths for qiov entries */
1276
        for (j = optind; j < argc; j++) {
1277
            if (!strcmp(argv[j], ";")) {
1278
                break;
1279
            }
1280
        }
1281

    
1282
        nr_iov = j - optind;
1283

    
1284
        /* Build request */
1285
        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
1286
        if (buf[i] == NULL) {
1287
            goto out;
1288
        }
1289

    
1290
        reqs[i].qiov = &qiovs[i];
1291
        reqs[i].sector = offset >> 9;
1292
        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1293

    
1294
        optind = j + 1;
1295

    
1296
        pattern++;
1297
    }
1298

    
1299
    /* If there were empty requests at the end, ignore them */
1300
    nr_reqs = i;
1301

    
1302
    gettimeofday(&t1, NULL);
1303
    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
1304
    gettimeofday(&t2, NULL);
1305

    
1306
    if (cnt < 0) {
1307
        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1308
        goto out;
1309
    }
1310

    
1311
    if (qflag) {
1312
        goto out;
1313
    }
1314

    
1315
    /* Finally, report back -- -C gives a parsable format */
1316
    t2 = tsub(t2, t1);
1317
    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1318
out:
1319
    for (i = 0; i < nr_reqs; i++) {
1320
        qemu_io_free(buf[i]);
1321
        if (reqs[i].qiov != NULL) {
1322
            qemu_iovec_destroy(&qiovs[i]);
1323
        }
1324
    }
1325
    g_free(buf);
1326
    g_free(reqs);
1327
    g_free(qiovs);
1328
    return 0;
1329
}
1330

    
1331
struct aio_ctx {
1332
    QEMUIOVector qiov;
1333
    int64_t offset;
1334
    char *buf;
1335
    int qflag;
1336
    int vflag;
1337
    int Cflag;
1338
    int Pflag;
1339
    int pattern;
1340
    struct timeval t1;
1341
};
1342

    
1343
static void aio_write_done(void *opaque, int ret)
1344
{
1345
    struct aio_ctx *ctx = opaque;
1346
    struct timeval t2;
1347

    
1348
    gettimeofday(&t2, NULL);
1349

    
1350

    
1351
    if (ret < 0) {
1352
        printf("aio_write failed: %s\n", strerror(-ret));
1353
        goto out;
1354
    }
1355

    
1356
    if (ctx->qflag) {
1357
        goto out;
1358
    }
1359

    
1360
    /* Finally, report back -- -C gives a parsable format */
1361
    t2 = tsub(t2, ctx->t1);
1362
    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1363
                 ctx->qiov.size, 1, ctx->Cflag);
1364
out:
1365
    qemu_io_free(ctx->buf);
1366
    qemu_iovec_destroy(&ctx->qiov);
1367
    g_free(ctx);
1368
}
1369

    
1370
static void aio_read_done(void *opaque, int ret)
1371
{
1372
    struct aio_ctx *ctx = opaque;
1373
    struct timeval t2;
1374

    
1375
    gettimeofday(&t2, NULL);
1376

    
1377
    if (ret < 0) {
1378
        printf("readv failed: %s\n", strerror(-ret));
1379
        goto out;
1380
    }
1381

    
1382
    if (ctx->Pflag) {
1383
        void *cmp_buf = g_malloc(ctx->qiov.size);
1384

    
1385
        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1386
        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1387
            printf("Pattern verification failed at offset %"
1388
                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1389
        }
1390
        g_free(cmp_buf);
1391
    }
1392

    
1393
    if (ctx->qflag) {
1394
        goto out;
1395
    }
1396

    
1397
    if (ctx->vflag) {
1398
        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1399
    }
1400

    
1401
    /* Finally, report back -- -C gives a parsable format */
1402
    t2 = tsub(t2, ctx->t1);
1403
    print_report("read", &t2, ctx->offset, ctx->qiov.size,
1404
                 ctx->qiov.size, 1, ctx->Cflag);
1405
out:
1406
    qemu_io_free(ctx->buf);
1407
    qemu_iovec_destroy(&ctx->qiov);
1408
    g_free(ctx);
1409
}
1410

    
1411
static void aio_read_help(void)
1412
{
1413
    printf(
1414
"\n"
1415
" asynchronously reads a range of bytes from the given offset\n"
1416
"\n"
1417
" Example:\n"
1418
" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1419
"\n"
1420
" Reads a segment of the currently open file, optionally dumping it to the\n"
1421
" standard output stream (with -v option) for subsequent inspection.\n"
1422
" The read is performed asynchronously and the aio_flush command must be\n"
1423
" used to ensure all outstanding aio requests have been completed.\n"
1424
" -C, -- report statistics in a machine parsable format\n"
1425
" -P, -- use a pattern to verify read data\n"
1426
" -v, -- dump buffer to standard output\n"
1427
" -q, -- quiet mode, do not show I/O statistics\n"
1428
"\n");
1429
}
1430

    
1431
static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1432

    
1433
static const cmdinfo_t aio_read_cmd = {
1434
    .name       = "aio_read",
1435
    .cfunc      = aio_read_f,
1436
    .argmin     = 2,
1437
    .argmax     = -1,
1438
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
1439
    .oneline    = "asynchronously reads a number of bytes",
1440
    .help       = aio_read_help,
1441
};
1442

    
1443
static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
1444
{
1445
    int nr_iov, c;
1446
    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1447

    
1448
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1449
        switch (c) {
1450
        case 'C':
1451
            ctx->Cflag = 1;
1452
            break;
1453
        case 'P':
1454
            ctx->Pflag = 1;
1455
            ctx->pattern = parse_pattern(optarg);
1456
            if (ctx->pattern < 0) {
1457
                g_free(ctx);
1458
                return 0;
1459
            }
1460
            break;
1461
        case 'q':
1462
            ctx->qflag = 1;
1463
            break;
1464
        case 'v':
1465
            ctx->vflag = 1;
1466
            break;
1467
        default:
1468
            g_free(ctx);
1469
            return qemuio_command_usage(&aio_read_cmd);
1470
        }
1471
    }
1472

    
1473
    if (optind > argc - 2) {
1474
        g_free(ctx);
1475
        return qemuio_command_usage(&aio_read_cmd);
1476
    }
1477

    
1478
    ctx->offset = cvtnum(argv[optind]);
1479
    if (ctx->offset < 0) {
1480
        printf("non-numeric length argument -- %s\n", argv[optind]);
1481
        g_free(ctx);
1482
        return 0;
1483
    }
1484
    optind++;
1485

    
1486
    if (ctx->offset & 0x1ff) {
1487
        printf("offset %" PRId64 " is not sector aligned\n",
1488
               ctx->offset);
1489
        g_free(ctx);
1490
        return 0;
1491
    }
1492

    
1493
    nr_iov = argc - optind;
1494
    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1495
    if (ctx->buf == NULL) {
1496
        g_free(ctx);
1497
        return 0;
1498
    }
1499

    
1500
    gettimeofday(&ctx->t1, NULL);
1501
    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1502
                   ctx->qiov.size >> 9, aio_read_done, ctx);
1503
    return 0;
1504
}
1505

    
1506
static void aio_write_help(void)
1507
{
1508
    printf(
1509
"\n"
1510
" asynchronously writes a range of bytes from the given offset source\n"
1511
" from multiple buffers\n"
1512
"\n"
1513
" Example:\n"
1514
" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1515
"\n"
1516
" Writes into a segment of the currently open file, using a buffer\n"
1517
" filled with a set pattern (0xcdcdcdcd).\n"
1518
" The write is performed asynchronously and the aio_flush command must be\n"
1519
" used to ensure all outstanding aio requests have been completed.\n"
1520
" -P, -- use different pattern to fill file\n"
1521
" -C, -- report statistics in a machine parsable format\n"
1522
" -q, -- quiet mode, do not show I/O statistics\n"
1523
"\n");
1524
}
1525

    
1526
static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1527

    
1528
static const cmdinfo_t aio_write_cmd = {
1529
    .name       = "aio_write",
1530
    .cfunc      = aio_write_f,
1531
    .argmin     = 2,
1532
    .argmax     = -1,
1533
    .args       = "[-Cq] [-P pattern ] off len [len..]",
1534
    .oneline    = "asynchronously writes a number of bytes",
1535
    .help       = aio_write_help,
1536
};
1537

    
1538
static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
1539
{
1540
    int nr_iov, c;
1541
    int pattern = 0xcd;
1542
    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1543

    
1544
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1545
        switch (c) {
1546
        case 'C':
1547
            ctx->Cflag = 1;
1548
            break;
1549
        case 'q':
1550
            ctx->qflag = 1;
1551
            break;
1552
        case 'P':
1553
            pattern = parse_pattern(optarg);
1554
            if (pattern < 0) {
1555
                g_free(ctx);
1556
                return 0;
1557
            }
1558
            break;
1559
        default:
1560
            g_free(ctx);
1561
            return qemuio_command_usage(&aio_write_cmd);
1562
        }
1563
    }
1564

    
1565
    if (optind > argc - 2) {
1566
        g_free(ctx);
1567
        return qemuio_command_usage(&aio_write_cmd);
1568
    }
1569

    
1570
    ctx->offset = cvtnum(argv[optind]);
1571
    if (ctx->offset < 0) {
1572
        printf("non-numeric length argument -- %s\n", argv[optind]);
1573
        g_free(ctx);
1574
        return 0;
1575
    }
1576
    optind++;
1577

    
1578
    if (ctx->offset & 0x1ff) {
1579
        printf("offset %" PRId64 " is not sector aligned\n",
1580
               ctx->offset);
1581
        g_free(ctx);
1582
        return 0;
1583
    }
1584

    
1585
    nr_iov = argc - optind;
1586
    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
1587
    if (ctx->buf == NULL) {
1588
        g_free(ctx);
1589
        return 0;
1590
    }
1591

    
1592
    gettimeofday(&ctx->t1, NULL);
1593
    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1594
                    ctx->qiov.size >> 9, aio_write_done, ctx);
1595
    return 0;
1596
}
1597

    
1598
static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1599
{
1600
    bdrv_drain_all();
1601
    return 0;
1602
}
1603

    
1604
static const cmdinfo_t aio_flush_cmd = {
1605
    .name       = "aio_flush",
1606
    .cfunc      = aio_flush_f,
1607
    .oneline    = "completes all outstanding aio requests"
1608
};
1609

    
1610
static int flush_f(BlockDriverState *bs, int argc, char **argv)
1611
{
1612
    bdrv_flush(bs);
1613
    return 0;
1614
}
1615

    
1616
static const cmdinfo_t flush_cmd = {
1617
    .name       = "flush",
1618
    .altname    = "f",
1619
    .cfunc      = flush_f,
1620
    .oneline    = "flush all in-core file state to disk",
1621
};
1622

    
1623
static int truncate_f(BlockDriverState *bs, int argc, char **argv)
1624
{
1625
    int64_t offset;
1626
    int ret;
1627

    
1628
    offset = cvtnum(argv[1]);
1629
    if (offset < 0) {
1630
        printf("non-numeric truncate argument -- %s\n", argv[1]);
1631
        return 0;
1632
    }
1633

    
1634
    ret = bdrv_truncate(bs, offset);
1635
    if (ret < 0) {
1636
        printf("truncate: %s\n", strerror(-ret));
1637
        return 0;
1638
    }
1639

    
1640
    return 0;
1641
}
1642

    
1643
static const cmdinfo_t truncate_cmd = {
1644
    .name       = "truncate",
1645
    .altname    = "t",
1646
    .cfunc      = truncate_f,
1647
    .argmin     = 1,
1648
    .argmax     = 1,
1649
    .args       = "off",
1650
    .oneline    = "truncates the current file at the given offset",
1651
};
1652

    
1653
static int length_f(BlockDriverState *bs, int argc, char **argv)
1654
{
1655
    int64_t size;
1656
    char s1[64];
1657

    
1658
    size = bdrv_getlength(bs);
1659
    if (size < 0) {
1660
        printf("getlength: %s\n", strerror(-size));
1661
        return 0;
1662
    }
1663

    
1664
    cvtstr(size, s1, sizeof(s1));
1665
    printf("%s\n", s1);
1666
    return 0;
1667
}
1668

    
1669

    
1670
static const cmdinfo_t length_cmd = {
1671
    .name   = "length",
1672
    .altname    = "l",
1673
    .cfunc      = length_f,
1674
    .oneline    = "gets the length of the current file",
1675
};
1676

    
1677

    
1678
static int info_f(BlockDriverState *bs, int argc, char **argv)
1679
{
1680
    BlockDriverInfo bdi;
1681
    char s1[64], s2[64];
1682
    int ret;
1683

    
1684
    if (bs->drv && bs->drv->format_name) {
1685
        printf("format name: %s\n", bs->drv->format_name);
1686
    }
1687
    if (bs->drv && bs->drv->protocol_name) {
1688
        printf("format name: %s\n", bs->drv->protocol_name);
1689
    }
1690

    
1691
    ret = bdrv_get_info(bs, &bdi);
1692
    if (ret) {
1693
        return 0;
1694
    }
1695

    
1696
    cvtstr(bdi.cluster_size, s1, sizeof(s1));
1697
    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1698

    
1699
    printf("cluster size: %s\n", s1);
1700
    printf("vm state offset: %s\n", s2);
1701

    
1702
    return 0;
1703
}
1704

    
1705

    
1706

    
1707
static const cmdinfo_t info_cmd = {
1708
    .name       = "info",
1709
    .altname    = "i",
1710
    .cfunc      = info_f,
1711
    .oneline    = "prints information about the current file",
1712
};
1713

    
1714
static void discard_help(void)
1715
{
1716
    printf(
1717
"\n"
1718
" discards a range of bytes from the given offset\n"
1719
"\n"
1720
" Example:\n"
1721
" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1722
"\n"
1723
" Discards a segment of the currently open file.\n"
1724
" -C, -- report statistics in a machine parsable format\n"
1725
" -q, -- quiet mode, do not show I/O statistics\n"
1726
"\n");
1727
}
1728

    
1729
static int discard_f(BlockDriverState *bs, int argc, char **argv);
1730

    
1731
static const cmdinfo_t discard_cmd = {
1732
    .name       = "discard",
1733
    .altname    = "d",
1734
    .cfunc      = discard_f,
1735
    .argmin     = 2,
1736
    .argmax     = -1,
1737
    .args       = "[-Cq] off len",
1738
    .oneline    = "discards a number of bytes at a specified offset",
1739
    .help       = discard_help,
1740
};
1741

    
1742
static int discard_f(BlockDriverState *bs, int argc, char **argv)
1743
{
1744
    struct timeval t1, t2;
1745
    int Cflag = 0, qflag = 0;
1746
    int c, ret;
1747
    int64_t offset;
1748
    int count;
1749

    
1750
    while ((c = getopt(argc, argv, "Cq")) != EOF) {
1751
        switch (c) {
1752
        case 'C':
1753
            Cflag = 1;
1754
            break;
1755
        case 'q':
1756
            qflag = 1;
1757
            break;
1758
        default:
1759
            return qemuio_command_usage(&discard_cmd);
1760
        }
1761
    }
1762

    
1763
    if (optind != argc - 2) {
1764
        return qemuio_command_usage(&discard_cmd);
1765
    }
1766

    
1767
    offset = cvtnum(argv[optind]);
1768
    if (offset < 0) {
1769
        printf("non-numeric length argument -- %s\n", argv[optind]);
1770
        return 0;
1771
    }
1772

    
1773
    optind++;
1774
    count = cvtnum(argv[optind]);
1775
    if (count < 0) {
1776
        printf("non-numeric length argument -- %s\n", argv[optind]);
1777
        return 0;
1778
    }
1779

    
1780
    gettimeofday(&t1, NULL);
1781
    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1782
                       count >> BDRV_SECTOR_BITS);
1783
    gettimeofday(&t2, NULL);
1784

    
1785
    if (ret < 0) {
1786
        printf("discard failed: %s\n", strerror(-ret));
1787
        goto out;
1788
    }
1789

    
1790
    /* Finally, report back -- -C gives a parsable format */
1791
    if (!qflag) {
1792
        t2 = tsub(t2, t1);
1793
        print_report("discard", &t2, offset, count, count, 1, Cflag);
1794
    }
1795

    
1796
out:
1797
    return 0;
1798
}
1799

    
1800
static int alloc_f(BlockDriverState *bs, int argc, char **argv)
1801
{
1802
    int64_t offset, sector_num;
1803
    int nb_sectors, remaining;
1804
    char s1[64];
1805
    int num, sum_alloc;
1806
    int ret;
1807

    
1808
    offset = cvtnum(argv[1]);
1809
    if (offset < 0) {
1810
        printf("non-numeric offset argument -- %s\n", argv[1]);
1811
        return 0;
1812
    } else if (offset & 0x1ff) {
1813
        printf("offset %" PRId64 " is not sector aligned\n",
1814
               offset);
1815
        return 0;
1816
    }
1817

    
1818
    if (argc == 3) {
1819
        nb_sectors = cvtnum(argv[2]);
1820
        if (nb_sectors < 0) {
1821
            printf("non-numeric length argument -- %s\n", argv[2]);
1822
            return 0;
1823
        }
1824
    } else {
1825
        nb_sectors = 1;
1826
    }
1827

    
1828
    remaining = nb_sectors;
1829
    sum_alloc = 0;
1830
    sector_num = offset >> 9;
1831
    while (remaining) {
1832
        ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1833
        sector_num += num;
1834
        remaining -= num;
1835
        if (ret) {
1836
            sum_alloc += num;
1837
        }
1838
        if (num == 0) {
1839
            nb_sectors -= remaining;
1840
            remaining = 0;
1841
        }
1842
    }
1843

    
1844
    cvtstr(offset, s1, sizeof(s1));
1845

    
1846
    printf("%d/%d sectors allocated at offset %s\n",
1847
           sum_alloc, nb_sectors, s1);
1848
    return 0;
1849
}
1850

    
1851
static const cmdinfo_t alloc_cmd = {
1852
    .name       = "alloc",
1853
    .altname    = "a",
1854
    .argmin     = 1,
1855
    .argmax     = 2,
1856
    .cfunc      = alloc_f,
1857
    .args       = "off [sectors]",
1858
    .oneline    = "checks if a sector is present in the file",
1859
};
1860

    
1861

    
1862
static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
1863
                            int64_t nb_sectors, int64_t *pnum)
1864
{
1865
    int num, num_checked;
1866
    int ret, firstret;
1867

    
1868
    num_checked = MIN(nb_sectors, INT_MAX);
1869
    ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1870
    if (ret < 0) {
1871
        return ret;
1872
    }
1873

    
1874
    firstret = ret;
1875
    *pnum = num;
1876

    
1877
    while (nb_sectors > 0 && ret == firstret) {
1878
        sector_num += num;
1879
        nb_sectors -= num;
1880

    
1881
        num_checked = MIN(nb_sectors, INT_MAX);
1882
        ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1883
        if (ret == firstret) {
1884
            *pnum += num;
1885
        } else {
1886
            break;
1887
        }
1888
    }
1889

    
1890
    return firstret;
1891
}
1892

    
1893
static int map_f(BlockDriverState *bs, int argc, char **argv)
1894
{
1895
    int64_t offset;
1896
    int64_t nb_sectors;
1897
    char s1[64];
1898
    int64_t num;
1899
    int ret;
1900
    const char *retstr;
1901

    
1902
    offset = 0;
1903
    nb_sectors = bs->total_sectors;
1904

    
1905
    do {
1906
        ret = map_is_allocated(bs, offset, nb_sectors, &num);
1907
        if (ret < 0) {
1908
            error_report("Failed to get allocation status: %s", strerror(-ret));
1909
            return 0;
1910
        }
1911

    
1912
        retstr = ret ? "    allocated" : "not allocated";
1913
        cvtstr(offset << 9ULL, s1, sizeof(s1));
1914
        printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
1915
               "at offset %s (%d)\n",
1916
               offset << 9ULL, num, nb_sectors, retstr, s1, ret);
1917

    
1918
        offset += num;
1919
        nb_sectors -= num;
1920
    } while (offset < bs->total_sectors);
1921

    
1922
    return 0;
1923
}
1924

    
1925
static const cmdinfo_t map_cmd = {
1926
       .name           = "map",
1927
       .argmin         = 0,
1928
       .argmax         = 0,
1929
       .cfunc          = map_f,
1930
       .args           = "",
1931
       .oneline        = "prints the allocated areas of a file",
1932
};
1933

    
1934
static int break_f(BlockDriverState *bs, int argc, char **argv)
1935
{
1936
    int ret;
1937

    
1938
    ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1939
    if (ret < 0) {
1940
        printf("Could not set breakpoint: %s\n", strerror(-ret));
1941
    }
1942

    
1943
    return 0;
1944
}
1945

    
1946
static const cmdinfo_t break_cmd = {
1947
       .name           = "break",
1948
       .argmin         = 2,
1949
       .argmax         = 2,
1950
       .cfunc          = break_f,
1951
       .args           = "event tag",
1952
       .oneline        = "sets a breakpoint on event and tags the stopped "
1953
                         "request as tag",
1954
};
1955

    
1956
static int resume_f(BlockDriverState *bs, int argc, char **argv)
1957
{
1958
    int ret;
1959

    
1960
    ret = bdrv_debug_resume(bs, argv[1]);
1961
    if (ret < 0) {
1962
        printf("Could not resume request: %s\n", strerror(-ret));
1963
    }
1964

    
1965
    return 0;
1966
}
1967

    
1968
static const cmdinfo_t resume_cmd = {
1969
       .name           = "resume",
1970
       .argmin         = 1,
1971
       .argmax         = 1,
1972
       .cfunc          = resume_f,
1973
       .args           = "tag",
1974
       .oneline        = "resumes the request tagged as tag",
1975
};
1976

    
1977
static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
1978
{
1979
    while (!bdrv_debug_is_suspended(bs, argv[1])) {
1980
        qemu_aio_wait();
1981
    }
1982

    
1983
    return 0;
1984
}
1985

    
1986
static const cmdinfo_t wait_break_cmd = {
1987
       .name           = "wait_break",
1988
       .argmin         = 1,
1989
       .argmax         = 1,
1990
       .cfunc          = wait_break_f,
1991
       .args           = "tag",
1992
       .oneline        = "waits for the suspension of a request",
1993
};
1994

    
1995
static int abort_f(BlockDriverState *bs, int argc, char **argv)
1996
{
1997
    abort();
1998
}
1999

    
2000
static const cmdinfo_t abort_cmd = {
2001
       .name           = "abort",
2002
       .cfunc          = abort_f,
2003
       .flags          = CMD_NOFILE_OK,
2004
       .oneline        = "simulate a program crash using abort(3)",
2005
};
2006

    
2007
static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2008
{
2009
    if (cmd) {
2010
        printf("%s ", cmd);
2011
    } else {
2012
        printf("%s ", ct->name);
2013
        if (ct->altname) {
2014
            printf("(or %s) ", ct->altname);
2015
        }
2016
    }
2017

    
2018
    if (ct->args) {
2019
        printf("%s ", ct->args);
2020
    }
2021
    printf("-- %s\n", ct->oneline);
2022
}
2023

    
2024
static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2025
{
2026
    help_oneline(cmd, ct);
2027
    if (ct->help) {
2028
        ct->help();
2029
    }
2030
}
2031

    
2032
static void help_all(void)
2033
{
2034
    const cmdinfo_t *ct;
2035

    
2036
    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2037
        help_oneline(ct->name, ct);
2038
    }
2039
    printf("\nUse 'help commandname' for extended help.\n");
2040
}
2041

    
2042
static int help_f(BlockDriverState *bs, int argc, char **argv)
2043
{
2044
    const cmdinfo_t *ct;
2045

    
2046
    if (argc == 1) {
2047
        help_all();
2048
        return 0;
2049
    }
2050

    
2051
    ct = find_command(argv[1]);
2052
    if (ct == NULL) {
2053
        printf("command %s not found\n", argv[1]);
2054
        return 0;
2055
    }
2056

    
2057
    help_onecmd(argv[1], ct);
2058
    return 0;
2059
}
2060

    
2061
static const cmdinfo_t help_cmd = {
2062
    .name       = "help",
2063
    .altname    = "?",
2064
    .cfunc      = help_f,
2065
    .argmin     = 0,
2066
    .argmax     = 1,
2067
    .flags      = CMD_FLAG_GLOBAL,
2068
    .args       = "[command]",
2069
    .oneline    = "help for one or all commands",
2070
};
2071

    
2072
bool qemuio_command(BlockDriverState *bs, const char *cmd)
2073
{
2074
    char *input;
2075
    const cmdinfo_t *ct;
2076
    char **v;
2077
    int c;
2078
    bool done = false;
2079

    
2080
    input = g_strdup(cmd);
2081
    v = breakline(input, &c);
2082
    if (c) {
2083
        ct = find_command(v[0]);
2084
        if (ct) {
2085
            done = command(bs, ct, c, v);
2086
        } else {
2087
            fprintf(stderr, "command \"%s\" not found\n", v[0]);
2088
        }
2089
    }
2090
    g_free(input);
2091
    g_free(v);
2092

    
2093
    return done;
2094
}
2095

    
2096
static void __attribute((constructor)) init_qemuio_commands(void)
2097
{
2098
    /* initialize commands */
2099
    qemuio_add_command(&help_cmd);
2100
    qemuio_add_command(&read_cmd);
2101
    qemuio_add_command(&readv_cmd);
2102
    qemuio_add_command(&write_cmd);
2103
    qemuio_add_command(&writev_cmd);
2104
    qemuio_add_command(&multiwrite_cmd);
2105
    qemuio_add_command(&aio_read_cmd);
2106
    qemuio_add_command(&aio_write_cmd);
2107
    qemuio_add_command(&aio_flush_cmd);
2108
    qemuio_add_command(&flush_cmd);
2109
    qemuio_add_command(&truncate_cmd);
2110
    qemuio_add_command(&length_cmd);
2111
    qemuio_add_command(&info_cmd);
2112
    qemuio_add_command(&discard_cmd);
2113
    qemuio_add_command(&alloc_cmd);
2114
    qemuio_add_command(&map_cmd);
2115
    qemuio_add_command(&break_cmd);
2116
    qemuio_add_command(&resume_cmd);
2117
    qemuio_add_command(&wait_break_cmd);
2118
    qemuio_add_command(&abort_cmd);
2119
}