Revision 797ac58c

b/Makefile
186 186

  
187 187
qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
188 188
qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
189
qemu-io$(EXESUF): qemu-io.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
189
qemu-io$(EXESUF): qemu-io.o qemu-io-cmds.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
190 190

  
191 191
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
192 192

  
b/qemu-io-cmds.c
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-common.h"
12
#include "block/block_int.h"
13
#include "cmd.h"
14

  
15
#define CMD_NOFILE_OK   0x01
16

  
17
int qemuio_misalign;
18

  
19
static int64_t cvtnum(const char *s)
20
{
21
    char *end;
22
    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
23
}
24

  
25
/*
26
 * Parse the pattern argument to various sub-commands.
27
 *
28
 * Because the pattern is used as an argument to memset it must evaluate
29
 * to an unsigned integer that fits into a single byte.
30
 */
31
static int parse_pattern(const char *arg)
32
{
33
    char *endptr = NULL;
34
    long pattern;
35

  
36
    pattern = strtol(arg, &endptr, 0);
37
    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
38
        printf("%s is not a valid pattern byte\n", arg);
39
        return -1;
40
    }
41

  
42
    return pattern;
43
}
44

  
45
/*
46
 * Memory allocation helpers.
47
 *
48
 * Make sure memory is aligned by default, or purposefully misaligned if
49
 * that is specified on the command line.
50
 */
51

  
52
#define MISALIGN_OFFSET     16
53
static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
54
{
55
    void *buf;
56

  
57
    if (qemuio_misalign) {
58
        len += MISALIGN_OFFSET;
59
    }
60
    buf = qemu_blockalign(bs, len);
61
    memset(buf, pattern, len);
62
    if (qemuio_misalign) {
63
        buf += MISALIGN_OFFSET;
64
    }
65
    return buf;
66
}
67

  
68
static void qemu_io_free(void *p)
69
{
70
    if (qemuio_misalign) {
71
        p -= MISALIGN_OFFSET;
72
    }
73
    qemu_vfree(p);
74
}
75

  
76
static void dump_buffer(const void *buffer, int64_t offset, int len)
77
{
78
    int i, j;
79
    const uint8_t *p;
80

  
81
    for (i = 0, p = buffer; i < len; i += 16) {
82
        const uint8_t *s = p;
83

  
84
        printf("%08" PRIx64 ":  ", offset + i);
85
        for (j = 0; j < 16 && i + j < len; j++, p++) {
86
            printf("%02x ", *p);
87
        }
88
        printf(" ");
89
        for (j = 0; j < 16 && i + j < len; j++, s++) {
90
            if (isalnum(*s)) {
91
                printf("%c", *s);
92
            } else {
93
                printf(".");
94
            }
95
        }
96
        printf("\n");
97
    }
98
}
99

  
100
static void print_report(const char *op, struct timeval *t, int64_t offset,
101
                         int count, int total, int cnt, int Cflag)
102
{
103
    char s1[64], s2[64], ts[64];
104

  
105
    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
106
    if (!Cflag) {
107
        cvtstr((double)total, s1, sizeof(s1));
108
        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
109
        printf("%s %d/%d bytes at offset %" PRId64 "\n",
110
               op, total, count, offset);
111
        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
112
               s1, cnt, ts, s2, tdiv((double)cnt, *t));
113
    } else {/* bytes,ops,time,bytes/sec,ops/sec */
114
        printf("%d,%d,%s,%.3f,%.3f\n",
115
            total, cnt, ts,
116
            tdiv((double)total, *t),
117
            tdiv((double)cnt, *t));
118
    }
119
}
120

  
121
/*
122
 * Parse multiple length statements for vectored I/O, and construct an I/O
123
 * vector matching it.
124
 */
125
static void *
126
create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
127
             int pattern)
128
{
129
    size_t *sizes = g_new0(size_t, nr_iov);
130
    size_t count = 0;
131
    void *buf = NULL;
132
    void *p;
133
    int i;
134

  
135
    for (i = 0; i < nr_iov; i++) {
136
        char *arg = argv[i];
137
        int64_t len;
138

  
139
        len = cvtnum(arg);
140
        if (len < 0) {
141
            printf("non-numeric length argument -- %s\n", arg);
142
            goto fail;
143
        }
144

  
145
        /* should be SIZE_T_MAX, but that doesn't exist */
146
        if (len > INT_MAX) {
147
            printf("too large length argument -- %s\n", arg);
148
            goto fail;
149
        }
150

  
151
        if (len & 0x1ff) {
152
            printf("length argument %" PRId64
153
                   " is not sector aligned\n", len);
154
            goto fail;
155
        }
156

  
157
        sizes[i] = len;
158
        count += len;
159
    }
160

  
161
    qemu_iovec_init(qiov, nr_iov);
162

  
163
    buf = p = qemu_io_alloc(bs, count, pattern);
164

  
165
    for (i = 0; i < nr_iov; i++) {
166
        qemu_iovec_add(qiov, p, sizes[i]);
167
        p += sizes[i];
168
    }
169

  
170
fail:
171
    g_free(sizes);
172
    return buf;
173
}
174

  
175
static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
176
                   int *total)
177
{
178
    int ret;
179

  
180
    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
181
    if (ret < 0) {
182
        return ret;
183
    }
184
    *total = count;
185
    return 1;
186
}
187

  
188
static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
189
                    int *total)
190
{
191
    int ret;
192

  
193
    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
194
    if (ret < 0) {
195
        return ret;
196
    }
197
    *total = count;
198
    return 1;
199
}
200

  
201
static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
202
                    int *total)
203
{
204
    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
205
    if (*total < 0) {
206
        return *total;
207
    }
208
    return 1;
209
}
210

  
211
static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
212
                     int *total)
213
{
214
    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
215
    if (*total < 0) {
216
        return *total;
217
    }
218
    return 1;
219
}
220

  
221
typedef struct {
222
    BlockDriverState *bs;
223
    int64_t offset;
224
    int count;
225
    int *total;
226
    int ret;
227
    bool done;
228
} CoWriteZeroes;
229

  
230
static void coroutine_fn co_write_zeroes_entry(void *opaque)
231
{
232
    CoWriteZeroes *data = opaque;
233

  
234
    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
235
                                     data->count / BDRV_SECTOR_SIZE);
236
    data->done = true;
237
    if (data->ret < 0) {
238
        *data->total = data->ret;
239
        return;
240
    }
241

  
242
    *data->total = data->count;
243
}
244

  
245
static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
246
                              int *total)
247
{
248
    Coroutine *co;
249
    CoWriteZeroes data = {
250
        .bs     = bs,
251
        .offset = offset,
252
        .count  = count,
253
        .total  = total,
254
        .done   = false,
255
    };
256

  
257
    co = qemu_coroutine_create(co_write_zeroes_entry);
258
    qemu_coroutine_enter(co, &data);
259
    while (!data.done) {
260
        qemu_aio_wait();
261
    }
262
    if (data.ret < 0) {
263
        return data.ret;
264
    } else {
265
        return 1;
266
    }
267
}
268

  
269
static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
270
                               int count, int *total)
271
{
272
    int ret;
273

  
274
    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
275
    if (ret < 0) {
276
        return ret;
277
    }
278
    *total = count;
279
    return 1;
280
}
281

  
282
static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
283
                           int count, int *total)
284
{
285
    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
286
    if (*total < 0) {
287
        return *total;
288
    }
289
    return 1;
290
}
291

  
292
static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
293
                           int count, int *total)
294
{
295
    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
296
    if (*total < 0) {
297
        return *total;
298
    }
299
    return 1;
300
}
301

  
302
#define NOT_DONE 0x7fffffff
303
static void aio_rw_done(void *opaque, int ret)
304
{
305
    *(int *)opaque = ret;
306
}
307

  
308
static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
309
                        int64_t offset, int *total)
310
{
311
    int async_ret = NOT_DONE;
312

  
313
    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
314
                   aio_rw_done, &async_ret);
315
    while (async_ret == NOT_DONE) {
316
        main_loop_wait(false);
317
    }
318

  
319
    *total = qiov->size;
320
    return async_ret < 0 ? async_ret : 1;
321
}
322

  
323
static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
324
                         int64_t offset, int *total)
325
{
326
    int async_ret = NOT_DONE;
327

  
328
    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
329
                    aio_rw_done, &async_ret);
330
    while (async_ret == NOT_DONE) {
331
        main_loop_wait(false);
332
    }
333

  
334
    *total = qiov->size;
335
    return async_ret < 0 ? async_ret : 1;
336
}
337

  
338
struct multiwrite_async_ret {
339
    int num_done;
340
    int error;
341
};
342

  
343
static void multiwrite_cb(void *opaque, int ret)
344
{
345
    struct multiwrite_async_ret *async_ret = opaque;
346

  
347
    async_ret->num_done++;
348
    if (ret < 0) {
349
        async_ret->error = ret;
350
    }
351
}
352

  
353
static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
354
                             int num_reqs, int *total)
355
{
356
    int i, ret;
357
    struct multiwrite_async_ret async_ret = {
358
        .num_done = 0,
359
        .error = 0,
360
    };
361

  
362
    *total = 0;
363
    for (i = 0; i < num_reqs; i++) {
364
        reqs[i].cb = multiwrite_cb;
365
        reqs[i].opaque = &async_ret;
366
        *total += reqs[i].qiov->size;
367
    }
368

  
369
    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
370
    if (ret < 0) {
371
        return ret;
372
    }
373

  
374
    while (async_ret.num_done < num_reqs) {
375
        main_loop_wait(false);
376
    }
377

  
378
    return async_ret.error < 0 ? async_ret.error : 1;
379
}
380

  
381
static void read_help(void)
382
{
383
    printf(
384
"\n"
385
" reads a range of bytes from the given offset\n"
386
"\n"
387
" Example:\n"
388
" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
389
"\n"
390
" Reads a segment of the currently open file, optionally dumping it to the\n"
391
" standard output stream (with -v option) for subsequent inspection.\n"
392
" -b, -- read from the VM state rather than the virtual disk\n"
393
" -C, -- report statistics in a machine parsable format\n"
394
" -l, -- length for pattern verification (only with -P)\n"
395
" -p, -- use bdrv_pread to read the file\n"
396
" -P, -- use a pattern to verify read data\n"
397
" -q, -- quiet mode, do not show I/O statistics\n"
398
" -s, -- start offset for pattern verification (only with -P)\n"
399
" -v, -- dump buffer to standard output\n"
400
"\n");
401
}
402

  
403
static int read_f(BlockDriverState *bs, int argc, char **argv);
404

  
405
static const cmdinfo_t read_cmd = {
406
    .name       = "read",
407
    .altname    = "r",
408
    .cfunc      = read_f,
409
    .argmin     = 2,
410
    .argmax     = -1,
411
    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
412
    .oneline    = "reads a number of bytes at a specified offset",
413
    .help       = read_help,
414
};
415

  
416
static int read_f(BlockDriverState *bs, int argc, char **argv)
417
{
418
    struct timeval t1, t2;
419
    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
420
    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
421
    int c, cnt;
422
    char *buf;
423
    int64_t offset;
424
    int count;
425
    /* Some compilers get confused and warn if this is not initialized.  */
426
    int total = 0;
427
    int pattern = 0, pattern_offset = 0, pattern_count = 0;
428

  
429
    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
430
        switch (c) {
431
        case 'b':
432
            bflag = 1;
433
            break;
434
        case 'C':
435
            Cflag = 1;
436
            break;
437
        case 'l':
438
            lflag = 1;
439
            pattern_count = cvtnum(optarg);
440
            if (pattern_count < 0) {
441
                printf("non-numeric length argument -- %s\n", optarg);
442
                return 0;
443
            }
444
            break;
445
        case 'p':
446
            pflag = 1;
447
            break;
448
        case 'P':
449
            Pflag = 1;
450
            pattern = parse_pattern(optarg);
451
            if (pattern < 0) {
452
                return 0;
453
            }
454
            break;
455
        case 'q':
456
            qflag = 1;
457
            break;
458
        case 's':
459
            sflag = 1;
460
            pattern_offset = cvtnum(optarg);
461
            if (pattern_offset < 0) {
462
                printf("non-numeric length argument -- %s\n", optarg);
463
                return 0;
464
            }
465
            break;
466
        case 'v':
467
            vflag = 1;
468
            break;
469
        default:
470
            return command_usage(&read_cmd);
471
        }
472
    }
473

  
474
    if (optind != argc - 2) {
475
        return command_usage(&read_cmd);
476
    }
477

  
478
    if (bflag && pflag) {
479
        printf("-b and -p cannot be specified at the same time\n");
480
        return 0;
481
    }
482

  
483
    offset = cvtnum(argv[optind]);
484
    if (offset < 0) {
485
        printf("non-numeric length argument -- %s\n", argv[optind]);
486
        return 0;
487
    }
488

  
489
    optind++;
490
    count = cvtnum(argv[optind]);
491
    if (count < 0) {
492
        printf("non-numeric length argument -- %s\n", argv[optind]);
493
        return 0;
494
    }
495

  
496
    if (!Pflag && (lflag || sflag)) {
497
        return command_usage(&read_cmd);
498
    }
499

  
500
    if (!lflag) {
501
        pattern_count = count - pattern_offset;
502
    }
503

  
504
    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
505
        printf("pattern verification range exceeds end of read data\n");
506
        return 0;
507
    }
508

  
509
    if (!pflag) {
510
        if (offset & 0x1ff) {
511
            printf("offset %" PRId64 " is not sector aligned\n",
512
                   offset);
513
            return 0;
514
        }
515
        if (count & 0x1ff) {
516
            printf("count %d is not sector aligned\n",
517
                   count);
518
            return 0;
519
        }
520
    }
521

  
522
    buf = qemu_io_alloc(bs, count, 0xab);
523

  
524
    gettimeofday(&t1, NULL);
525
    if (pflag) {
526
        cnt = do_pread(bs, buf, offset, count, &total);
527
    } else if (bflag) {
528
        cnt = do_load_vmstate(bs, buf, offset, count, &total);
529
    } else {
530
        cnt = do_read(bs, buf, offset, count, &total);
531
    }
532
    gettimeofday(&t2, NULL);
533

  
534
    if (cnt < 0) {
535
        printf("read failed: %s\n", strerror(-cnt));
536
        goto out;
537
    }
538

  
539
    if (Pflag) {
540
        void *cmp_buf = g_malloc(pattern_count);
541
        memset(cmp_buf, pattern, pattern_count);
542
        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
543
            printf("Pattern verification failed at offset %"
544
                   PRId64 ", %d bytes\n",
545
                   offset + pattern_offset, pattern_count);
546
        }
547
        g_free(cmp_buf);
548
    }
549

  
550
    if (qflag) {
551
        goto out;
552
    }
553

  
554
    if (vflag) {
555
        dump_buffer(buf, offset, count);
556
    }
557

  
558
    /* Finally, report back -- -C gives a parsable format */
559
    t2 = tsub(t2, t1);
560
    print_report("read", &t2, offset, count, total, cnt, Cflag);
561

  
562
out:
563
    qemu_io_free(buf);
564

  
565
    return 0;
566
}
567

  
568
static void readv_help(void)
569
{
570
    printf(
571
"\n"
572
" reads a range of bytes from the given offset into multiple buffers\n"
573
"\n"
574
" Example:\n"
575
" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
576
"\n"
577
" Reads a segment of the currently open file, optionally dumping it to the\n"
578
" standard output stream (with -v option) for subsequent inspection.\n"
579
" Uses multiple iovec buffers if more than one byte range is specified.\n"
580
" -C, -- report statistics in a machine parsable format\n"
581
" -P, -- use a pattern to verify read data\n"
582
" -v, -- dump buffer to standard output\n"
583
" -q, -- quiet mode, do not show I/O statistics\n"
584
"\n");
585
}
586

  
587
static int readv_f(BlockDriverState *bs, int argc, char **argv);
588

  
589
static const cmdinfo_t readv_cmd = {
590
    .name       = "readv",
591
    .cfunc      = readv_f,
592
    .argmin     = 2,
593
    .argmax     = -1,
594
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
595
    .oneline    = "reads a number of bytes at a specified offset",
596
    .help       = readv_help,
597
};
598

  
599
static int readv_f(BlockDriverState *bs, int argc, char **argv)
600
{
601
    struct timeval t1, t2;
602
    int Cflag = 0, qflag = 0, vflag = 0;
603
    int c, cnt;
604
    char *buf;
605
    int64_t offset;
606
    /* Some compilers get confused and warn if this is not initialized.  */
607
    int total = 0;
608
    int nr_iov;
609
    QEMUIOVector qiov;
610
    int pattern = 0;
611
    int Pflag = 0;
612

  
613
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
614
        switch (c) {
615
        case 'C':
616
            Cflag = 1;
617
            break;
618
        case 'P':
619
            Pflag = 1;
620
            pattern = parse_pattern(optarg);
621
            if (pattern < 0) {
622
                return 0;
623
            }
624
            break;
625
        case 'q':
626
            qflag = 1;
627
            break;
628
        case 'v':
629
            vflag = 1;
630
            break;
631
        default:
632
            return command_usage(&readv_cmd);
633
        }
634
    }
635

  
636
    if (optind > argc - 2) {
637
        return command_usage(&readv_cmd);
638
    }
639

  
640

  
641
    offset = cvtnum(argv[optind]);
642
    if (offset < 0) {
643
        printf("non-numeric length argument -- %s\n", argv[optind]);
644
        return 0;
645
    }
646
    optind++;
647

  
648
    if (offset & 0x1ff) {
649
        printf("offset %" PRId64 " is not sector aligned\n",
650
               offset);
651
        return 0;
652
    }
653

  
654
    nr_iov = argc - optind;
655
    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
656
    if (buf == NULL) {
657
        return 0;
658
    }
659

  
660
    gettimeofday(&t1, NULL);
661
    cnt = do_aio_readv(bs, &qiov, offset, &total);
662
    gettimeofday(&t2, NULL);
663

  
664
    if (cnt < 0) {
665
        printf("readv failed: %s\n", strerror(-cnt));
666
        goto out;
667
    }
668

  
669
    if (Pflag) {
670
        void *cmp_buf = g_malloc(qiov.size);
671
        memset(cmp_buf, pattern, qiov.size);
672
        if (memcmp(buf, cmp_buf, qiov.size)) {
673
            printf("Pattern verification failed at offset %"
674
                   PRId64 ", %zd bytes\n", offset, qiov.size);
675
        }
676
        g_free(cmp_buf);
677
    }
678

  
679
    if (qflag) {
680
        goto out;
681
    }
682

  
683
    if (vflag) {
684
        dump_buffer(buf, offset, qiov.size);
685
    }
686

  
687
    /* Finally, report back -- -C gives a parsable format */
688
    t2 = tsub(t2, t1);
689
    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
690

  
691
out:
692
    qemu_iovec_destroy(&qiov);
693
    qemu_io_free(buf);
694
    return 0;
695
}
696

  
697
static void write_help(void)
698
{
699
    printf(
700
"\n"
701
" writes a range of bytes from the given offset\n"
702
"\n"
703
" Example:\n"
704
" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
705
"\n"
706
" Writes into a segment of the currently open file, using a buffer\n"
707
" filled with a set pattern (0xcdcdcdcd).\n"
708
" -b, -- write to the VM state rather than the virtual disk\n"
709
" -c, -- write compressed data with bdrv_write_compressed\n"
710
" -p, -- use bdrv_pwrite to write the file\n"
711
" -P, -- use different pattern to fill file\n"
712
" -C, -- report statistics in a machine parsable format\n"
713
" -q, -- quiet mode, do not show I/O statistics\n"
714
" -z, -- write zeroes using bdrv_co_write_zeroes\n"
715
"\n");
716
}
717

  
718
static int write_f(BlockDriverState *bs, int argc, char **argv);
719

  
720
static const cmdinfo_t write_cmd = {
721
    .name       = "write",
722
    .altname    = "w",
723
    .cfunc      = write_f,
724
    .argmin     = 2,
725
    .argmax     = -1,
726
    .args       = "[-bcCpqz] [-P pattern ] off len",
727
    .oneline    = "writes a number of bytes at a specified offset",
728
    .help       = write_help,
729
};
730

  
731
static int write_f(BlockDriverState *bs, int argc, char **argv)
732
{
733
    struct timeval t1, t2;
734
    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
735
    int cflag = 0;
736
    int c, cnt;
737
    char *buf = NULL;
738
    int64_t offset;
739
    int count;
740
    /* Some compilers get confused and warn if this is not initialized.  */
741
    int total = 0;
742
    int pattern = 0xcd;
743

  
744
    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
745
        switch (c) {
746
        case 'b':
747
            bflag = 1;
748
            break;
749
        case 'c':
750
            cflag = 1;
751
            break;
752
        case 'C':
753
            Cflag = 1;
754
            break;
755
        case 'p':
756
            pflag = 1;
757
            break;
758
        case 'P':
759
            Pflag = 1;
760
            pattern = parse_pattern(optarg);
761
            if (pattern < 0) {
762
                return 0;
763
            }
764
            break;
765
        case 'q':
766
            qflag = 1;
767
            break;
768
        case 'z':
769
            zflag = 1;
770
            break;
771
        default:
772
            return command_usage(&write_cmd);
773
        }
774
    }
775

  
776
    if (optind != argc - 2) {
777
        return command_usage(&write_cmd);
778
    }
779

  
780
    if (bflag + pflag + zflag > 1) {
781
        printf("-b, -p, or -z cannot be specified at the same time\n");
782
        return 0;
783
    }
784

  
785
    if (zflag && Pflag) {
786
        printf("-z and -P cannot be specified at the same time\n");
787
        return 0;
788
    }
789

  
790
    offset = cvtnum(argv[optind]);
791
    if (offset < 0) {
792
        printf("non-numeric length argument -- %s\n", argv[optind]);
793
        return 0;
794
    }
795

  
796
    optind++;
797
    count = cvtnum(argv[optind]);
798
    if (count < 0) {
799
        printf("non-numeric length argument -- %s\n", argv[optind]);
800
        return 0;
801
    }
802

  
803
    if (!pflag) {
804
        if (offset & 0x1ff) {
805
            printf("offset %" PRId64 " is not sector aligned\n",
806
                   offset);
807
            return 0;
808
        }
809

  
810
        if (count & 0x1ff) {
811
            printf("count %d is not sector aligned\n",
812
                   count);
813
            return 0;
814
        }
815
    }
816

  
817
    if (!zflag) {
818
        buf = qemu_io_alloc(bs, count, pattern);
819
    }
820

  
821
    gettimeofday(&t1, NULL);
822
    if (pflag) {
823
        cnt = do_pwrite(bs, buf, offset, count, &total);
824
    } else if (bflag) {
825
        cnt = do_save_vmstate(bs, buf, offset, count, &total);
826
    } else if (zflag) {
827
        cnt = do_co_write_zeroes(bs, offset, count, &total);
828
    } else if (cflag) {
829
        cnt = do_write_compressed(bs, buf, offset, count, &total);
830
    } else {
831
        cnt = do_write(bs, buf, offset, count, &total);
832
    }
833
    gettimeofday(&t2, NULL);
834

  
835
    if (cnt < 0) {
836
        printf("write failed: %s\n", strerror(-cnt));
837
        goto out;
838
    }
839

  
840
    if (qflag) {
841
        goto out;
842
    }
843

  
844
    /* Finally, report back -- -C gives a parsable format */
845
    t2 = tsub(t2, t1);
846
    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
847

  
848
out:
849
    if (!zflag) {
850
        qemu_io_free(buf);
851
    }
852

  
853
    return 0;
854
}
855

  
856
static void
857
writev_help(void)
858
{
859
    printf(
860
"\n"
861
" writes a range of bytes from the given offset source from multiple buffers\n"
862
"\n"
863
" Example:\n"
864
" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
865
"\n"
866
" Writes into a segment of the currently open file, using a buffer\n"
867
" filled with a set pattern (0xcdcdcdcd).\n"
868
" -P, -- use different pattern to fill file\n"
869
" -C, -- report statistics in a machine parsable format\n"
870
" -q, -- quiet mode, do not show I/O statistics\n"
871
"\n");
872
}
873

  
874
static int writev_f(BlockDriverState *bs, int argc, char **argv);
875

  
876
static const cmdinfo_t writev_cmd = {
877
    .name       = "writev",
878
    .cfunc      = writev_f,
879
    .argmin     = 2,
880
    .argmax     = -1,
881
    .args       = "[-Cq] [-P pattern ] off len [len..]",
882
    .oneline    = "writes a number of bytes at a specified offset",
883
    .help       = writev_help,
884
};
885

  
886
static int writev_f(BlockDriverState *bs, int argc, char **argv)
887
{
888
    struct timeval t1, t2;
889
    int Cflag = 0, qflag = 0;
890
    int c, cnt;
891
    char *buf;
892
    int64_t offset;
893
    /* Some compilers get confused and warn if this is not initialized.  */
894
    int total = 0;
895
    int nr_iov;
896
    int pattern = 0xcd;
897
    QEMUIOVector qiov;
898

  
899
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
900
        switch (c) {
901
        case 'C':
902
            Cflag = 1;
903
            break;
904
        case 'q':
905
            qflag = 1;
906
            break;
907
        case 'P':
908
            pattern = parse_pattern(optarg);
909
            if (pattern < 0) {
910
                return 0;
911
            }
912
            break;
913
        default:
914
            return command_usage(&writev_cmd);
915
        }
916
    }
917

  
918
    if (optind > argc - 2) {
919
        return command_usage(&writev_cmd);
920
    }
921

  
922
    offset = cvtnum(argv[optind]);
923
    if (offset < 0) {
924
        printf("non-numeric length argument -- %s\n", argv[optind]);
925
        return 0;
926
    }
927
    optind++;
928

  
929
    if (offset & 0x1ff) {
930
        printf("offset %" PRId64 " is not sector aligned\n",
931
               offset);
932
        return 0;
933
    }
934

  
935
    nr_iov = argc - optind;
936
    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
937
    if (buf == NULL) {
938
        return 0;
939
    }
940

  
941
    gettimeofday(&t1, NULL);
942
    cnt = do_aio_writev(bs, &qiov, offset, &total);
943
    gettimeofday(&t2, NULL);
944

  
945
    if (cnt < 0) {
946
        printf("writev failed: %s\n", strerror(-cnt));
947
        goto out;
948
    }
949

  
950
    if (qflag) {
951
        goto out;
952
    }
953

  
954
    /* Finally, report back -- -C gives a parsable format */
955
    t2 = tsub(t2, t1);
956
    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
957
out:
958
    qemu_iovec_destroy(&qiov);
959
    qemu_io_free(buf);
960
    return 0;
961
}
962

  
963
static void multiwrite_help(void)
964
{
965
    printf(
966
"\n"
967
" writes a range of bytes from the given offset source from multiple buffers,\n"
968
" in a batch of requests that may be merged by qemu\n"
969
"\n"
970
" Example:\n"
971
" 'multiwrite 512 1k 1k ; 4k 1k'\n"
972
"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
973
"\n"
974
" Writes into a segment of the currently open file, using a buffer\n"
975
" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
976
" by one for each request contained in the multiwrite command.\n"
977
" -P, -- use different pattern to fill file\n"
978
" -C, -- report statistics in a machine parsable format\n"
979
" -q, -- quiet mode, do not show I/O statistics\n"
980
"\n");
981
}
982

  
983
static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
984

  
985
static const cmdinfo_t multiwrite_cmd = {
986
    .name       = "multiwrite",
987
    .cfunc      = multiwrite_f,
988
    .argmin     = 2,
989
    .argmax     = -1,
990
    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
991
    .oneline    = "issues multiple write requests at once",
992
    .help       = multiwrite_help,
993
};
994

  
995
static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
996
{
997
    struct timeval t1, t2;
998
    int Cflag = 0, qflag = 0;
999
    int c, cnt;
1000
    char **buf;
1001
    int64_t offset, first_offset = 0;
1002
    /* Some compilers get confused and warn if this is not initialized.  */
1003
    int total = 0;
1004
    int nr_iov;
1005
    int nr_reqs;
1006
    int pattern = 0xcd;
1007
    QEMUIOVector *qiovs;
1008
    int i;
1009
    BlockRequest *reqs;
1010

  
1011
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1012
        switch (c) {
1013
        case 'C':
1014
            Cflag = 1;
1015
            break;
1016
        case 'q':
1017
            qflag = 1;
1018
            break;
1019
        case 'P':
1020
            pattern = parse_pattern(optarg);
1021
            if (pattern < 0) {
1022
                return 0;
1023
            }
1024
            break;
1025
        default:
1026
            return command_usage(&writev_cmd);
1027
        }
1028
    }
1029

  
1030
    if (optind > argc - 2) {
1031
        return command_usage(&writev_cmd);
1032
    }
1033

  
1034
    nr_reqs = 1;
1035
    for (i = optind; i < argc; i++) {
1036
        if (!strcmp(argv[i], ";")) {
1037
            nr_reqs++;
1038
        }
1039
    }
1040

  
1041
    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1042
    buf = g_malloc0(nr_reqs * sizeof(*buf));
1043
    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1044

  
1045
    for (i = 0; i < nr_reqs && optind < argc; i++) {
1046
        int j;
1047

  
1048
        /* Read the offset of the request */
1049
        offset = cvtnum(argv[optind]);
1050
        if (offset < 0) {
1051
            printf("non-numeric offset argument -- %s\n", argv[optind]);
1052
            goto out;
1053
        }
1054
        optind++;
1055

  
1056
        if (offset & 0x1ff) {
1057
            printf("offset %lld is not sector aligned\n",
1058
                   (long long)offset);
1059
            goto out;
1060
        }
1061

  
1062
        if (i == 0) {
1063
            first_offset = offset;
1064
        }
1065

  
1066
        /* Read lengths for qiov entries */
1067
        for (j = optind; j < argc; j++) {
1068
            if (!strcmp(argv[j], ";")) {
1069
                break;
1070
            }
1071
        }
1072

  
1073
        nr_iov = j - optind;
1074

  
1075
        /* Build request */
1076
        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
1077
        if (buf[i] == NULL) {
1078
            goto out;
1079
        }
1080

  
1081
        reqs[i].qiov = &qiovs[i];
1082
        reqs[i].sector = offset >> 9;
1083
        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1084

  
1085
        optind = j + 1;
1086

  
1087
        pattern++;
1088
    }
1089

  
1090
    /* If there were empty requests at the end, ignore them */
1091
    nr_reqs = i;
1092

  
1093
    gettimeofday(&t1, NULL);
1094
    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
1095
    gettimeofday(&t2, NULL);
1096

  
1097
    if (cnt < 0) {
1098
        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1099
        goto out;
1100
    }
1101

  
1102
    if (qflag) {
1103
        goto out;
1104
    }
1105

  
1106
    /* Finally, report back -- -C gives a parsable format */
1107
    t2 = tsub(t2, t1);
1108
    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1109
out:
1110
    for (i = 0; i < nr_reqs; i++) {
1111
        qemu_io_free(buf[i]);
1112
        if (reqs[i].qiov != NULL) {
1113
            qemu_iovec_destroy(&qiovs[i]);
1114
        }
1115
    }
1116
    g_free(buf);
1117
    g_free(reqs);
1118
    g_free(qiovs);
1119
    return 0;
1120
}
1121

  
1122
struct aio_ctx {
1123
    QEMUIOVector qiov;
1124
    int64_t offset;
1125
    char *buf;
1126
    int qflag;
1127
    int vflag;
1128
    int Cflag;
1129
    int Pflag;
1130
    int pattern;
1131
    struct timeval t1;
1132
};
1133

  
1134
static void aio_write_done(void *opaque, int ret)
1135
{
1136
    struct aio_ctx *ctx = opaque;
1137
    struct timeval t2;
1138

  
1139
    gettimeofday(&t2, NULL);
1140

  
1141

  
1142
    if (ret < 0) {
1143
        printf("aio_write failed: %s\n", strerror(-ret));
1144
        goto out;
1145
    }
1146

  
1147
    if (ctx->qflag) {
1148
        goto out;
1149
    }
1150

  
1151
    /* Finally, report back -- -C gives a parsable format */
1152
    t2 = tsub(t2, ctx->t1);
1153
    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1154
                 ctx->qiov.size, 1, ctx->Cflag);
1155
out:
1156
    qemu_io_free(ctx->buf);
1157
    qemu_iovec_destroy(&ctx->qiov);
1158
    g_free(ctx);
1159
}
1160

  
1161
static void aio_read_done(void *opaque, int ret)
1162
{
1163
    struct aio_ctx *ctx = opaque;
1164
    struct timeval t2;
1165

  
1166
    gettimeofday(&t2, NULL);
1167

  
1168
    if (ret < 0) {
1169
        printf("readv failed: %s\n", strerror(-ret));
1170
        goto out;
1171
    }
1172

  
1173
    if (ctx->Pflag) {
1174
        void *cmp_buf = g_malloc(ctx->qiov.size);
1175

  
1176
        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1177
        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1178
            printf("Pattern verification failed at offset %"
1179
                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1180
        }
1181
        g_free(cmp_buf);
1182
    }
1183

  
1184
    if (ctx->qflag) {
1185
        goto out;
1186
    }
1187

  
1188
    if (ctx->vflag) {
1189
        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1190
    }
1191

  
1192
    /* Finally, report back -- -C gives a parsable format */
1193
    t2 = tsub(t2, ctx->t1);
1194
    print_report("read", &t2, ctx->offset, ctx->qiov.size,
1195
                 ctx->qiov.size, 1, ctx->Cflag);
1196
out:
1197
    qemu_io_free(ctx->buf);
1198
    qemu_iovec_destroy(&ctx->qiov);
1199
    g_free(ctx);
1200
}
1201

  
1202
static void aio_read_help(void)
1203
{
1204
    printf(
1205
"\n"
1206
" asynchronously reads a range of bytes from the given offset\n"
1207
"\n"
1208
" Example:\n"
1209
" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1210
"\n"
1211
" Reads a segment of the currently open file, optionally dumping it to the\n"
1212
" standard output stream (with -v option) for subsequent inspection.\n"
1213
" The read is performed asynchronously and the aio_flush command must be\n"
1214
" used to ensure all outstanding aio requests have been completed.\n"
1215
" -C, -- report statistics in a machine parsable format\n"
1216
" -P, -- use a pattern to verify read data\n"
1217
" -v, -- dump buffer to standard output\n"
1218
" -q, -- quiet mode, do not show I/O statistics\n"
1219
"\n");
1220
}
1221

  
1222
static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1223

  
1224
static const cmdinfo_t aio_read_cmd = {
1225
    .name       = "aio_read",
1226
    .cfunc      = aio_read_f,
1227
    .argmin     = 2,
1228
    .argmax     = -1,
1229
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
1230
    .oneline    = "asynchronously reads a number of bytes",
1231
    .help       = aio_read_help,
1232
};
1233

  
1234
static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
1235
{
1236
    int nr_iov, c;
1237
    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1238

  
1239
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1240
        switch (c) {
1241
        case 'C':
1242
            ctx->Cflag = 1;
1243
            break;
1244
        case 'P':
1245
            ctx->Pflag = 1;
1246
            ctx->pattern = parse_pattern(optarg);
1247
            if (ctx->pattern < 0) {
1248
                g_free(ctx);
1249
                return 0;
1250
            }
1251
            break;
1252
        case 'q':
1253
            ctx->qflag = 1;
1254
            break;
1255
        case 'v':
1256
            ctx->vflag = 1;
1257
            break;
1258
        default:
1259
            g_free(ctx);
1260
            return command_usage(&aio_read_cmd);
1261
        }
1262
    }
1263

  
1264
    if (optind > argc - 2) {
1265
        g_free(ctx);
1266
        return command_usage(&aio_read_cmd);
1267
    }
1268

  
1269
    ctx->offset = cvtnum(argv[optind]);
1270
    if (ctx->offset < 0) {
1271
        printf("non-numeric length argument -- %s\n", argv[optind]);
1272
        g_free(ctx);
1273
        return 0;
1274
    }
1275
    optind++;
1276

  
1277
    if (ctx->offset & 0x1ff) {
1278
        printf("offset %" PRId64 " is not sector aligned\n",
1279
               ctx->offset);
1280
        g_free(ctx);
1281
        return 0;
1282
    }
1283

  
1284
    nr_iov = argc - optind;
1285
    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1286
    if (ctx->buf == NULL) {
1287
        g_free(ctx);
1288
        return 0;
1289
    }
1290

  
1291
    gettimeofday(&ctx->t1, NULL);
1292
    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1293
                   ctx->qiov.size >> 9, aio_read_done, ctx);
1294
    return 0;
1295
}
1296

  
1297
static void aio_write_help(void)
1298
{
1299
    printf(
1300
"\n"
1301
" asynchronously writes a range of bytes from the given offset source\n"
1302
" from multiple buffers\n"
1303
"\n"
1304
" Example:\n"
1305
" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1306
"\n"
1307
" Writes into a segment of the currently open file, using a buffer\n"
1308
" filled with a set pattern (0xcdcdcdcd).\n"
1309
" The write is performed asynchronously and the aio_flush command must be\n"
1310
" used to ensure all outstanding aio requests have been completed.\n"
1311
" -P, -- use different pattern to fill file\n"
1312
" -C, -- report statistics in a machine parsable format\n"
1313
" -q, -- quiet mode, do not show I/O statistics\n"
1314
"\n");
1315
}
1316

  
1317
static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1318

  
1319
static const cmdinfo_t aio_write_cmd = {
1320
    .name       = "aio_write",
1321
    .cfunc      = aio_write_f,
1322
    .argmin     = 2,
1323
    .argmax     = -1,
1324
    .args       = "[-Cq] [-P pattern ] off len [len..]",
1325
    .oneline    = "asynchronously writes a number of bytes",
1326
    .help       = aio_write_help,
1327
};
1328

  
1329
static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
1330
{
1331
    int nr_iov, c;
1332
    int pattern = 0xcd;
1333
    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1334

  
1335
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1336
        switch (c) {
1337
        case 'C':
1338
            ctx->Cflag = 1;
1339
            break;
1340
        case 'q':
1341
            ctx->qflag = 1;
1342
            break;
1343
        case 'P':
1344
            pattern = parse_pattern(optarg);
1345
            if (pattern < 0) {
1346
                g_free(ctx);
1347
                return 0;
1348
            }
1349
            break;
1350
        default:
1351
            g_free(ctx);
1352
            return command_usage(&aio_write_cmd);
1353
        }
1354
    }
1355

  
1356
    if (optind > argc - 2) {
1357
        g_free(ctx);
1358
        return command_usage(&aio_write_cmd);
1359
    }
1360

  
1361
    ctx->offset = cvtnum(argv[optind]);
1362
    if (ctx->offset < 0) {
1363
        printf("non-numeric length argument -- %s\n", argv[optind]);
1364
        g_free(ctx);
1365
        return 0;
1366
    }
1367
    optind++;
1368

  
1369
    if (ctx->offset & 0x1ff) {
1370
        printf("offset %" PRId64 " is not sector aligned\n",
1371
               ctx->offset);
1372
        g_free(ctx);
1373
        return 0;
1374
    }
1375

  
1376
    nr_iov = argc - optind;
1377
    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
1378
    if (ctx->buf == NULL) {
1379
        g_free(ctx);
1380
        return 0;
1381
    }
1382

  
1383
    gettimeofday(&ctx->t1, NULL);
1384
    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1385
                    ctx->qiov.size >> 9, aio_write_done, ctx);
1386
    return 0;
1387
}
1388

  
1389
static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1390
{
1391
    bdrv_drain_all();
1392
    return 0;
1393
}
1394

  
1395
static const cmdinfo_t aio_flush_cmd = {
1396
    .name       = "aio_flush",
1397
    .cfunc      = aio_flush_f,
1398
    .oneline    = "completes all outstanding aio requests"
1399
};
1400

  
1401
static int flush_f(BlockDriverState *bs, int argc, char **argv)
1402
{
1403
    bdrv_flush(bs);
1404
    return 0;
1405
}
1406

  
1407
static const cmdinfo_t flush_cmd = {
1408
    .name       = "flush",
1409
    .altname    = "f",
1410
    .cfunc      = flush_f,
1411
    .oneline    = "flush all in-core file state to disk",
1412
};
1413

  
1414
static int truncate_f(BlockDriverState *bs, int argc, char **argv)
1415
{
1416
    int64_t offset;
1417
    int ret;
1418

  
1419
    offset = cvtnum(argv[1]);
1420
    if (offset < 0) {
1421
        printf("non-numeric truncate argument -- %s\n", argv[1]);
1422
        return 0;
1423
    }
1424

  
1425
    ret = bdrv_truncate(bs, offset);
1426
    if (ret < 0) {
1427
        printf("truncate: %s\n", strerror(-ret));
1428
        return 0;
1429
    }
1430

  
1431
    return 0;
1432
}
1433

  
1434
static const cmdinfo_t truncate_cmd = {
1435
    .name       = "truncate",
1436
    .altname    = "t",
1437
    .cfunc      = truncate_f,
1438
    .argmin     = 1,
1439
    .argmax     = 1,
1440
    .args       = "off",
1441
    .oneline    = "truncates the current file at the given offset",
1442
};
1443

  
1444
static int length_f(BlockDriverState *bs, int argc, char **argv)
1445
{
1446
    int64_t size;
1447
    char s1[64];
1448

  
1449
    size = bdrv_getlength(bs);
1450
    if (size < 0) {
1451
        printf("getlength: %s\n", strerror(-size));
1452
        return 0;
1453
    }
1454

  
1455
    cvtstr(size, s1, sizeof(s1));
1456
    printf("%s\n", s1);
1457
    return 0;
1458
}
1459

  
1460

  
1461
static const cmdinfo_t length_cmd = {
1462
    .name   = "length",
1463
    .altname    = "l",
1464
    .cfunc      = length_f,
1465
    .oneline    = "gets the length of the current file",
1466
};
1467

  
1468

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff