Statistics
| Branch: | Revision:

root / qemu-io.c @ 43642b38

History | View | Annotate | Download (43.4 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
    }
65
    buf = qemu_blockalign(bs, len);
66
    memset(buf, pattern, len);
67
    if (misalign) {
68
        buf += MISALIGN_OFFSET;
69
    }
70
    return buf;
71
}
72

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

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

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

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

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

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

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

    
139
    for (i = 0; i < nr_iov; i++) {
140
        char *arg = argv[i];
141
        int64_t len;
142

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

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

    
155
        if (len & 0x1ff) {
156
            printf("length argument %" PRId64
157
                   " is not sector aligned\n", len);
158
            goto fail;
159
        }
160

    
161
        sizes[i] = len;
162
        count += len;
163
    }
164

    
165
    qemu_iovec_init(qiov, nr_iov);
166

    
167
    buf = p = qemu_io_alloc(count, pattern);
168

    
169
    for (i = 0; i < nr_iov; i++) {
170
        qemu_iovec_add(qiov, p, sizes[i]);
171
        p += sizes[i];
172
    }
173

    
174
fail:
175
    free(sizes);
176
    return buf;
177
}
178

    
179
static int do_read(char *buf, int64_t offset, int count, int *total)
180
{
181
    int ret;
182

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

    
191
static int do_write(char *buf, int64_t offset, int count, int *total)
192
{
193
    int ret;
194

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

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

    
212
static int do_pwrite(char *buf, int64_t offset, int count, 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
static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
222
{
223
    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
224
    if (*total < 0) {
225
        return *total;
226
    }
227
    return 1;
228
}
229

    
230
static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
231
{
232
    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
233
    if (*total < 0) {
234
        return *total;
235
    }
236
    return 1;
237
}
238

    
239
#define NOT_DONE 0x7fffffff
240
static void aio_rw_done(void *opaque, int ret)
241
{
242
    *(int *)opaque = ret;
243
}
244

    
245
static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
246
{
247
    BlockDriverAIOCB *acb;
248
    int async_ret = NOT_DONE;
249

    
250
    acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
251
                         aio_rw_done, &async_ret);
252
    if (!acb) {
253
        return -EIO;
254
    }
255
    while (async_ret == NOT_DONE) {
256
        qemu_aio_wait();
257
    }
258

    
259
    *total = qiov->size;
260
    return async_ret < 0 ? async_ret : 1;
261
}
262

    
263
static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
264
{
265
    BlockDriverAIOCB *acb;
266
    int async_ret = NOT_DONE;
267

    
268
    acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
269
                          aio_rw_done, &async_ret);
270
    if (!acb) {
271
        return -EIO;
272
    }
273

    
274
    while (async_ret == NOT_DONE) {
275
        qemu_aio_wait();
276
    }
277

    
278
    *total = qiov->size;
279
    return async_ret < 0 ? async_ret : 1;
280
}
281

    
282
struct multiwrite_async_ret {
283
    int num_done;
284
    int error;
285
};
286

    
287
static void multiwrite_cb(void *opaque, int ret)
288
{
289
    struct multiwrite_async_ret *async_ret = opaque;
290

    
291
    async_ret->num_done++;
292
    if (ret < 0) {
293
        async_ret->error = ret;
294
    }
295
}
296

    
297
static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
298
{
299
    int i, ret;
300
    struct multiwrite_async_ret async_ret = {
301
        .num_done = 0,
302
        .error = 0,
303
    };
304

    
305
    *total = 0;
306
    for (i = 0; i < num_reqs; i++) {
307
        reqs[i].cb = multiwrite_cb;
308
        reqs[i].opaque = &async_ret;
309
        *total += reqs[i].qiov->size;
310
    }
311

    
312
    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
313
    if (ret < 0) {
314
        return ret;
315
    }
316

    
317
    while (async_ret.num_done < num_reqs) {
318
        qemu_aio_wait();
319
    }
320

    
321
    return async_ret.error < 0 ? async_ret.error : 1;
322
}
323

    
324
static void read_help(void)
325
{
326
    printf(
327
"\n"
328
" reads a range of bytes from the given offset\n"
329
"\n"
330
" Example:\n"
331
" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
332
"\n"
333
" Reads a segment of the currently open file, optionally dumping it to the\n"
334
" standard output stream (with -v option) for subsequent inspection.\n"
335
" -b, -- read from the VM state rather than the virtual disk\n"
336
" -C, -- report statistics in a machine parsable format\n"
337
" -l, -- length for pattern verification (only with -P)\n"
338
" -p, -- use bdrv_pread to read the file\n"
339
" -P, -- use a pattern to verify read data\n"
340
" -q, -- quiet mode, do not show I/O statistics\n"
341
" -s, -- start offset for pattern verification (only with -P)\n"
342
" -v, -- dump buffer to standard output\n"
343
"\n");
344
}
345

    
346
static int read_f(int argc, char **argv);
347

    
348
static const cmdinfo_t read_cmd = {
349
    .name       = "read",
350
    .altname    = "r",
351
    .cfunc      = read_f,
352
    .argmin     = 2,
353
    .argmax     = -1,
354
    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
355
    .oneline    = "reads a number of bytes at a specified offset",
356
    .help       = read_help,
357
};
358

    
359
static int read_f(int argc, char **argv)
360
{
361
    struct timeval t1, t2;
362
    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
363
    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
364
    int c, cnt;
365
    char *buf;
366
    int64_t offset;
367
    int count;
368
    /* Some compilers get confused and warn if this is not initialized.  */
369
    int total = 0;
370
    int pattern = 0, pattern_offset = 0, pattern_count = 0;
371

    
372
    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
373
        switch (c) {
374
        case 'b':
375
            bflag = 1;
376
            break;
377
        case 'C':
378
            Cflag = 1;
379
            break;
380
        case 'l':
381
            lflag = 1;
382
            pattern_count = cvtnum(optarg);
383
            if (pattern_count < 0) {
384
                printf("non-numeric length argument -- %s\n", optarg);
385
                return 0;
386
            }
387
            break;
388
        case 'p':
389
            pflag = 1;
390
            break;
391
        case 'P':
392
            Pflag = 1;
393
            pattern = parse_pattern(optarg);
394
            if (pattern < 0) {
395
                return 0;
396
            }
397
            break;
398
        case 'q':
399
            qflag = 1;
400
            break;
401
        case 's':
402
            sflag = 1;
403
            pattern_offset = cvtnum(optarg);
404
            if (pattern_offset < 0) {
405
                printf("non-numeric length argument -- %s\n", optarg);
406
                return 0;
407
            }
408
            break;
409
        case 'v':
410
            vflag = 1;
411
            break;
412
        default:
413
            return command_usage(&read_cmd);
414
        }
415
    }
416

    
417
    if (optind != argc - 2) {
418
        return command_usage(&read_cmd);
419
    }
420

    
421
    if (bflag && pflag) {
422
        printf("-b and -p cannot be specified at the same time\n");
423
        return 0;
424
    }
425

    
426
    offset = cvtnum(argv[optind]);
427
    if (offset < 0) {
428
        printf("non-numeric length argument -- %s\n", argv[optind]);
429
        return 0;
430
    }
431

    
432
    optind++;
433
    count = cvtnum(argv[optind]);
434
    if (count < 0) {
435
        printf("non-numeric length argument -- %s\n", argv[optind]);
436
        return 0;
437
    }
438

    
439
    if (!Pflag && (lflag || sflag)) {
440
        return command_usage(&read_cmd);
441
    }
442

    
443
    if (!lflag) {
444
        pattern_count = count - pattern_offset;
445
    }
446

    
447
    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
448
        printf("pattern verfication range exceeds end of read data\n");
449
        return 0;
450
    }
451

    
452
    if (!pflag)
453
        if (offset & 0x1ff) {
454
            printf("offset %" PRId64 " is not sector aligned\n",
455
                   offset);
456
            return 0;
457
        }
458
        if (count & 0x1ff) {
459
            printf("count %d is not sector aligned\n",
460
                   count);
461
            return 0;
462
        }
463

    
464
    buf = qemu_io_alloc(count, 0xab);
465

    
466
    gettimeofday(&t1, NULL);
467
    if (pflag) {
468
        cnt = do_pread(buf, offset, count, &total);
469
    } else if (bflag) {
470
        cnt = do_load_vmstate(buf, offset, count, &total);
471
    } else {
472
        cnt = do_read(buf, offset, count, &total);
473
    }
474
    gettimeofday(&t2, NULL);
475

    
476
    if (cnt < 0) {
477
        printf("read failed: %s\n", strerror(-cnt));
478
        goto out;
479
    }
480

    
481
    if (Pflag) {
482
        void *cmp_buf = malloc(pattern_count);
483
        memset(cmp_buf, pattern, pattern_count);
484
        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
485
            printf("Pattern verification failed at offset %"
486
                   PRId64 ", %d bytes\n",
487
                   offset + pattern_offset, pattern_count);
488
        }
489
        free(cmp_buf);
490
    }
491

    
492
    if (qflag) {
493
        goto out;
494
    }
495

    
496
    if (vflag) {
497
        dump_buffer(buf, offset, count);
498
    }
499

    
500
    /* Finally, report back -- -C gives a parsable format */
501
    t2 = tsub(t2, t1);
502
    print_report("read", &t2, offset, count, total, cnt, Cflag);
503

    
504
out:
505
    qemu_io_free(buf);
506

    
507
    return 0;
508
}
509

    
510
static void readv_help(void)
511
{
512
    printf(
513
"\n"
514
" reads a range of bytes from the given offset into multiple buffers\n"
515
"\n"
516
" Example:\n"
517
" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
518
"\n"
519
" Reads a segment of the currently open file, optionally dumping it to the\n"
520
" standard output stream (with -v option) for subsequent inspection.\n"
521
" Uses multiple iovec buffers if more than one byte range is specified.\n"
522
" -C, -- report statistics in a machine parsable format\n"
523
" -P, -- use a pattern to verify read data\n"
524
" -v, -- dump buffer to standard output\n"
525
" -q, -- quiet mode, do not show I/O statistics\n"
526
"\n");
527
}
528

    
529
static int readv_f(int argc, char **argv);
530

    
531
static const cmdinfo_t readv_cmd = {
532
    .name       = "readv",
533
    .cfunc      = readv_f,
534
    .argmin     = 2,
535
    .argmax     = -1,
536
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
537
    .oneline    = "reads a number of bytes at a specified offset",
538
    .help       = readv_help,
539
};
540

    
541
static int readv_f(int argc, char **argv)
542
{
543
    struct timeval t1, t2;
544
    int Cflag = 0, qflag = 0, vflag = 0;
545
    int c, cnt;
546
    char *buf;
547
    int64_t offset;
548
    /* Some compilers get confused and warn if this is not initialized.  */
549
    int total = 0;
550
    int nr_iov;
551
    QEMUIOVector qiov;
552
    int pattern = 0;
553
    int Pflag = 0;
554

    
555
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
556
        switch (c) {
557
        case 'C':
558
            Cflag = 1;
559
            break;
560
        case 'P':
561
            Pflag = 1;
562
            pattern = parse_pattern(optarg);
563
            if (pattern < 0) {
564
                return 0;
565
            }
566
            break;
567
        case 'q':
568
            qflag = 1;
569
            break;
570
        case 'v':
571
            vflag = 1;
572
            break;
573
        default:
574
            return command_usage(&readv_cmd);
575
        }
576
    }
577

    
578
    if (optind > argc - 2) {
579
        return command_usage(&readv_cmd);
580
    }
581

    
582

    
583
    offset = cvtnum(argv[optind]);
584
    if (offset < 0) {
585
        printf("non-numeric length argument -- %s\n", argv[optind]);
586
        return 0;
587
    }
588
    optind++;
589

    
590
    if (offset & 0x1ff) {
591
        printf("offset %" PRId64 " is not sector aligned\n",
592
               offset);
593
        return 0;
594
    }
595

    
596
    nr_iov = argc - optind;
597
    buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
598

    
599
    gettimeofday(&t1, NULL);
600
    cnt = do_aio_readv(&qiov, offset, &total);
601
    gettimeofday(&t2, NULL);
602

    
603
    if (cnt < 0) {
604
        printf("readv failed: %s\n", strerror(-cnt));
605
        goto out;
606
    }
607

    
608
    if (Pflag) {
609
        void *cmp_buf = malloc(qiov.size);
610
        memset(cmp_buf, pattern, qiov.size);
611
        if (memcmp(buf, cmp_buf, qiov.size)) {
612
            printf("Pattern verification failed at offset %"
613
                   PRId64 ", %zd bytes\n", offset, qiov.size);
614
        }
615
        free(cmp_buf);
616
    }
617

    
618
    if (qflag) {
619
        goto out;
620
    }
621

    
622
    if (vflag) {
623
        dump_buffer(buf, offset, qiov.size);
624
    }
625

    
626
    /* Finally, report back -- -C gives a parsable format */
627
    t2 = tsub(t2, t1);
628
    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
629

    
630
out:
631
    qemu_io_free(buf);
632
    return 0;
633
}
634

    
635
static void write_help(void)
636
{
637
    printf(
638
"\n"
639
" writes a range of bytes from the given offset\n"
640
"\n"
641
" Example:\n"
642
" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
643
"\n"
644
" Writes into a segment of the currently open file, using a buffer\n"
645
" filled with a set pattern (0xcdcdcdcd).\n"
646
" -b, -- write to the VM state rather than the virtual disk\n"
647
" -p, -- use bdrv_pwrite to write the file\n"
648
" -P, -- use different pattern to fill file\n"
649
" -C, -- report statistics in a machine parsable format\n"
650
" -q, -- quiet mode, do not show I/O statistics\n"
651
"\n");
652
}
653

    
654
static int write_f(int argc, char **argv);
655

    
656
static const cmdinfo_t write_cmd = {
657
    .name       = "write",
658
    .altname    = "w",
659
    .cfunc      = write_f,
660
    .argmin     = 2,
661
    .argmax     = -1,
662
    .args       = "[-abCpq] [-P pattern ] off len",
663
    .oneline    = "writes a number of bytes at a specified offset",
664
    .help       = write_help,
665
};
666

    
667
static int write_f(int argc, char **argv)
668
{
669
    struct timeval t1, t2;
670
    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
671
    int c, cnt;
672
    char *buf;
673
    int64_t offset;
674
    int count;
675
    /* Some compilers get confused and warn if this is not initialized.  */
676
    int total = 0;
677
    int pattern = 0xcd;
678

    
679
    while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
680
        switch (c) {
681
        case 'b':
682
            bflag = 1;
683
            break;
684
        case 'C':
685
            Cflag = 1;
686
            break;
687
        case 'p':
688
            pflag = 1;
689
            break;
690
        case 'P':
691
            pattern = parse_pattern(optarg);
692
            if (pattern < 0) {
693
                return 0;
694
            }
695
            break;
696
        case 'q':
697
            qflag = 1;
698
            break;
699
        default:
700
            return command_usage(&write_cmd);
701
        }
702
    }
703

    
704
    if (optind != argc - 2) {
705
        return command_usage(&write_cmd);
706
    }
707

    
708
    if (bflag && pflag) {
709
        printf("-b and -p cannot be specified at the same time\n");
710
        return 0;
711
    }
712

    
713
    offset = cvtnum(argv[optind]);
714
    if (offset < 0) {
715
        printf("non-numeric length argument -- %s\n", argv[optind]);
716
        return 0;
717
    }
718

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

    
726
    if (!pflag) {
727
        if (offset & 0x1ff) {
728
            printf("offset %" PRId64 " is not sector aligned\n",
729
                   offset);
730
            return 0;
731
        }
732

    
733
        if (count & 0x1ff) {
734
            printf("count %d is not sector aligned\n",
735
                   count);
736
            return 0;
737
        }
738
    }
739

    
740
    buf = qemu_io_alloc(count, pattern);
741

    
742
    gettimeofday(&t1, NULL);
743
    if (pflag) {
744
        cnt = do_pwrite(buf, offset, count, &total);
745
    } else if (bflag) {
746
        cnt = do_save_vmstate(buf, offset, count, &total);
747
    } else {
748
        cnt = do_write(buf, offset, count, &total);
749
    }
750
    gettimeofday(&t2, NULL);
751

    
752
    if (cnt < 0) {
753
        printf("write failed: %s\n", strerror(-cnt));
754
        goto out;
755
    }
756

    
757
    if (qflag) {
758
        goto out;
759
    }
760

    
761
    /* Finally, report back -- -C gives a parsable format */
762
    t2 = tsub(t2, t1);
763
    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
764

    
765
out:
766
    qemu_io_free(buf);
767

    
768
    return 0;
769
}
770

    
771
static void
772
writev_help(void)
773
{
774
    printf(
775
"\n"
776
" writes a range of bytes from the given offset source from multiple buffers\n"
777
"\n"
778
" Example:\n"
779
" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
780
"\n"
781
" Writes into a segment of the currently open file, using a buffer\n"
782
" filled with a set pattern (0xcdcdcdcd).\n"
783
" -P, -- use different pattern to fill file\n"
784
" -C, -- report statistics in a machine parsable format\n"
785
" -q, -- quiet mode, do not show I/O statistics\n"
786
"\n");
787
}
788

    
789
static int writev_f(int argc, char **argv);
790

    
791
static const cmdinfo_t writev_cmd = {
792
    .name       = "writev",
793
    .cfunc      = writev_f,
794
    .argmin     = 2,
795
    .argmax     = -1,
796
    .args       = "[-Cq] [-P pattern ] off len [len..]",
797
    .oneline    = "writes a number of bytes at a specified offset",
798
    .help       = writev_help,
799
};
800

    
801
static int writev_f(int argc, char **argv)
802
{
803
    struct timeval t1, t2;
804
    int Cflag = 0, qflag = 0;
805
    int c, cnt;
806
    char *buf;
807
    int64_t offset;
808
    /* Some compilers get confused and warn if this is not initialized.  */
809
    int total = 0;
810
    int nr_iov;
811
    int pattern = 0xcd;
812
    QEMUIOVector qiov;
813

    
814
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
815
        switch (c) {
816
        case 'C':
817
            Cflag = 1;
818
            break;
819
        case 'q':
820
            qflag = 1;
821
            break;
822
        case 'P':
823
            pattern = parse_pattern(optarg);
824
            if (pattern < 0) {
825
                return 0;
826
            }
827
            break;
828
        default:
829
            return command_usage(&writev_cmd);
830
        }
831
    }
832

    
833
    if (optind > argc - 2) {
834
        return command_usage(&writev_cmd);
835
    }
836

    
837
    offset = cvtnum(argv[optind]);
838
    if (offset < 0) {
839
        printf("non-numeric length argument -- %s\n", argv[optind]);
840
        return 0;
841
    }
842
    optind++;
843

    
844
    if (offset & 0x1ff) {
845
        printf("offset %" PRId64 " is not sector aligned\n",
846
               offset);
847
        return 0;
848
    }
849

    
850
    nr_iov = argc - optind;
851
    buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
852

    
853
    gettimeofday(&t1, NULL);
854
    cnt = do_aio_writev(&qiov, offset, &total);
855
    gettimeofday(&t2, NULL);
856

    
857
    if (cnt < 0) {
858
        printf("writev failed: %s\n", strerror(-cnt));
859
        goto out;
860
    }
861

    
862
    if (qflag) {
863
        goto out;
864
    }
865

    
866
    /* Finally, report back -- -C gives a parsable format */
867
    t2 = tsub(t2, t1);
868
    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
869
out:
870
    qemu_io_free(buf);
871
    return 0;
872
}
873

    
874
static void multiwrite_help(void)
875
{
876
    printf(
877
"\n"
878
" writes a range of bytes from the given offset source from multiple buffers,\n"
879
" in a batch of requests that may be merged by qemu\n"
880
"\n"
881
" Example:\n"
882
" 'multiwrite 512 1k 1k ; 4k 1k' \n"
883
"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
884
"\n"
885
" Writes into a segment of the currently open file, using a buffer\n"
886
" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
887
" by one for each request contained in the multiwrite command.\n"
888
" -P, -- use different pattern to fill file\n"
889
" -C, -- report statistics in a machine parsable format\n"
890
" -q, -- quiet mode, do not show I/O statistics\n"
891
"\n");
892
}
893

    
894
static int multiwrite_f(int argc, char **argv);
895

    
896
static const cmdinfo_t multiwrite_cmd = {
897
    .name       = "multiwrite",
898
    .cfunc      = multiwrite_f,
899
    .argmin     = 2,
900
    .argmax     = -1,
901
    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
902
    .oneline    = "issues multiple write requests at once",
903
    .help       = multiwrite_help,
904
};
905

    
906
static int multiwrite_f(int argc, char **argv)
907
{
908
    struct timeval t1, t2;
909
    int Cflag = 0, qflag = 0;
910
    int c, cnt;
911
    char **buf;
912
    int64_t offset, first_offset = 0;
913
    /* Some compilers get confused and warn if this is not initialized.  */
914
    int total = 0;
915
    int nr_iov;
916
    int nr_reqs;
917
    int pattern = 0xcd;
918
    QEMUIOVector *qiovs;
919
    int i;
920
    BlockRequest *reqs;
921

    
922
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
923
        switch (c) {
924
        case 'C':
925
            Cflag = 1;
926
            break;
927
        case 'q':
928
            qflag = 1;
929
            break;
930
        case 'P':
931
            pattern = parse_pattern(optarg);
932
            if (pattern < 0) {
933
                return 0;
934
            }
935
            break;
936
        default:
937
            return command_usage(&writev_cmd);
938
        }
939
    }
940

    
941
    if (optind > argc - 2) {
942
        return command_usage(&writev_cmd);
943
    }
944

    
945
    nr_reqs = 1;
946
    for (i = optind; i < argc; i++) {
947
        if (!strcmp(argv[i], ";")) {
948
            nr_reqs++;
949
        }
950
    }
951

    
952
    reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
953
    buf = qemu_malloc(nr_reqs * sizeof(*buf));
954
    qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));
955

    
956
    for (i = 0; i < nr_reqs; i++) {
957
        int j;
958

    
959
        /* Read the offset of the request */
960
        offset = cvtnum(argv[optind]);
961
        if (offset < 0) {
962
            printf("non-numeric offset argument -- %s\n", argv[optind]);
963
            return 0;
964
        }
965
        optind++;
966

    
967
        if (offset & 0x1ff) {
968
            printf("offset %lld is not sector aligned\n",
969
                   (long long)offset);
970
            return 0;
971
        }
972

    
973
        if (i == 0) {
974
            first_offset = offset;
975
        }
976

    
977
        /* Read lengths for qiov entries */
978
        for (j = optind; j < argc; j++) {
979
            if (!strcmp(argv[j], ";")) {
980
                break;
981
            }
982
        }
983

    
984
        nr_iov = j - optind;
985

    
986
        /* Build request */
987
        reqs[i].qiov = &qiovs[i];
988
        buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern);
989
        reqs[i].sector = offset >> 9;
990
        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
991

    
992
        optind = j + 1;
993

    
994
        offset += reqs[i].qiov->size;
995
        pattern++;
996
    }
997

    
998
    gettimeofday(&t1, NULL);
999
    cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
1000
    gettimeofday(&t2, NULL);
1001

    
1002
    if (cnt < 0) {
1003
        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1004
        goto out;
1005
    }
1006

    
1007
    if (qflag) {
1008
        goto out;
1009
    }
1010

    
1011
    /* Finally, report back -- -C gives a parsable format */
1012
    t2 = tsub(t2, t1);
1013
    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1014
out:
1015
    for (i = 0; i < nr_reqs; i++) {
1016
        qemu_io_free(buf[i]);
1017
        qemu_iovec_destroy(&qiovs[i]);
1018
    }
1019
    qemu_free(buf);
1020
    qemu_free(reqs);
1021
    qemu_free(qiovs);
1022
    return 0;
1023
}
1024

    
1025
struct aio_ctx {
1026
    QEMUIOVector qiov;
1027
    int64_t offset;
1028
    char *buf;
1029
    int qflag;
1030
    int vflag;
1031
    int Cflag;
1032
    int Pflag;
1033
    int pattern;
1034
    struct timeval t1;
1035
};
1036

    
1037
static void aio_write_done(void *opaque, int ret)
1038
{
1039
    struct aio_ctx *ctx = opaque;
1040
    struct timeval t2;
1041

    
1042
    gettimeofday(&t2, NULL);
1043

    
1044

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

    
1050
    if (ctx->qflag) {
1051
        goto out;
1052
    }
1053

    
1054
    /* Finally, report back -- -C gives a parsable format */
1055
    t2 = tsub(t2, ctx->t1);
1056
    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1057
                 ctx->qiov.size, 1, ctx->Cflag);
1058
out:
1059
    qemu_io_free(ctx->buf);
1060
    free(ctx);
1061
}
1062

    
1063
static void aio_read_done(void *opaque, int ret)
1064
{
1065
    struct aio_ctx *ctx = opaque;
1066
    struct timeval t2;
1067

    
1068
    gettimeofday(&t2, NULL);
1069

    
1070
    if (ret < 0) {
1071
        printf("readv failed: %s\n", strerror(-ret));
1072
        goto out;
1073
    }
1074

    
1075
    if (ctx->Pflag) {
1076
        void *cmp_buf = malloc(ctx->qiov.size);
1077

    
1078
        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1079
        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1080
            printf("Pattern verification failed at offset %"
1081
                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1082
        }
1083
        free(cmp_buf);
1084
    }
1085

    
1086
    if (ctx->qflag) {
1087
        goto out;
1088
    }
1089

    
1090
    if (ctx->vflag) {
1091
        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1092
    }
1093

    
1094
    /* Finally, report back -- -C gives a parsable format */
1095
    t2 = tsub(t2, ctx->t1);
1096
    print_report("read", &t2, ctx->offset, ctx->qiov.size,
1097
                 ctx->qiov.size, 1, ctx->Cflag);
1098
out:
1099
    qemu_io_free(ctx->buf);
1100
    free(ctx);
1101
}
1102

    
1103
static void aio_read_help(void)
1104
{
1105
    printf(
1106
"\n"
1107
" asynchronously reads a range of bytes from the given offset\n"
1108
"\n"
1109
" Example:\n"
1110
" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1111
"\n"
1112
" Reads a segment of the currently open file, optionally dumping it to the\n"
1113
" standard output stream (with -v option) for subsequent inspection.\n"
1114
" The read is performed asynchronously and the aio_flush command must be\n"
1115
" used to ensure all outstanding aio requests have been completed\n"
1116
" -C, -- report statistics in a machine parsable format\n"
1117
" -P, -- use a pattern to verify read data\n"
1118
" -v, -- dump buffer to standard output\n"
1119
" -q, -- quiet mode, do not show I/O statistics\n"
1120
"\n");
1121
}
1122

    
1123
static int aio_read_f(int argc, char **argv);
1124

    
1125
static const cmdinfo_t aio_read_cmd = {
1126
    .name       = "aio_read",
1127
    .cfunc      = aio_read_f,
1128
    .argmin     = 2,
1129
    .argmax     = -1,
1130
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
1131
    .oneline    = "asynchronously reads a number of bytes",
1132
    .help       = aio_read_help,
1133
};
1134

    
1135
static int aio_read_f(int argc, char **argv)
1136
{
1137
    int nr_iov, c;
1138
    struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
1139
    BlockDriverAIOCB *acb;
1140

    
1141
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1142
        switch (c) {
1143
        case 'C':
1144
            ctx->Cflag = 1;
1145
            break;
1146
        case 'P':
1147
            ctx->Pflag = 1;
1148
            ctx->pattern = parse_pattern(optarg);
1149
            if (ctx->pattern < 0) {
1150
                free(ctx);
1151
                return 0;
1152
            }
1153
            break;
1154
        case 'q':
1155
            ctx->qflag = 1;
1156
            break;
1157
        case 'v':
1158
            ctx->vflag = 1;
1159
            break;
1160
        default:
1161
            free(ctx);
1162
            return command_usage(&aio_read_cmd);
1163
        }
1164
    }
1165

    
1166
    if (optind > argc - 2) {
1167
        free(ctx);
1168
        return command_usage(&aio_read_cmd);
1169
    }
1170

    
1171
    ctx->offset = cvtnum(argv[optind]);
1172
    if (ctx->offset < 0) {
1173
        printf("non-numeric length argument -- %s\n", argv[optind]);
1174
        free(ctx);
1175
        return 0;
1176
    }
1177
    optind++;
1178

    
1179
    if (ctx->offset & 0x1ff) {
1180
        printf("offset %" PRId64 " is not sector aligned\n",
1181
               ctx->offset);
1182
        free(ctx);
1183
        return 0;
1184
    }
1185

    
1186
    nr_iov = argc - optind;
1187
    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
1188

    
1189
    gettimeofday(&ctx->t1, NULL);
1190
    acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1191
                         ctx->qiov.size >> 9, aio_read_done, ctx);
1192
    if (!acb) {
1193
        free(ctx->buf);
1194
        free(ctx);
1195
        return -EIO;
1196
    }
1197

    
1198
    return 0;
1199
}
1200

    
1201
static void aio_write_help(void)
1202
{
1203
    printf(
1204
"\n"
1205
" asynchronously writes a range of bytes from the given offset source\n"
1206
" from multiple buffers\n"
1207
"\n"
1208
" Example:\n"
1209
" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1210
"\n"
1211
" Writes into a segment of the currently open file, using a buffer\n"
1212
" filled with a set pattern (0xcdcdcdcd).\n"
1213
" The write is performed asynchronously and the aio_flush command must be\n"
1214
" used to ensure all outstanding aio requests have been completed\n"
1215
" -P, -- use different pattern to fill file\n"
1216
" -C, -- report statistics in a machine parsable format\n"
1217
" -q, -- quiet mode, do not show I/O statistics\n"
1218
"\n");
1219
}
1220

    
1221
static int aio_write_f(int argc, char **argv);
1222

    
1223
static const cmdinfo_t aio_write_cmd = {
1224
    .name       = "aio_write",
1225
    .cfunc      = aio_write_f,
1226
    .argmin     = 2,
1227
    .argmax     = -1,
1228
    .args       = "[-Cq] [-P pattern ] off len [len..]",
1229
    .oneline    = "asynchronously writes a number of bytes",
1230
    .help       = aio_write_help,
1231
};
1232

    
1233
static int aio_write_f(int argc, char **argv)
1234
{
1235
    int nr_iov, c;
1236
    int pattern = 0xcd;
1237
    struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
1238
    BlockDriverAIOCB *acb;
1239

    
1240
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1241
        switch (c) {
1242
        case 'C':
1243
            ctx->Cflag = 1;
1244
            break;
1245
        case 'q':
1246
            ctx->qflag = 1;
1247
            break;
1248
        case 'P':
1249
            pattern = parse_pattern(optarg);
1250
            if (pattern < 0) {
1251
                return 0;
1252
            }
1253
            break;
1254
        default:
1255
            free(ctx);
1256
            return command_usage(&aio_write_cmd);
1257
        }
1258
    }
1259

    
1260
    if (optind > argc - 2) {
1261
        free(ctx);
1262
        return command_usage(&aio_write_cmd);
1263
    }
1264

    
1265
    ctx->offset = cvtnum(argv[optind]);
1266
    if (ctx->offset < 0) {
1267
        printf("non-numeric length argument -- %s\n", argv[optind]);
1268
        free(ctx);
1269
        return 0;
1270
    }
1271
    optind++;
1272

    
1273
    if (ctx->offset & 0x1ff) {
1274
        printf("offset %" PRId64 " is not sector aligned\n",
1275
               ctx->offset);
1276
        free(ctx);
1277
        return 0;
1278
    }
1279

    
1280
    nr_iov = argc - optind;
1281
    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
1282

    
1283
    gettimeofday(&ctx->t1, NULL);
1284
    acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1285
                          ctx->qiov.size >> 9, aio_write_done, ctx);
1286
    if (!acb) {
1287
        free(ctx->buf);
1288
        free(ctx);
1289
        return -EIO;
1290
    }
1291

    
1292
    return 0;
1293
}
1294

    
1295
static int aio_flush_f(int argc, char **argv)
1296
{
1297
    qemu_aio_flush();
1298
    return 0;
1299
}
1300

    
1301
static const cmdinfo_t aio_flush_cmd = {
1302
    .name       = "aio_flush",
1303
    .cfunc      = aio_flush_f,
1304
    .oneline    = "completes all outstanding aio requests"
1305
};
1306

    
1307
static int flush_f(int argc, char **argv)
1308
{
1309
    bdrv_flush(bs);
1310
    return 0;
1311
}
1312

    
1313
static const cmdinfo_t flush_cmd = {
1314
    .name       = "flush",
1315
    .altname    = "f",
1316
    .cfunc      = flush_f,
1317
    .oneline    = "flush all in-core file state to disk",
1318
};
1319

    
1320
static int truncate_f(int argc, char **argv)
1321
{
1322
    int64_t offset;
1323
    int ret;
1324

    
1325
    offset = cvtnum(argv[1]);
1326
    if (offset < 0) {
1327
        printf("non-numeric truncate argument -- %s\n", argv[1]);
1328
        return 0;
1329
    }
1330

    
1331
    ret = bdrv_truncate(bs, offset);
1332
    if (ret < 0) {
1333
        printf("truncate: %s\n", strerror(-ret));
1334
        return 0;
1335
    }
1336

    
1337
    return 0;
1338
}
1339

    
1340
static const cmdinfo_t truncate_cmd = {
1341
    .name       = "truncate",
1342
    .altname    = "t",
1343
    .cfunc      = truncate_f,
1344
    .argmin     = 1,
1345
    .argmax     = 1,
1346
    .args       = "off",
1347
    .oneline    = "truncates the current file at the given offset",
1348
};
1349

    
1350
static int length_f(int argc, char **argv)
1351
{
1352
    int64_t size;
1353
    char s1[64];
1354

    
1355
    size = bdrv_getlength(bs);
1356
    if (size < 0) {
1357
        printf("getlength: %s\n", strerror(-size));
1358
        return 0;
1359
    }
1360

    
1361
    cvtstr(size, s1, sizeof(s1));
1362
    printf("%s\n", s1);
1363
    return 0;
1364
}
1365

    
1366

    
1367
static const cmdinfo_t length_cmd = {
1368
    .name   = "length",
1369
    .altname    = "l",
1370
    .cfunc      = length_f,
1371
    .oneline    = "gets the length of the current file",
1372
};
1373

    
1374

    
1375
static int info_f(int argc, char **argv)
1376
{
1377
    BlockDriverInfo bdi;
1378
    char s1[64], s2[64];
1379
    int ret;
1380

    
1381
    if (bs->drv && bs->drv->format_name) {
1382
        printf("format name: %s\n", bs->drv->format_name);
1383
    }
1384
    if (bs->drv && bs->drv->protocol_name) {
1385
        printf("format name: %s\n", bs->drv->protocol_name);
1386
    }
1387

    
1388
    ret = bdrv_get_info(bs, &bdi);
1389
    if (ret) {
1390
        return 0;
1391
    }
1392

    
1393
    cvtstr(bdi.cluster_size, s1, sizeof(s1));
1394
    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1395

    
1396
    printf("cluster size: %s\n", s1);
1397
    printf("vm state offset: %s\n", s2);
1398

    
1399
    return 0;
1400
}
1401

    
1402

    
1403

    
1404
static const cmdinfo_t info_cmd = {
1405
    .name       = "info",
1406
    .altname    = "i",
1407
    .cfunc      = info_f,
1408
    .oneline    = "prints information about the current file",
1409
};
1410

    
1411
static void discard_help(void)
1412
{
1413
    printf(
1414
"\n"
1415
" discards a range of bytes from the given offset\n"
1416
"\n"
1417
" Example:\n"
1418
" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1419
"\n"
1420
" Discards a segment of the currently open file.\n"
1421
" -C, -- report statistics in a machine parsable format\n"
1422
" -q, -- quiet mode, do not show I/O statistics\n"
1423
"\n");
1424
}
1425

    
1426
static int discard_f(int argc, char **argv);
1427

    
1428
static const cmdinfo_t discard_cmd = {
1429
    .name       = "discard",
1430
    .altname    = "d",
1431
    .cfunc      = discard_f,
1432
    .argmin     = 2,
1433
    .argmax     = -1,
1434
    .args       = "[-Cq] off len",
1435
    .oneline    = "discards a number of bytes at a specified offset",
1436
    .help       = discard_help,
1437
};
1438

    
1439
static int discard_f(int argc, char **argv)
1440
{
1441
    struct timeval t1, t2;
1442
    int Cflag = 0, qflag = 0;
1443
    int c, ret;
1444
    int64_t offset;
1445
    int count;
1446

    
1447
    while ((c = getopt(argc, argv, "Cq")) != EOF) {
1448
        switch (c) {
1449
        case 'C':
1450
            Cflag = 1;
1451
            break;
1452
        case 'q':
1453
            qflag = 1;
1454
            break;
1455
        default:
1456
            return command_usage(&discard_cmd);
1457
        }
1458
    }
1459

    
1460
    if (optind != argc - 2) {
1461
        return command_usage(&discard_cmd);
1462
    }
1463

    
1464
    offset = cvtnum(argv[optind]);
1465
    if (offset < 0) {
1466
        printf("non-numeric length argument -- %s\n", argv[optind]);
1467
        return 0;
1468
    }
1469

    
1470
    optind++;
1471
    count = cvtnum(argv[optind]);
1472
    if (count < 0) {
1473
        printf("non-numeric length argument -- %s\n", argv[optind]);
1474
        return 0;
1475
    }
1476

    
1477
    gettimeofday(&t1, NULL);
1478
    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1479
                       count >> BDRV_SECTOR_BITS);
1480
    gettimeofday(&t2, NULL);
1481

    
1482
    if (ret < 0) {
1483
        printf("discard failed: %s\n", strerror(-ret));
1484
        goto out;
1485
    }
1486

    
1487
    /* Finally, report back -- -C gives a parsable format */
1488
    if (!qflag) {
1489
        t2 = tsub(t2, t1);
1490
        print_report("discard", &t2, offset, count, count, 1, Cflag);
1491
    }
1492

    
1493
out:
1494
    return 0;
1495
}
1496

    
1497
static int alloc_f(int argc, char **argv)
1498
{
1499
    int64_t offset;
1500
    int nb_sectors, remaining;
1501
    char s1[64];
1502
    int num, sum_alloc;
1503
    int ret;
1504

    
1505
    offset = cvtnum(argv[1]);
1506
    if (offset & 0x1ff) {
1507
        printf("offset %" PRId64 " is not sector aligned\n",
1508
               offset);
1509
        return 0;
1510
    }
1511

    
1512
    if (argc == 3) {
1513
        nb_sectors = cvtnum(argv[2]);
1514
    } else {
1515
        nb_sectors = 1;
1516
    }
1517

    
1518
    remaining = nb_sectors;
1519
    sum_alloc = 0;
1520
    while (remaining) {
1521
        ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
1522
        remaining -= num;
1523
        if (ret) {
1524
            sum_alloc += num;
1525
        }
1526
    }
1527

    
1528
    cvtstr(offset, s1, sizeof(s1));
1529

    
1530
    printf("%d/%d sectors allocated at offset %s\n",
1531
           sum_alloc, nb_sectors, s1);
1532
    return 0;
1533
}
1534

    
1535
static const cmdinfo_t alloc_cmd = {
1536
    .name       = "alloc",
1537
    .altname    = "a",
1538
    .argmin     = 1,
1539
    .argmax     = 2,
1540
    .cfunc      = alloc_f,
1541
    .args       = "off [sectors]",
1542
    .oneline    = "checks if a sector is present in the file",
1543
};
1544

    
1545
static int map_f(int argc, char **argv)
1546
{
1547
    int64_t offset;
1548
    int64_t nb_sectors;
1549
    char s1[64];
1550
    int num, num_checked;
1551
    int ret;
1552
    const char *retstr;
1553

    
1554
    offset = 0;
1555
    nb_sectors = bs->total_sectors;
1556

    
1557
    do {
1558
        num_checked = MIN(nb_sectors, INT_MAX);
1559
        ret = bdrv_is_allocated(bs, offset, num_checked, &num);
1560
        retstr = ret ? "    allocated" : "not allocated";
1561
        cvtstr(offset << 9ULL, s1, sizeof(s1));
1562
        printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
1563
               offset << 9ULL, num, num_checked, retstr, s1, ret);
1564

    
1565
        offset += num;
1566
        nb_sectors -= num;
1567
    } while (offset < bs->total_sectors);
1568

    
1569
    return 0;
1570
}
1571

    
1572
static const cmdinfo_t map_cmd = {
1573
       .name           = "map",
1574
       .argmin         = 0,
1575
       .argmax         = 0,
1576
       .cfunc          = map_f,
1577
       .args           = "",
1578
       .oneline        = "prints the allocated areas of a file",
1579
};
1580

    
1581

    
1582
static int close_f(int argc, char **argv)
1583
{
1584
    bdrv_close(bs);
1585
    bs = NULL;
1586
    return 0;
1587
}
1588

    
1589
static const cmdinfo_t close_cmd = {
1590
    .name       = "close",
1591
    .altname    = "c",
1592
    .cfunc      = close_f,
1593
    .oneline    = "close the current open file",
1594
};
1595

    
1596
static int openfile(char *name, int flags, int growable)
1597
{
1598
    if (bs) {
1599
        fprintf(stderr, "file open already, try 'help close'\n");
1600
        return 1;
1601
    }
1602

    
1603
    if (growable) {
1604
        if (bdrv_file_open(&bs, name, flags)) {
1605
            fprintf(stderr, "%s: can't open device %s\n", progname, name);
1606
            return 1;
1607
        }
1608
    } else {
1609
        bs = bdrv_new("hda");
1610

    
1611
        if (bdrv_open(bs, name, flags, NULL) < 0) {
1612
            fprintf(stderr, "%s: can't open device %s\n", progname, name);
1613
            bs = NULL;
1614
            return 1;
1615
        }
1616
    }
1617

    
1618
    return 0;
1619
}
1620

    
1621
static void open_help(void)
1622
{
1623
    printf(
1624
"\n"
1625
" opens a new file in the requested mode\n"
1626
"\n"
1627
" Example:\n"
1628
" 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
1629
"\n"
1630
" Opens a file for subsequent use by all of the other qemu-io commands.\n"
1631
" -r, -- open file read-only\n"
1632
" -s, -- use snapshot file\n"
1633
" -n, -- disable host cache\n"
1634
" -g, -- allow file to grow (only applies to protocols)"
1635
"\n");
1636
}
1637

    
1638
static int open_f(int argc, char **argv);
1639

    
1640
static const cmdinfo_t open_cmd = {
1641
    .name       = "open",
1642
    .altname    = "o",
1643
    .cfunc      = open_f,
1644
    .argmin     = 1,
1645
    .argmax     = -1,
1646
    .flags      = CMD_NOFILE_OK,
1647
    .args       = "[-Crsn] [path]",
1648
    .oneline    = "open the file specified by path",
1649
    .help       = open_help,
1650
};
1651

    
1652
static int open_f(int argc, char **argv)
1653
{
1654
    int flags = 0;
1655
    int readonly = 0;
1656
    int growable = 0;
1657
    int c;
1658

    
1659
    while ((c = getopt(argc, argv, "snrg")) != EOF) {
1660
        switch (c) {
1661
        case 's':
1662
            flags |= BDRV_O_SNAPSHOT;
1663
            break;
1664
        case 'n':
1665
            flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
1666
            break;
1667
        case 'r':
1668
            readonly = 1;
1669
            break;
1670
        case 'g':
1671
            growable = 1;
1672
            break;
1673
        default:
1674
            return command_usage(&open_cmd);
1675
        }
1676
    }
1677

    
1678
    if (!readonly) {
1679
        flags |= BDRV_O_RDWR;
1680
    }
1681

    
1682
    if (optind != argc - 1) {
1683
        return command_usage(&open_cmd);
1684
    }
1685

    
1686
    return openfile(argv[optind], flags, growable);
1687
}
1688

    
1689
static int init_args_command(int index)
1690
{
1691
    /* only one device allowed so far */
1692
    if (index >= 1) {
1693
        return 0;
1694
    }
1695
    return ++index;
1696
}
1697

    
1698
static int init_check_command(const cmdinfo_t *ct)
1699
{
1700
    if (ct->flags & CMD_FLAG_GLOBAL) {
1701
        return 1;
1702
    }
1703
    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1704
        fprintf(stderr, "no file open, try 'help open'\n");
1705
        return 0;
1706
    }
1707
    return 1;
1708
}
1709

    
1710
static void usage(const char *name)
1711
{
1712
    printf(
1713
"Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
1714
"QEMU Disk exerciser\n"
1715
"\n"
1716
"  -c, --cmd            command to execute\n"
1717
"  -r, --read-only      export read-only\n"
1718
"  -s, --snapshot       use snapshot file\n"
1719
"  -n, --nocache        disable host cache\n"
1720
"  -g, --growable       allow file to grow (only applies to protocols)\n"
1721
"  -m, --misalign       misalign allocations for O_DIRECT\n"
1722
"  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
1723
"  -h, --help           display this help and exit\n"
1724
"  -V, --version        output version information and exit\n"
1725
"\n",
1726
    name);
1727
}
1728

    
1729

    
1730
int main(int argc, char **argv)
1731
{
1732
    int readonly = 0;
1733
    int growable = 0;
1734
    const char *sopt = "hVc:rsnmgk";
1735
    const struct option lopt[] = {
1736
        { "help", 0, NULL, 'h' },
1737
        { "version", 0, NULL, 'V' },
1738
        { "offset", 1, NULL, 'o' },
1739
        { "cmd", 1, NULL, 'c' },
1740
        { "read-only", 0, NULL, 'r' },
1741
        { "snapshot", 0, NULL, 's' },
1742
        { "nocache", 0, NULL, 'n' },
1743
        { "misalign", 0, NULL, 'm' },
1744
        { "growable", 0, NULL, 'g' },
1745
        { "native-aio", 0, NULL, 'k' },
1746
        { NULL, 0, NULL, 0 }
1747
    };
1748
    int c;
1749
    int opt_index = 0;
1750
    int flags = 0;
1751

    
1752
    progname = basename(argv[0]);
1753

    
1754
    while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
1755
        switch (c) {
1756
        case 's':
1757
            flags |= BDRV_O_SNAPSHOT;
1758
            break;
1759
        case 'n':
1760
            flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
1761
            break;
1762
        case 'c':
1763
            add_user_command(optarg);
1764
            break;
1765
        case 'r':
1766
            readonly = 1;
1767
            break;
1768
        case 'm':
1769
            misalign = 1;
1770
            break;
1771
        case 'g':
1772
            growable = 1;
1773
            break;
1774
        case 'k':
1775
            flags |= BDRV_O_NATIVE_AIO;
1776
            break;
1777
        case 'V':
1778
            printf("%s version %s\n", progname, VERSION);
1779
            exit(0);
1780
        case 'h':
1781
            usage(progname);
1782
            exit(0);
1783
        default:
1784
            usage(progname);
1785
            exit(1);
1786
        }
1787
    }
1788

    
1789
    if ((argc - optind) > 1) {
1790
        usage(progname);
1791
        exit(1);
1792
    }
1793

    
1794
    bdrv_init();
1795

    
1796
    /* initialize commands */
1797
    quit_init();
1798
    help_init();
1799
    add_command(&open_cmd);
1800
    add_command(&close_cmd);
1801
    add_command(&read_cmd);
1802
    add_command(&readv_cmd);
1803
    add_command(&write_cmd);
1804
    add_command(&writev_cmd);
1805
    add_command(&multiwrite_cmd);
1806
    add_command(&aio_read_cmd);
1807
    add_command(&aio_write_cmd);
1808
    add_command(&aio_flush_cmd);
1809
    add_command(&flush_cmd);
1810
    add_command(&truncate_cmd);
1811
    add_command(&length_cmd);
1812
    add_command(&info_cmd);
1813
    add_command(&discard_cmd);
1814
    add_command(&alloc_cmd);
1815
    add_command(&map_cmd);
1816

    
1817
    add_args_command(init_args_command);
1818
    add_check_command(init_check_command);
1819

    
1820
    /* open the device */
1821
    if (!readonly) {
1822
        flags |= BDRV_O_RDWR;
1823
    }
1824

    
1825
    if ((argc - optind) == 1) {
1826
        openfile(argv[optind], flags, growable);
1827
    }
1828
    command_loop();
1829

    
1830
    /*
1831
     * Make sure all outstanding requests get flushed the program exits.
1832
     */
1833
    qemu_aio_flush();
1834

    
1835
    if (bs) {
1836
        bdrv_close(bs);
1837
    }
1838
    return 0;
1839
}