Statistics
| Branch: | Revision:

root / qemu-io.c @ e432cef9

History | View | Annotate | Download (30.6 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
#include <sys/time.h>
11
#include <sys/types.h>
12
#include <stdarg.h>
13
#include <stdio.h>
14
#include <getopt.h>
15
#include <libgen.h>
16

    
17
#include "qemu-common.h"
18
#include "block_int.h"
19
#include "cmd.h"
20

    
21
#define VERSION        "0.0.1"
22

    
23
#define CMD_NOFILE_OK        0x01
24

    
25
char *progname;
26
static BlockDriverState *bs;
27

    
28
static int misalign;
29

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

    
41
        pattern = strtol(arg, &endptr, 0);
42
        if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
43
                printf("%s is not a valid pattern byte\n", arg);
44
                return -1;
45
        }
46

    
47
        return pattern;
48
}
49

    
50
/*
51
 * Memory allocation helpers.
52
 *
53
 * Make sure memory is aligned by default, or purposefully misaligned if
54
 * that is specified on the command line.
55
 */
56

    
57
#define MISALIGN_OFFSET                16
58
static void *qemu_io_alloc(size_t len, int pattern)
59
{
60
        void *buf;
61

    
62
        if (misalign)
63
                len += MISALIGN_OFFSET;
64
        buf = qemu_memalign(512, len);
65
        memset(buf, pattern, len);
66
        if (misalign)
67
                buf += MISALIGN_OFFSET;
68
        return buf;
69
}
70

    
71
static void qemu_io_free(void *p)
72
{
73
        if (misalign)
74
                p -= MISALIGN_OFFSET;
75
        qemu_vfree(p);
76
}
77

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

    
84
        for (i = 0, p = buffer; i < len; i += 16) {
85
                const uint8_t *s = p;
86

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

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

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

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

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

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

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

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

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

    
162
        qemu_iovec_init(qiov, nr_iov);
163

    
164
        buf = p = qemu_io_alloc(count, pattern);
165

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

    
171
fail:
172
        free(sizes);
173
        return buf;
174
}
175

    
176
static int do_read(char *buf, int64_t offset, int count, 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
        *total = count;
184
        return 1;
185
}
186

    
187
static int do_write(char *buf, int64_t offset, int count, int *total)
188
{
189
        int ret;
190

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

    
198
static int do_pread(char *buf, int64_t offset, int count, int *total)
199
{
200
        *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
201
        if (*total < 0)
202
                return *total;
203
        return 1;
204
}
205

    
206
static int do_pwrite(char *buf, int64_t offset, int count, int *total)
207
{
208
        *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
209
        if (*total < 0)
210
                return *total;
211
        return 1;
212
}
213

    
214
static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
215
{
216
        *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
217
        if (*total < 0)
218
                return *total;
219
        return 1;
220
}
221

    
222
static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
223
{
224
        *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
225
        if (*total < 0)
226
                return *total;
227
        return 1;
228
}
229

    
230
#define NOT_DONE 0x7fffffff
231
static void aio_rw_done(void *opaque, int ret)
232
{
233
        *(int *)opaque = ret;
234
}
235

    
236
static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
237
{
238
        BlockDriverAIOCB *acb;
239
        int async_ret = NOT_DONE;
240

    
241
        acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
242
                             aio_rw_done, &async_ret);
243
        if (!acb)
244
                return -EIO;
245

    
246
        while (async_ret == NOT_DONE)
247
                qemu_aio_wait();
248

    
249
        *total = qiov->size;
250
        return async_ret < 0 ? async_ret : 1;
251
}
252

    
253
static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
254
{
255
        BlockDriverAIOCB *acb;
256
        int async_ret = NOT_DONE;
257

    
258
        acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
259
                              aio_rw_done, &async_ret);
260
        if (!acb)
261
                return -EIO;
262

    
263
        while (async_ret == NOT_DONE)
264
                qemu_aio_wait();
265

    
266
        *total = qiov->size;
267
        return async_ret < 0 ? async_ret : 1;
268
}
269

    
270

    
271
static void
272
read_help(void)
273
{
274
        printf(
275
"\n"
276
" reads a range of bytes from the given offset\n"
277
"\n"
278
" Example:\n"
279
" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
280
"\n"
281
" Reads a segment of the currently open file, optionally dumping it to the\n"
282
" standard output stream (with -v option) for subsequent inspection.\n"
283
" -b, -- read from the VM state rather than the virtual disk\n"
284
" -C, -- report statistics in a machine parsable format\n"
285
" -l, -- length for pattern verification (only with -P)\n"
286
" -p, -- use bdrv_pread to read the file\n"
287
" -P, -- use a pattern to verify read data\n"
288
" -q, -- quite mode, do not show I/O statistics\n"
289
" -s, -- start offset for pattern verification (only with -P)\n"
290
" -v, -- dump buffer to standard output\n"
291
"\n");
292
}
293

    
294
static int read_f(int argc, char **argv);
295

    
296
static const cmdinfo_t read_cmd = {
297
        .name                = "read",
298
        .altname        = "r",
299
        .cfunc                = read_f,
300
        .argmin                = 2,
301
        .argmax                = -1,
302
        .args                = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
303
        .oneline        = "reads a number of bytes at a specified offset",
304
        .help                = read_help,
305
};
306

    
307
static int
308
read_f(int argc, char **argv)
309
{
310
        struct timeval t1, t2;
311
        int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
312
        int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
313
        int c, cnt;
314
        char *buf;
315
        int64_t offset;
316
        int count;
317
        /* Some compilers get confused and warn if this is not initialized.  */
318
        int total = 0;
319
        int pattern = 0, pattern_offset = 0, pattern_count = 0;
320

    
321
        while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
322
                switch (c) {
323
                case 'b':
324
                        bflag = 1;
325
                        break;
326
                case 'C':
327
                        Cflag = 1;
328
                        break;
329
                case 'l':
330
                        lflag = 1;
331
                        pattern_count = cvtnum(optarg);
332
                        if (pattern_count < 0) {
333
                                printf("non-numeric length argument -- %s\n", optarg);
334
                                return 0;
335
                        }
336
                        break;
337
                case 'p':
338
                        pflag = 1;
339
                        break;
340
                case 'P':
341
                        Pflag = 1;
342
                        pattern = parse_pattern(optarg);
343
                        if (pattern < 0)
344
                                return 0;
345
                        break;
346
                case 'q':
347
                        qflag = 1;
348
                        break;
349
                case 's':
350
                        sflag = 1;
351
                        pattern_offset = cvtnum(optarg);
352
                        if (pattern_offset < 0) {
353
                                printf("non-numeric length argument -- %s\n", optarg);
354
                                return 0;
355
                        }
356
                        break;
357
                case 'v':
358
                        vflag = 1;
359
                        break;
360
                default:
361
                        return command_usage(&read_cmd);
362
                }
363
        }
364

    
365
        if (optind != argc - 2)
366
                return command_usage(&read_cmd);
367

    
368
        if (bflag && pflag) {
369
                printf("-b and -p cannot be specified at the same time\n");
370
                return 0;
371
        }
372

    
373
        offset = cvtnum(argv[optind]);
374
        if (offset < 0) {
375
                printf("non-numeric length argument -- %s\n", argv[optind]);
376
                return 0;
377
        }
378

    
379
        optind++;
380
        count = cvtnum(argv[optind]);
381
        if (count < 0) {
382
                printf("non-numeric length argument -- %s\n", argv[optind]);
383
                return 0;
384
        }
385

    
386
    if (!Pflag && (lflag || sflag)) {
387
        return command_usage(&read_cmd);
388
    }
389

    
390
    if (!lflag) {
391
        pattern_count = count - pattern_offset;
392
    }
393

    
394
    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
395
        printf("pattern verfication range exceeds end of read data\n");
396
        return 0;
397
    }
398

    
399
        if (!pflag)
400
                if (offset & 0x1ff) {
401
                        printf("offset %lld is not sector aligned\n",
402
                                (long long)offset);
403
                        return 0;
404

    
405
                if (count & 0x1ff) {
406
                        printf("count %d is not sector aligned\n",
407
                                count);
408
                        return 0;
409
                }
410
        }
411

    
412
        buf = qemu_io_alloc(count, 0xab);
413

    
414
        gettimeofday(&t1, NULL);
415
        if (pflag)
416
                cnt = do_pread(buf, offset, count, &total);
417
        else if (bflag)
418
                cnt = do_load_vmstate(buf, offset, count, &total);
419
        else
420
                cnt = do_read(buf, offset, count, &total);
421
        gettimeofday(&t2, NULL);
422

    
423
        if (cnt < 0) {
424
                printf("read failed: %s\n", strerror(-cnt));
425
                goto out;
426
        }
427

    
428
        if (Pflag) {
429
                void* cmp_buf = malloc(pattern_count);
430
                memset(cmp_buf, pattern, pattern_count);
431
                if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
432
                        printf("Pattern verification failed at offset %lld, "
433
                                "%d bytes\n",
434
                                (long long) offset + pattern_offset, pattern_count);
435
                }
436
                free(cmp_buf);
437
        }
438

    
439
        if (qflag)
440
                goto out;
441

    
442
        if (vflag)
443
                dump_buffer(buf, offset, count);
444

    
445
        /* Finally, report back -- -C gives a parsable format */
446
        t2 = tsub(t2, t1);
447
        print_report("read", &t2, offset, count, total, cnt, Cflag);
448

    
449
out:
450
        qemu_io_free(buf);
451

    
452
        return 0;
453
}
454

    
455
static void
456
readv_help(void)
457
{
458
        printf(
459
"\n"
460
" reads a range of bytes from the given offset into multiple buffers\n"
461
"\n"
462
" Example:\n"
463
" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
464
"\n"
465
" Reads a segment of the currently open file, optionally dumping it to the\n"
466
" standard output stream (with -v option) for subsequent inspection.\n"
467
" Uses multiple iovec buffers if more than one byte range is specified.\n"
468
" -C, -- report statistics in a machine parsable format\n"
469
" -P, -- use a pattern to verify read data\n"
470
" -v, -- dump buffer to standard output\n"
471
" -q, -- quite mode, do not show I/O statistics\n"
472
"\n");
473
}
474

    
475
static int readv_f(int argc, char **argv);
476

    
477
static const cmdinfo_t readv_cmd = {
478
        .name                = "readv",
479
        .cfunc                = readv_f,
480
        .argmin                = 2,
481
        .argmax                = -1,
482
        .args                = "[-Cqv] [-P pattern ] off len [len..]",
483
        .oneline        = "reads a number of bytes at a specified offset",
484
        .help                = readv_help,
485
};
486

    
487
static int
488
readv_f(int argc, char **argv)
489
{
490
        struct timeval t1, t2;
491
        int Cflag = 0, qflag = 0, vflag = 0;
492
        int c, cnt;
493
        char *buf;
494
        int64_t offset;
495
        /* Some compilers get confused and warn if this is not initialized.  */
496
        int total = 0;
497
        int nr_iov;
498
        QEMUIOVector qiov;
499
        int pattern = 0;
500
        int Pflag = 0;
501

    
502
        while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
503
                switch (c) {
504
                case 'C':
505
                        Cflag = 1;
506
                        break;
507
                case 'P':
508
                        Pflag = 1;
509
                        pattern = parse_pattern(optarg);
510
                        if (pattern < 0)
511
                                return 0;
512
                        break;
513
                case 'q':
514
                        qflag = 1;
515
                        break;
516
                case 'v':
517
                        vflag = 1;
518
                        break;
519
                default:
520
                        return command_usage(&readv_cmd);
521
                }
522
        }
523

    
524
        if (optind > argc - 2)
525
                return command_usage(&readv_cmd);
526

    
527

    
528
        offset = cvtnum(argv[optind]);
529
        if (offset < 0) {
530
                printf("non-numeric length argument -- %s\n", argv[optind]);
531
                return 0;
532
        }
533
        optind++;
534

    
535
        if (offset & 0x1ff) {
536
                printf("offset %lld is not sector aligned\n",
537
                        (long long)offset);
538
                return 0;
539
        }
540

    
541
        nr_iov = argc - optind;
542
        buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
543

    
544
        gettimeofday(&t1, NULL);
545
        cnt = do_aio_readv(&qiov, offset, &total);
546
        gettimeofday(&t2, NULL);
547

    
548
        if (cnt < 0) {
549
                printf("readv failed: %s\n", strerror(-cnt));
550
                goto out;
551
        }
552

    
553
        if (Pflag) {
554
                void* cmp_buf = malloc(qiov.size);
555
                memset(cmp_buf, pattern, qiov.size);
556
                if (memcmp(buf, cmp_buf, qiov.size)) {
557
                        printf("Pattern verification failed at offset %lld, "
558
                                "%zd bytes\n",
559
                                (long long) offset, qiov.size);
560
                }
561
                free(cmp_buf);
562
        }
563

    
564
        if (qflag)
565
                goto out;
566

    
567
        if (vflag)
568
                dump_buffer(buf, offset, qiov.size);
569

    
570
        /* Finally, report back -- -C gives a parsable format */
571
        t2 = tsub(t2, t1);
572
        print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
573

    
574
out:
575
        qemu_io_free(buf);
576
        return 0;
577
}
578

    
579
static void
580
write_help(void)
581
{
582
        printf(
583
"\n"
584
" writes a range of bytes from the given offset\n"
585
"\n"
586
" Example:\n"
587
" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
588
"\n"
589
" Writes into a segment of the currently open file, using a buffer\n"
590
" filled with a set pattern (0xcdcdcdcd).\n"
591
" -b, -- write to the VM state rather than the virtual disk\n"
592
" -p, -- use bdrv_pwrite to write the file\n"
593
" -P, -- use different pattern to fill file\n"
594
" -C, -- report statistics in a machine parsable format\n"
595
" -q, -- quite mode, do not show I/O statistics\n"
596
"\n");
597
}
598

    
599
static int write_f(int argc, char **argv);
600

    
601
static const cmdinfo_t write_cmd = {
602
        .name                = "write",
603
        .altname        = "w",
604
        .cfunc                = write_f,
605
        .argmin                = 2,
606
        .argmax                = -1,
607
        .args                = "[-abCpq] [-P pattern ] off len",
608
        .oneline        = "writes a number of bytes at a specified offset",
609
        .help                = write_help,
610
};
611

    
612
static int
613
write_f(int argc, char **argv)
614
{
615
        struct timeval t1, t2;
616
        int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
617
        int c, cnt;
618
        char *buf;
619
        int64_t offset;
620
        int count;
621
        /* Some compilers get confused and warn if this is not initialized.  */
622
        int total = 0;
623
        int pattern = 0xcd;
624

    
625
        while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
626
                switch (c) {
627
                case 'b':
628
                        bflag = 1;
629
                        break;
630
                case 'C':
631
                        Cflag = 1;
632
                        break;
633
                case 'p':
634
                        pflag = 1;
635
                        break;
636
                case 'P':
637
                        pattern = parse_pattern(optarg);
638
                        if (pattern < 0)
639
                                return 0;
640
                        break;
641
                case 'q':
642
                        qflag = 1;
643
                        break;
644
                default:
645
                        return command_usage(&write_cmd);
646
                }
647
        }
648

    
649
        if (optind != argc - 2)
650
                return command_usage(&write_cmd);
651

    
652
        if (bflag && pflag) {
653
                printf("-b and -p cannot be specified at the same time\n");
654
                return 0;
655
        }
656

    
657
        offset = cvtnum(argv[optind]);
658
        if (offset < 0) {
659
                printf("non-numeric length argument -- %s\n", argv[optind]);
660
                return 0;
661
        }
662

    
663
        optind++;
664
        count = cvtnum(argv[optind]);
665
        if (count < 0) {
666
                printf("non-numeric length argument -- %s\n", argv[optind]);
667
                return 0;
668
        }
669

    
670
        if (!pflag) {
671
                if (offset & 0x1ff) {
672
                        printf("offset %lld is not sector aligned\n",
673
                                (long long)offset);
674
                        return 0;
675
                }
676

    
677
                if (count & 0x1ff) {
678
                        printf("count %d is not sector aligned\n",
679
                                count);
680
                        return 0;
681
                }
682
        }
683

    
684
        buf = qemu_io_alloc(count, pattern);
685

    
686
        gettimeofday(&t1, NULL);
687
        if (pflag)
688
                cnt = do_pwrite(buf, offset, count, &total);
689
        else if (bflag)
690
                cnt = do_save_vmstate(buf, offset, count, &total);
691
        else
692
                cnt = do_write(buf, offset, count, &total);
693
        gettimeofday(&t2, NULL);
694

    
695
        if (cnt < 0) {
696
                printf("write failed: %s\n", strerror(-cnt));
697
                goto out;
698
        }
699

    
700
        if (qflag)
701
                goto out;
702

    
703
        /* Finally, report back -- -C gives a parsable format */
704
        t2 = tsub(t2, t1);
705
        print_report("wrote", &t2, offset, count, total, cnt, Cflag);
706

    
707
out:
708
        qemu_io_free(buf);
709

    
710
        return 0;
711
}
712

    
713
static void
714
writev_help(void)
715
{
716
        printf(
717
"\n"
718
" writes a range of bytes from the given offset source from multiple buffers\n"
719
"\n"
720
" Example:\n"
721
" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
722
"\n"
723
" Writes into a segment of the currently open file, using a buffer\n"
724
" filled with a set pattern (0xcdcdcdcd).\n"
725
" -P, -- use different pattern to fill file\n"
726
" -C, -- report statistics in a machine parsable format\n"
727
" -q, -- quite mode, do not show I/O statistics\n"
728
"\n");
729
}
730

    
731
static int writev_f(int argc, char **argv);
732

    
733
static const cmdinfo_t writev_cmd = {
734
        .name                = "writev",
735
        .cfunc                = writev_f,
736
        .argmin                = 2,
737
        .argmax                = -1,
738
        .args                = "[-Cq] [-P pattern ] off len [len..]",
739
        .oneline        = "writes a number of bytes at a specified offset",
740
        .help                = writev_help,
741
};
742

    
743
static int
744
writev_f(int argc, char **argv)
745
{
746
        struct timeval t1, t2;
747
        int Cflag = 0, qflag = 0;
748
        int c, cnt;
749
        char *buf;
750
        int64_t offset;
751
        /* Some compilers get confused and warn if this is not initialized.  */
752
        int total = 0;
753
        int nr_iov;
754
        int pattern = 0xcd;
755
        QEMUIOVector qiov;
756

    
757
        while ((c = getopt(argc, argv, "CqP:")) != EOF) {
758
                switch (c) {
759
                case 'C':
760
                        Cflag = 1;
761
                        break;
762
                case 'q':
763
                        qflag = 1;
764
                        break;
765
                case 'P':
766
                        pattern = parse_pattern(optarg);
767
                        if (pattern < 0)
768
                                return 0;
769
                        break;
770
                default:
771
                        return command_usage(&writev_cmd);
772
                }
773
        }
774

    
775
        if (optind > argc - 2)
776
                return command_usage(&writev_cmd);
777

    
778
        offset = cvtnum(argv[optind]);
779
        if (offset < 0) {
780
                printf("non-numeric length argument -- %s\n", argv[optind]);
781
                return 0;
782
        }
783
        optind++;
784

    
785
        if (offset & 0x1ff) {
786
                printf("offset %lld is not sector aligned\n",
787
                        (long long)offset);
788
                return 0;
789
        }
790

    
791
        nr_iov = argc - optind;
792
        buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
793

    
794
        gettimeofday(&t1, NULL);
795
        cnt = do_aio_writev(&qiov, offset, &total);
796
        gettimeofday(&t2, NULL);
797

    
798
        if (cnt < 0) {
799
                printf("writev failed: %s\n", strerror(-cnt));
800
                goto out;
801
        }
802

    
803
        if (qflag)
804
                goto out;
805

    
806
        /* Finally, report back -- -C gives a parsable format */
807
        t2 = tsub(t2, t1);
808
        print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
809
out:
810
        qemu_io_free(buf);
811
        return 0;
812
}
813

    
814
struct aio_ctx {
815
        QEMUIOVector qiov;
816
        int64_t offset;
817
        char *buf;
818
        int qflag;
819
        int vflag;
820
        int Cflag;
821
        int Pflag;
822
        int pattern;
823
        struct timeval t1;
824
};
825

    
826
static void
827
aio_write_done(void *opaque, int ret)
828
{
829
        struct aio_ctx *ctx = opaque;
830
        struct timeval t2;
831

    
832
        gettimeofday(&t2, NULL);
833

    
834

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

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

    
844
        /* Finally, report back -- -C gives a parsable format */
845
        t2 = tsub(t2, ctx->t1);
846
        print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
847
                     ctx->qiov.size, 1, ctx->Cflag);
848
out:
849
        qemu_io_free(ctx->buf);
850
        free(ctx);
851
}
852

    
853
static void
854
aio_read_done(void *opaque, int ret)
855
{
856
        struct aio_ctx *ctx = opaque;
857
        struct timeval t2;
858

    
859
        gettimeofday(&t2, NULL);
860

    
861
        if (ret < 0) {
862
                printf("readv failed: %s\n", strerror(-ret));
863
                goto out;
864
        }
865

    
866
        if (ctx->Pflag) {
867
                void *cmp_buf = malloc(ctx->qiov.size);
868

    
869
                memset(cmp_buf, ctx->pattern, ctx->qiov.size);
870
                if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
871
                        printf("Pattern verification failed at offset %lld, "
872
                                "%zd bytes\n",
873
                                (long long) ctx->offset, ctx->qiov.size);
874
                }
875
                free(cmp_buf);
876
        }
877

    
878
        if (ctx->qflag) {
879
                goto out;
880
        }
881

    
882
        if (ctx->vflag) {
883
                dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
884
        }
885

    
886
        /* Finally, report back -- -C gives a parsable format */
887
        t2 = tsub(t2, ctx->t1);
888
        print_report("read", &t2, ctx->offset, ctx->qiov.size,
889
                     ctx->qiov.size, 1, ctx->Cflag);
890
out:
891
        qemu_io_free(ctx->buf);
892
        free(ctx);
893
}
894

    
895
static void
896
aio_read_help(void)
897
{
898
        printf(
899
"\n"
900
" asynchronously reads a range of bytes from the given offset\n"
901
"\n"
902
" Example:\n"
903
" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
904
"\n"
905
" Reads a segment of the currently open file, optionally dumping it to the\n"
906
" standard output stream (with -v option) for subsequent inspection.\n"
907
" The read is performed asynchronously and the aio_flush command must be\n"
908
" used to ensure all outstanding aio requests have been completed\n"
909
" -C, -- report statistics in a machine parsable format\n"
910
" -P, -- use a pattern to verify read data\n"
911
" -v, -- dump buffer to standard output\n"
912
" -q, -- quite mode, do not show I/O statistics\n"
913
"\n");
914
}
915

    
916
static int aio_read_f(int argc, char **argv);
917

    
918
static const cmdinfo_t aio_read_cmd = {
919
        .name                = "aio_read",
920
        .cfunc                = aio_read_f,
921
        .argmin                = 2,
922
        .argmax                = -1,
923
        .args                = "[-Cqv] [-P pattern ] off len [len..]",
924
        .oneline        = "asynchronously reads a number of bytes",
925
        .help                = aio_read_help,
926
};
927

    
928
static int
929
aio_read_f(int argc, char **argv)
930
{
931
        int nr_iov, c;
932
        struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
933
        BlockDriverAIOCB *acb;
934

    
935
        while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
936
                switch (c) {
937
                case 'C':
938
                        ctx->Cflag = 1;
939
                        break;
940
                case 'P':
941
                        ctx->Pflag = 1;
942
                        ctx->pattern = parse_pattern(optarg);
943
                        if (ctx->pattern < 0)
944
                                return 0;
945
                        break;
946
                case 'q':
947
                        ctx->qflag = 1;
948
                        break;
949
                case 'v':
950
                        ctx->vflag = 1;
951
                        break;
952
                default:
953
                        free(ctx);
954
                        return command_usage(&aio_read_cmd);
955
                }
956
        }
957

    
958
        if (optind > argc - 2) {
959
                free(ctx);
960
                return command_usage(&aio_read_cmd);
961
        }
962

    
963
        ctx->offset = cvtnum(argv[optind]);
964
        if (ctx->offset < 0) {
965
                printf("non-numeric length argument -- %s\n", argv[optind]);
966
                free(ctx);
967
                return 0;
968
        }
969
        optind++;
970

    
971
        if (ctx->offset & 0x1ff) {
972
                printf("offset %lld is not sector aligned\n",
973
                        (long long)ctx->offset);
974
                free(ctx);
975
                return 0;
976
        }
977

    
978
        nr_iov = argc - optind;
979
        ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
980

    
981
        gettimeofday(&ctx->t1, NULL);
982
        acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
983
                              ctx->qiov.size >> 9, aio_read_done, ctx);
984
        if (!acb) {
985
                free(ctx->buf);
986
                free(ctx);
987
                return -EIO;
988
        }
989

    
990
        return 0;
991
}
992

    
993
static void
994
aio_write_help(void)
995
{
996
        printf(
997
"\n"
998
" asynchronously writes a range of bytes from the given offset source \n"
999
" from multiple buffers\n"
1000
"\n"
1001
" Example:\n"
1002
" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1003
"\n"
1004
" Writes into a segment of the currently open file, using a buffer\n"
1005
" filled with a set pattern (0xcdcdcdcd).\n"
1006
" The write is performed asynchronously and the aio_flush command must be\n"
1007
" used to ensure all outstanding aio requests have been completed\n"
1008
" -P, -- use different pattern to fill file\n"
1009
" -C, -- report statistics in a machine parsable format\n"
1010
" -q, -- quite mode, do not show I/O statistics\n"
1011
"\n");
1012
}
1013

    
1014
static int aio_write_f(int argc, char **argv);
1015

    
1016
static const cmdinfo_t aio_write_cmd = {
1017
        .name                = "aio_write",
1018
        .cfunc                = aio_write_f,
1019
        .argmin                = 2,
1020
        .argmax                = -1,
1021
        .args                = "[-Cq] [-P pattern ] off len [len..]",
1022
        .oneline        = "asynchronously writes a number of bytes",
1023
        .help                = aio_write_help,
1024
};
1025

    
1026
static int
1027
aio_write_f(int argc, char **argv)
1028
{
1029
        int nr_iov, c;
1030
        int pattern = 0xcd;
1031
        struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
1032
        BlockDriverAIOCB *acb;
1033

    
1034
        while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1035
                switch (c) {
1036
                case 'C':
1037
                        ctx->Cflag = 1;
1038
                        break;
1039
                case 'q':
1040
                        ctx->qflag = 1;
1041
                        break;
1042
                case 'P':
1043
                        pattern = parse_pattern(optarg);
1044
                        if (pattern < 0)
1045
                                return 0;
1046
                        break;
1047
                default:
1048
                        free(ctx);
1049
                        return command_usage(&aio_write_cmd);
1050
                }
1051
        }
1052

    
1053
        if (optind > argc - 2) {
1054
                free(ctx);
1055
                return command_usage(&aio_write_cmd);
1056
        }
1057

    
1058
        ctx->offset = cvtnum(argv[optind]);
1059
        if (ctx->offset < 0) {
1060
                printf("non-numeric length argument -- %s\n", argv[optind]);
1061
                free(ctx);
1062
                return 0;
1063
        }
1064
        optind++;
1065

    
1066
        if (ctx->offset & 0x1ff) {
1067
                printf("offset %lld is not sector aligned\n",
1068
                        (long long)ctx->offset);
1069
                free(ctx);
1070
                return 0;
1071
        }
1072

    
1073
        nr_iov = argc - optind;
1074
        ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
1075

    
1076
        gettimeofday(&ctx->t1, NULL);
1077
        acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1078
                              ctx->qiov.size >> 9, aio_write_done, ctx);
1079
        if (!acb) {
1080
                free(ctx->buf);
1081
                free(ctx);
1082
                return -EIO;
1083
        }
1084

    
1085
        return 0;
1086
}
1087

    
1088
static int
1089
aio_flush_f(int argc, char **argv)
1090
{
1091
        qemu_aio_flush();
1092
        return 0;
1093
}
1094

    
1095
static const cmdinfo_t aio_flush_cmd = {
1096
        .name                = "aio_flush",
1097
        .cfunc                = aio_flush_f,
1098
        .oneline        = "completes all outstanding aio requests"
1099
};
1100

    
1101
static int
1102
flush_f(int argc, char **argv)
1103
{
1104
        bdrv_flush(bs);
1105
        return 0;
1106
}
1107

    
1108
static const cmdinfo_t flush_cmd = {
1109
        .name                = "flush",
1110
        .altname        = "f",
1111
        .cfunc                = flush_f,
1112
        .oneline        = "flush all in-core file state to disk",
1113
};
1114

    
1115
static int
1116
truncate_f(int argc, char **argv)
1117
{
1118
        int64_t offset;
1119
        int ret;
1120

    
1121
        offset = cvtnum(argv[1]);
1122
        if (offset < 0) {
1123
                printf("non-numeric truncate argument -- %s\n", argv[1]);
1124
                return 0;
1125
        }
1126

    
1127
        ret = bdrv_truncate(bs, offset);
1128
        if (ret < 0) {
1129
                printf("truncate: %s", strerror(ret));
1130
                return 0;
1131
        }
1132

    
1133
        return 0;
1134
}
1135

    
1136
static const cmdinfo_t truncate_cmd = {
1137
        .name                = "truncate",
1138
        .altname        = "t",
1139
        .cfunc                = truncate_f,
1140
        .argmin                = 1,
1141
        .argmax                = 1,
1142
        .args                = "off",
1143
        .oneline        = "truncates the current file at the given offset",
1144
};
1145

    
1146
static int
1147
length_f(int argc, char **argv)
1148
{
1149
        int64_t size;
1150
        char s1[64];
1151

    
1152
        size = bdrv_getlength(bs);
1153
        if (size < 0) {
1154
                printf("getlength: %s", strerror(size));
1155
                return 0;
1156
        }
1157

    
1158
        cvtstr(size, s1, sizeof(s1));
1159
        printf("%s\n", s1);
1160
        return 0;
1161
}
1162

    
1163

    
1164
static const cmdinfo_t length_cmd = {
1165
        .name                = "length",
1166
        .altname        = "l",
1167
        .cfunc                = length_f,
1168
        .oneline        = "gets the length of the current file",
1169
};
1170

    
1171

    
1172
static int
1173
info_f(int argc, char **argv)
1174
{
1175
        BlockDriverInfo bdi;
1176
        char s1[64], s2[64];
1177
        int ret;
1178

    
1179
        if (bs->drv && bs->drv->format_name)
1180
                printf("format name: %s\n", bs->drv->format_name);
1181
        if (bs->drv && bs->drv->protocol_name)
1182
                printf("format name: %s\n", bs->drv->protocol_name);
1183

    
1184
        ret = bdrv_get_info(bs, &bdi);
1185
        if (ret)
1186
                return 0;
1187

    
1188
        cvtstr(bdi.cluster_size, s1, sizeof(s1));
1189
        cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1190

    
1191
        printf("cluster size: %s\n", s1);
1192
        printf("vm state offset: %s\n", s2);
1193

    
1194
        return 0;
1195
}
1196

    
1197

    
1198

    
1199
static const cmdinfo_t info_cmd = {
1200
        .name                = "info",
1201
        .altname        = "i",
1202
        .cfunc                = info_f,
1203
        .oneline        = "prints information about the current file",
1204
};
1205

    
1206
static int
1207
alloc_f(int argc, char **argv)
1208
{
1209
        int64_t offset;
1210
        int nb_sectors, remaining;
1211
        char s1[64];
1212
        int num, sum_alloc;
1213
        int ret;
1214

    
1215
        offset = cvtnum(argv[1]);
1216
        if (offset & 0x1ff) {
1217
                printf("offset %lld is not sector aligned\n",
1218
                        (long long)offset);
1219
                return 0;
1220
        }
1221

    
1222
        if (argc == 3)
1223
                nb_sectors = cvtnum(argv[2]);
1224
        else
1225
                nb_sectors = 1;
1226

    
1227
        remaining = nb_sectors;
1228
        sum_alloc = 0;
1229
        while (remaining) {
1230
                ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
1231
                remaining -= num;
1232
                if (ret) {
1233
                        sum_alloc += num;
1234
                }
1235
        }
1236

    
1237
        cvtstr(offset, s1, sizeof(s1));
1238

    
1239
        if (nb_sectors == 1)
1240
                printf("sector allocated at offset %s\n", s1);
1241
        else
1242
                printf("%d/%d sectors allocated at offset %s\n",
1243
                        sum_alloc, nb_sectors, s1);
1244
        return 0;
1245
}
1246

    
1247
static const cmdinfo_t alloc_cmd = {
1248
        .name                = "alloc",
1249
        .altname        = "a",
1250
        .argmin                = 1,
1251
        .argmax                = 2,
1252
        .cfunc                = alloc_f,
1253
        .args                = "off [sectors]",
1254
        .oneline        = "checks if a sector is present in the file",
1255
};
1256

    
1257
static int
1258
close_f(int argc, char **argv)
1259
{
1260
        bdrv_close(bs);
1261
        bs = NULL;
1262
        return 0;
1263
}
1264

    
1265
static const cmdinfo_t close_cmd = {
1266
        .name                = "close",
1267
        .altname        = "c",
1268
        .cfunc                = close_f,
1269
        .oneline        = "close the current open file",
1270
};
1271

    
1272
static int openfile(char *name, int flags, int growable)
1273
{
1274
        if (bs) {
1275
                fprintf(stderr, "file open already, try 'help close'\n");
1276
                return 1;
1277
        }
1278

    
1279
        bs = bdrv_new("hda");
1280
        if (!bs)
1281
                return 1;
1282

    
1283
        if (growable) {
1284
                flags |= BDRV_O_FILE;
1285
        }
1286

    
1287
        if (bdrv_open(bs, name, flags) < 0) {
1288
                fprintf(stderr, "%s: can't open device %s\n", progname, name);
1289
                bs = NULL;
1290
                return 1;
1291
        }
1292

    
1293
        if (growable) {
1294
                bs->growable = 1;
1295
        }
1296
        return 0;
1297
}
1298

    
1299
static void
1300
open_help(void)
1301
{
1302
        printf(
1303
"\n"
1304
" opens a new file in the requested mode\n"
1305
"\n"
1306
" Example:\n"
1307
" 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
1308
"\n"
1309
" Opens a file for subsequent use by all of the other qemu-io commands.\n"
1310
" -r, -- open file read-only\n"
1311
" -s, -- use snapshot file\n"
1312
" -n, -- disable host cache\n"
1313
" -g, -- allow file to grow (only applies to protocols)"
1314
"\n");
1315
}
1316

    
1317
static int open_f(int argc, char **argv);
1318

    
1319
static const cmdinfo_t open_cmd = {
1320
        .name                = "open",
1321
        .altname        = "o",
1322
        .cfunc                = open_f,
1323
        .argmin                = 1,
1324
        .argmax                = -1,
1325
        .flags                = CMD_NOFILE_OK,
1326
        .args                = "[-Crsn] [path]",
1327
        .oneline        = "open the file specified by path",
1328
        .help                = open_help,
1329
};
1330

    
1331
static int
1332
open_f(int argc, char **argv)
1333
{
1334
        int flags = 0;
1335
        int readonly = 0;
1336
        int growable = 0;
1337
        int c;
1338

    
1339
        while ((c = getopt(argc, argv, "snrg")) != EOF) {
1340
                switch (c) {
1341
                case 's':
1342
                        flags |= BDRV_O_SNAPSHOT;
1343
                        break;
1344
                case 'n':
1345
                        flags |= BDRV_O_NOCACHE;
1346
                        break;
1347
                case 'r':
1348
                        readonly = 1;
1349
                        break;
1350
                case 'g':
1351
                        growable = 1;
1352
                        break;
1353
                default:
1354
                        return command_usage(&open_cmd);
1355
                }
1356
        }
1357

    
1358
        if (!readonly) {
1359
            flags |= BDRV_O_RDWR;
1360
        }
1361

    
1362
        if (optind != argc - 1)
1363
                return command_usage(&open_cmd);
1364

    
1365
        return openfile(argv[optind], flags, growable);
1366
}
1367

    
1368
static int
1369
init_args_command(
1370
        int     index)
1371
{
1372
        /* only one device allowed so far */
1373
        if (index >= 1)
1374
                return 0;
1375
        return ++index;
1376
}
1377

    
1378
static int
1379
init_check_command(
1380
        const cmdinfo_t *ct)
1381
{
1382
        if (ct->flags & CMD_FLAG_GLOBAL)
1383
                return 1;
1384
        if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1385
                fprintf(stderr, "no file open, try 'help open'\n");
1386
                return 0;
1387
        }
1388
        return 1;
1389
}
1390

    
1391
static void usage(const char *name)
1392
{
1393
        printf(
1394
"Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
1395
"QEMU Disk exerciser\n"
1396
"\n"
1397
"  -c, --cmd            command to execute\n"
1398
"  -r, --read-only      export read-only\n"
1399
"  -s, --snapshot       use snapshot file\n"
1400
"  -n, --nocache        disable host cache\n"
1401
"  -g, --growable       allow file to grow (only applies to protocols)\n"
1402
"  -m, --misalign       misalign allocations for O_DIRECT\n"
1403
"  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
1404
"  -h, --help           display this help and exit\n"
1405
"  -V, --version        output version information and exit\n"
1406
"\n",
1407
        name);
1408
}
1409

    
1410

    
1411
int main(int argc, char **argv)
1412
{
1413
        int readonly = 0;
1414
        int growable = 0;
1415
        const char *sopt = "hVc:rsnmgk";
1416
        const struct option lopt[] = {
1417
                { "help", 0, NULL, 'h' },
1418
                { "version", 0, NULL, 'V' },
1419
                { "offset", 1, NULL, 'o' },
1420
                { "cmd", 1, NULL, 'c' },
1421
                { "read-only", 0, NULL, 'r' },
1422
                { "snapshot", 0, NULL, 's' },
1423
                { "nocache", 0, NULL, 'n' },
1424
                { "misalign", 0, NULL, 'm' },
1425
                { "growable", 0, NULL, 'g' },
1426
                { "native-aio", 0, NULL, 'k' },
1427
                { NULL, 0, NULL, 0 }
1428
        };
1429
        int c;
1430
        int opt_index = 0;
1431
        int flags = 0;
1432

    
1433
        progname = basename(argv[0]);
1434

    
1435
        while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
1436
                switch (c) {
1437
                case 's':
1438
                        flags |= BDRV_O_SNAPSHOT;
1439
                        break;
1440
                case 'n':
1441
                        flags |= BDRV_O_NOCACHE;
1442
                        break;
1443
                case 'c':
1444
                        add_user_command(optarg);
1445
                        break;
1446
                case 'r':
1447
                        readonly = 1;
1448
                        break;
1449
                case 'm':
1450
                        misalign = 1;
1451
                        break;
1452
                case 'g':
1453
                        growable = 1;
1454
                        break;
1455
                case 'k':
1456
                        flags |= BDRV_O_NATIVE_AIO;
1457
                        break;
1458
                case 'V':
1459
                        printf("%s version %s\n", progname, VERSION);
1460
                        exit(0);
1461
                case 'h':
1462
                        usage(progname);
1463
                        exit(0);
1464
                default:
1465
                        usage(progname);
1466
                        exit(1);
1467
                }
1468
        }
1469

    
1470
        if ((argc - optind) > 1) {
1471
                usage(progname);
1472
                exit(1);
1473
        }
1474

    
1475
        bdrv_init();
1476

    
1477
        /* initialize commands */
1478
        quit_init();
1479
        help_init();
1480
        add_command(&open_cmd);
1481
        add_command(&close_cmd);
1482
        add_command(&read_cmd);
1483
        add_command(&readv_cmd);
1484
        add_command(&write_cmd);
1485
        add_command(&writev_cmd);
1486
        add_command(&aio_read_cmd);
1487
        add_command(&aio_write_cmd);
1488
        add_command(&aio_flush_cmd);
1489
        add_command(&flush_cmd);
1490
        add_command(&truncate_cmd);
1491
        add_command(&length_cmd);
1492
        add_command(&info_cmd);
1493
        add_command(&alloc_cmd);
1494

    
1495
        add_args_command(init_args_command);
1496
        add_check_command(init_check_command);
1497

    
1498
        /* open the device */
1499
        if (!readonly) {
1500
            flags |= BDRV_O_RDWR;
1501
        }
1502

    
1503
        if ((argc - optind) == 1)
1504
                openfile(argv[optind], flags, growable);
1505
        command_loop();
1506

    
1507
        /*
1508
         * Make sure all outstanding requests get flushed the program exits.
1509
         */
1510
        qemu_aio_flush();
1511

    
1512
        if (bs)
1513
                bdrv_close(bs);
1514
        return 0;
1515
}