~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to qemu-io-cmds.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-10-22 22:47:07 UTC
  • mfrom: (1.8.3) (10.1.42 sid)
  • Revision ID: package-import@ubuntu.com-20131022224707-1lya34fw3k3f24tv
Tags: 1.6.0+dfsg-2ubuntu1
* Merge 1.6.0~rc0+dfsg-2exp from debian experimental.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
      - drop openbios-ppc and openhackware Depends to Suggests (for now)
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - New linaro patches from qemu-linaro rebasing branch
  - Dropped patches:
    * xen-simplify-xen_enabled.patch
    * sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
    * main_loop-do-not-set-nonblocking-if-xen_enabled.patch
    * xen_machine_pv-do-not-create-a-dummy-CPU-in-machine-.patch
    * virtio-rng-fix-crash
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * linaro arm patches from qemu-linaro rebasing branch
  - New patches:
    * fix-pci-add: change CONFIG variable in ifdef to make sure that
      pci_add is defined.
* Add linaro patches
* Add experimental mach-virt patches for arm virtualization.
* qemu-system-common.install: add debian/tmp/usr/lib to install the
  qemu-bridge-helper

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Command line utility to exercise the QEMU I/O path.
 
3
 *
 
4
 * Copyright (C) 2009 Red Hat, Inc.
 
5
 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
 
6
 *
 
7
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 
8
 * See the COPYING file in the top-level directory.
 
9
 */
 
10
 
 
11
#include "qemu-io.h"
 
12
#include "block/block_int.h"
 
13
 
 
14
#define CMD_NOFILE_OK   0x01
 
15
 
 
16
int qemuio_misalign;
 
17
 
 
18
static cmdinfo_t *cmdtab;
 
19
static int ncmds;
 
20
 
 
21
static int compare_cmdname(const void *a, const void *b)
 
22
{
 
23
    return strcmp(((const cmdinfo_t *)a)->name,
 
24
                  ((const cmdinfo_t *)b)->name);
 
25
}
 
26
 
 
27
void qemuio_add_command(const cmdinfo_t *ci)
 
28
{
 
29
    cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
 
30
    cmdtab[ncmds - 1] = *ci;
 
31
    qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
 
32
}
 
33
 
 
34
int qemuio_command_usage(const cmdinfo_t *ci)
 
35
{
 
36
    printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
 
37
    return 0;
 
38
}
 
39
 
 
40
static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
 
41
{
 
42
    if (ct->flags & CMD_FLAG_GLOBAL) {
 
43
        return 1;
 
44
    }
 
45
    if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
 
46
        fprintf(stderr, "no file open, try 'help open'\n");
 
47
        return 0;
 
48
    }
 
49
    return 1;
 
50
}
 
51
 
 
52
static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
 
53
                   char **argv)
 
54
{
 
55
    char *cmd = argv[0];
 
56
 
 
57
    if (!init_check_command(bs, ct)) {
 
58
        return 0;
 
59
    }
 
60
 
 
61
    if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
 
62
        if (ct->argmax == -1) {
 
63
            fprintf(stderr,
 
64
                    "bad argument count %d to %s, expected at least %d arguments\n",
 
65
                    argc-1, cmd, ct->argmin);
 
66
        } else if (ct->argmin == ct->argmax) {
 
67
            fprintf(stderr,
 
68
                    "bad argument count %d to %s, expected %d arguments\n",
 
69
                    argc-1, cmd, ct->argmin);
 
70
        } else {
 
71
            fprintf(stderr,
 
72
                    "bad argument count %d to %s, expected between %d and %d arguments\n",
 
73
                    argc-1, cmd, ct->argmin, ct->argmax);
 
74
        }
 
75
        return 0;
 
76
    }
 
77
    optind = 0;
 
78
    return ct->cfunc(bs, argc, argv);
 
79
}
 
80
 
 
81
static const cmdinfo_t *find_command(const char *cmd)
 
82
{
 
83
    cmdinfo_t *ct;
 
84
 
 
85
    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
 
86
        if (strcmp(ct->name, cmd) == 0 ||
 
87
            (ct->altname && strcmp(ct->altname, cmd) == 0))
 
88
        {
 
89
            return (const cmdinfo_t *)ct;
 
90
        }
 
91
    }
 
92
    return NULL;
 
93
}
 
94
 
 
95
static char **breakline(char *input, int *count)
 
96
{
 
97
    int c = 0;
 
98
    char *p;
 
99
    char **rval = g_malloc0(sizeof(char *));
 
100
    char **tmp;
 
101
 
 
102
    while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
 
103
        if (!*p) {
 
104
            continue;
 
105
        }
 
106
        c++;
 
107
        tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
 
108
        if (!tmp) {
 
109
            g_free(rval);
 
110
            rval = NULL;
 
111
            c = 0;
 
112
            break;
 
113
        } else {
 
114
            rval = tmp;
 
115
        }
 
116
        rval[c - 1] = p;
 
117
        rval[c] = NULL;
 
118
    }
 
119
    *count = c;
 
120
    return rval;
 
121
}
 
122
 
 
123
static int64_t cvtnum(const char *s)
 
124
{
 
125
    char *end;
 
126
    return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
 
127
}
 
128
 
 
129
#define EXABYTES(x)     ((long long)(x) << 60)
 
130
#define PETABYTES(x)    ((long long)(x) << 50)
 
131
#define TERABYTES(x)    ((long long)(x) << 40)
 
132
#define GIGABYTES(x)    ((long long)(x) << 30)
 
133
#define MEGABYTES(x)    ((long long)(x) << 20)
 
134
#define KILOBYTES(x)    ((long long)(x) << 10)
 
135
 
 
136
#define TO_EXABYTES(x)  ((x) / EXABYTES(1))
 
137
#define TO_PETABYTES(x) ((x) / PETABYTES(1))
 
138
#define TO_TERABYTES(x) ((x) / TERABYTES(1))
 
139
#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
 
140
#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
 
141
#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
 
142
 
 
143
static void cvtstr(double value, char *str, size_t size)
 
144
{
 
145
    char *trim;
 
146
    const char *suffix;
 
147
 
 
148
    if (value >= EXABYTES(1)) {
 
149
        suffix = " EiB";
 
150
        snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
 
151
    } else if (value >= PETABYTES(1)) {
 
152
        suffix = " PiB";
 
153
        snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
 
154
    } else if (value >= TERABYTES(1)) {
 
155
        suffix = " TiB";
 
156
        snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
 
157
    } else if (value >= GIGABYTES(1)) {
 
158
        suffix = " GiB";
 
159
        snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
 
160
    } else if (value >= MEGABYTES(1)) {
 
161
        suffix = " MiB";
 
162
        snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
 
163
    } else if (value >= KILOBYTES(1)) {
 
164
        suffix = " KiB";
 
165
        snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
 
166
    } else {
 
167
        suffix = " bytes";
 
168
        snprintf(str, size - 6, "%f", value);
 
169
    }
 
170
 
 
171
    trim = strstr(str, ".000");
 
172
    if (trim) {
 
173
        strcpy(trim, suffix);
 
174
    } else {
 
175
        strcat(str, suffix);
 
176
    }
 
177
}
 
178
 
 
179
 
 
180
 
 
181
static struct timeval tsub(struct timeval t1, struct timeval t2)
 
182
{
 
183
    t1.tv_usec -= t2.tv_usec;
 
184
    if (t1.tv_usec < 0) {
 
185
        t1.tv_usec += 1000000;
 
186
        t1.tv_sec--;
 
187
    }
 
188
    t1.tv_sec -= t2.tv_sec;
 
189
    return t1;
 
190
}
 
191
 
 
192
static double tdiv(double value, struct timeval tv)
 
193
{
 
194
    return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
 
195
}
 
196
 
 
197
#define HOURS(sec)      ((sec) / (60 * 60))
 
198
#define MINUTES(sec)    (((sec) % (60 * 60)) / 60)
 
199
#define SECONDS(sec)    ((sec) % 60)
 
200
 
 
201
enum {
 
202
    DEFAULT_TIME        = 0x0,
 
203
    TERSE_FIXED_TIME    = 0x1,
 
204
    VERBOSE_FIXED_TIME  = 0x2,
 
205
};
 
206
 
 
207
static void timestr(struct timeval *tv, char *ts, size_t size, int format)
 
208
{
 
209
    double usec = (double)tv->tv_usec / 1000000.0;
 
210
 
 
211
    if (format & TERSE_FIXED_TIME) {
 
212
        if (!HOURS(tv->tv_sec)) {
 
213
            snprintf(ts, size, "%u:%02u.%02u",
 
214
                    (unsigned int) MINUTES(tv->tv_sec),
 
215
                    (unsigned int) SECONDS(tv->tv_sec),
 
216
                    (unsigned int) (usec * 100));
 
217
            return;
 
218
        }
 
219
        format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
 
220
    }
 
221
 
 
222
    if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
 
223
        snprintf(ts, size, "%u:%02u:%02u.%02u",
 
224
                (unsigned int) HOURS(tv->tv_sec),
 
225
                (unsigned int) MINUTES(tv->tv_sec),
 
226
                (unsigned int) SECONDS(tv->tv_sec),
 
227
                (unsigned int) (usec * 100));
 
228
    } else {
 
229
        snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
 
230
    }
 
231
}
 
232
 
 
233
/*
 
234
 * Parse the pattern argument to various sub-commands.
 
235
 *
 
236
 * Because the pattern is used as an argument to memset it must evaluate
 
237
 * to an unsigned integer that fits into a single byte.
 
238
 */
 
239
static int parse_pattern(const char *arg)
 
240
{
 
241
    char *endptr = NULL;
 
242
    long pattern;
 
243
 
 
244
    pattern = strtol(arg, &endptr, 0);
 
245
    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
 
246
        printf("%s is not a valid pattern byte\n", arg);
 
247
        return -1;
 
248
    }
 
249
 
 
250
    return pattern;
 
251
}
 
252
 
 
253
/*
 
254
 * Memory allocation helpers.
 
255
 *
 
256
 * Make sure memory is aligned by default, or purposefully misaligned if
 
257
 * that is specified on the command line.
 
258
 */
 
259
 
 
260
#define MISALIGN_OFFSET     16
 
261
static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
 
262
{
 
263
    void *buf;
 
264
 
 
265
    if (qemuio_misalign) {
 
266
        len += MISALIGN_OFFSET;
 
267
    }
 
268
    buf = qemu_blockalign(bs, len);
 
269
    memset(buf, pattern, len);
 
270
    if (qemuio_misalign) {
 
271
        buf += MISALIGN_OFFSET;
 
272
    }
 
273
    return buf;
 
274
}
 
275
 
 
276
static void qemu_io_free(void *p)
 
277
{
 
278
    if (qemuio_misalign) {
 
279
        p -= MISALIGN_OFFSET;
 
280
    }
 
281
    qemu_vfree(p);
 
282
}
 
283
 
 
284
static void dump_buffer(const void *buffer, int64_t offset, int len)
 
285
{
 
286
    int i, j;
 
287
    const uint8_t *p;
 
288
 
 
289
    for (i = 0, p = buffer; i < len; i += 16) {
 
290
        const uint8_t *s = p;
 
291
 
 
292
        printf("%08" PRIx64 ":  ", offset + i);
 
293
        for (j = 0; j < 16 && i + j < len; j++, p++) {
 
294
            printf("%02x ", *p);
 
295
        }
 
296
        printf(" ");
 
297
        for (j = 0; j < 16 && i + j < len; j++, s++) {
 
298
            if (isalnum(*s)) {
 
299
                printf("%c", *s);
 
300
            } else {
 
301
                printf(".");
 
302
            }
 
303
        }
 
304
        printf("\n");
 
305
    }
 
306
}
 
307
 
 
308
static void print_report(const char *op, struct timeval *t, int64_t offset,
 
309
                         int count, int total, int cnt, int Cflag)
 
310
{
 
311
    char s1[64], s2[64], ts[64];
 
312
 
 
313
    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
 
314
    if (!Cflag) {
 
315
        cvtstr((double)total, s1, sizeof(s1));
 
316
        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
 
317
        printf("%s %d/%d bytes at offset %" PRId64 "\n",
 
318
               op, total, count, offset);
 
319
        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
 
320
               s1, cnt, ts, s2, tdiv((double)cnt, *t));
 
321
    } else {/* bytes,ops,time,bytes/sec,ops/sec */
 
322
        printf("%d,%d,%s,%.3f,%.3f\n",
 
323
            total, cnt, ts,
 
324
            tdiv((double)total, *t),
 
325
            tdiv((double)cnt, *t));
 
326
    }
 
327
}
 
328
 
 
329
/*
 
330
 * Parse multiple length statements for vectored I/O, and construct an I/O
 
331
 * vector matching it.
 
332
 */
 
333
static void *
 
334
create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
 
335
             int pattern)
 
336
{
 
337
    size_t *sizes = g_new0(size_t, nr_iov);
 
338
    size_t count = 0;
 
339
    void *buf = NULL;
 
340
    void *p;
 
341
    int i;
 
342
 
 
343
    for (i = 0; i < nr_iov; i++) {
 
344
        char *arg = argv[i];
 
345
        int64_t len;
 
346
 
 
347
        len = cvtnum(arg);
 
348
        if (len < 0) {
 
349
            printf("non-numeric length argument -- %s\n", arg);
 
350
            goto fail;
 
351
        }
 
352
 
 
353
        /* should be SIZE_T_MAX, but that doesn't exist */
 
354
        if (len > INT_MAX) {
 
355
            printf("too large length argument -- %s\n", arg);
 
356
            goto fail;
 
357
        }
 
358
 
 
359
        if (len & 0x1ff) {
 
360
            printf("length argument %" PRId64
 
361
                   " is not sector aligned\n", len);
 
362
            goto fail;
 
363
        }
 
364
 
 
365
        sizes[i] = len;
 
366
        count += len;
 
367
    }
 
368
 
 
369
    qemu_iovec_init(qiov, nr_iov);
 
370
 
 
371
    buf = p = qemu_io_alloc(bs, count, pattern);
 
372
 
 
373
    for (i = 0; i < nr_iov; i++) {
 
374
        qemu_iovec_add(qiov, p, sizes[i]);
 
375
        p += sizes[i];
 
376
    }
 
377
 
 
378
fail:
 
379
    g_free(sizes);
 
380
    return buf;
 
381
}
 
382
 
 
383
static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
 
384
                   int *total)
 
385
{
 
386
    int ret;
 
387
 
 
388
    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
 
389
    if (ret < 0) {
 
390
        return ret;
 
391
    }
 
392
    *total = count;
 
393
    return 1;
 
394
}
 
395
 
 
396
static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
 
397
                    int *total)
 
398
{
 
399
    int ret;
 
400
 
 
401
    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
 
402
    if (ret < 0) {
 
403
        return ret;
 
404
    }
 
405
    *total = count;
 
406
    return 1;
 
407
}
 
408
 
 
409
static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
 
410
                    int *total)
 
411
{
 
412
    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
 
413
    if (*total < 0) {
 
414
        return *total;
 
415
    }
 
416
    return 1;
 
417
}
 
418
 
 
419
static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
 
420
                     int *total)
 
421
{
 
422
    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
 
423
    if (*total < 0) {
 
424
        return *total;
 
425
    }
 
426
    return 1;
 
427
}
 
428
 
 
429
typedef struct {
 
430
    BlockDriverState *bs;
 
431
    int64_t offset;
 
432
    int count;
 
433
    int *total;
 
434
    int ret;
 
435
    bool done;
 
436
} CoWriteZeroes;
 
437
 
 
438
static void coroutine_fn co_write_zeroes_entry(void *opaque)
 
439
{
 
440
    CoWriteZeroes *data = opaque;
 
441
 
 
442
    data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
 
443
                                     data->count / BDRV_SECTOR_SIZE);
 
444
    data->done = true;
 
445
    if (data->ret < 0) {
 
446
        *data->total = data->ret;
 
447
        return;
 
448
    }
 
449
 
 
450
    *data->total = data->count;
 
451
}
 
452
 
 
453
static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
 
454
                              int *total)
 
455
{
 
456
    Coroutine *co;
 
457
    CoWriteZeroes data = {
 
458
        .bs     = bs,
 
459
        .offset = offset,
 
460
        .count  = count,
 
461
        .total  = total,
 
462
        .done   = false,
 
463
    };
 
464
 
 
465
    co = qemu_coroutine_create(co_write_zeroes_entry);
 
466
    qemu_coroutine_enter(co, &data);
 
467
    while (!data.done) {
 
468
        qemu_aio_wait();
 
469
    }
 
470
    if (data.ret < 0) {
 
471
        return data.ret;
 
472
    } else {
 
473
        return 1;
 
474
    }
 
475
}
 
476
 
 
477
static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
 
478
                               int count, int *total)
 
479
{
 
480
    int ret;
 
481
 
 
482
    ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
 
483
    if (ret < 0) {
 
484
        return ret;
 
485
    }
 
486
    *total = count;
 
487
    return 1;
 
488
}
 
489
 
 
490
static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
 
491
                           int count, int *total)
 
492
{
 
493
    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
 
494
    if (*total < 0) {
 
495
        return *total;
 
496
    }
 
497
    return 1;
 
498
}
 
499
 
 
500
static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
 
501
                           int count, int *total)
 
502
{
 
503
    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
 
504
    if (*total < 0) {
 
505
        return *total;
 
506
    }
 
507
    return 1;
 
508
}
 
509
 
 
510
#define NOT_DONE 0x7fffffff
 
511
static void aio_rw_done(void *opaque, int ret)
 
512
{
 
513
    *(int *)opaque = ret;
 
514
}
 
515
 
 
516
static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
 
517
                        int64_t offset, int *total)
 
518
{
 
519
    int async_ret = NOT_DONE;
 
520
 
 
521
    bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
 
522
                   aio_rw_done, &async_ret);
 
523
    while (async_ret == NOT_DONE) {
 
524
        main_loop_wait(false);
 
525
    }
 
526
 
 
527
    *total = qiov->size;
 
528
    return async_ret < 0 ? async_ret : 1;
 
529
}
 
530
 
 
531
static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
 
532
                         int64_t offset, int *total)
 
533
{
 
534
    int async_ret = NOT_DONE;
 
535
 
 
536
    bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
 
537
                    aio_rw_done, &async_ret);
 
538
    while (async_ret == NOT_DONE) {
 
539
        main_loop_wait(false);
 
540
    }
 
541
 
 
542
    *total = qiov->size;
 
543
    return async_ret < 0 ? async_ret : 1;
 
544
}
 
545
 
 
546
struct multiwrite_async_ret {
 
547
    int num_done;
 
548
    int error;
 
549
};
 
550
 
 
551
static void multiwrite_cb(void *opaque, int ret)
 
552
{
 
553
    struct multiwrite_async_ret *async_ret = opaque;
 
554
 
 
555
    async_ret->num_done++;
 
556
    if (ret < 0) {
 
557
        async_ret->error = ret;
 
558
    }
 
559
}
 
560
 
 
561
static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
 
562
                             int num_reqs, int *total)
 
563
{
 
564
    int i, ret;
 
565
    struct multiwrite_async_ret async_ret = {
 
566
        .num_done = 0,
 
567
        .error = 0,
 
568
    };
 
569
 
 
570
    *total = 0;
 
571
    for (i = 0; i < num_reqs; i++) {
 
572
        reqs[i].cb = multiwrite_cb;
 
573
        reqs[i].opaque = &async_ret;
 
574
        *total += reqs[i].qiov->size;
 
575
    }
 
576
 
 
577
    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
 
578
    if (ret < 0) {
 
579
        return ret;
 
580
    }
 
581
 
 
582
    while (async_ret.num_done < num_reqs) {
 
583
        main_loop_wait(false);
 
584
    }
 
585
 
 
586
    return async_ret.error < 0 ? async_ret.error : 1;
 
587
}
 
588
 
 
589
static void read_help(void)
 
590
{
 
591
    printf(
 
592
"\n"
 
593
" reads a range of bytes from the given offset\n"
 
594
"\n"
 
595
" Example:\n"
 
596
" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
 
597
"\n"
 
598
" Reads a segment of the currently open file, optionally dumping it to the\n"
 
599
" standard output stream (with -v option) for subsequent inspection.\n"
 
600
" -b, -- read from the VM state rather than the virtual disk\n"
 
601
" -C, -- report statistics in a machine parsable format\n"
 
602
" -l, -- length for pattern verification (only with -P)\n"
 
603
" -p, -- use bdrv_pread to read the file\n"
 
604
" -P, -- use a pattern to verify read data\n"
 
605
" -q, -- quiet mode, do not show I/O statistics\n"
 
606
" -s, -- start offset for pattern verification (only with -P)\n"
 
607
" -v, -- dump buffer to standard output\n"
 
608
"\n");
 
609
}
 
610
 
 
611
static int read_f(BlockDriverState *bs, int argc, char **argv);
 
612
 
 
613
static const cmdinfo_t read_cmd = {
 
614
    .name       = "read",
 
615
    .altname    = "r",
 
616
    .cfunc      = read_f,
 
617
    .argmin     = 2,
 
618
    .argmax     = -1,
 
619
    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
 
620
    .oneline    = "reads a number of bytes at a specified offset",
 
621
    .help       = read_help,
 
622
};
 
623
 
 
624
static int read_f(BlockDriverState *bs, int argc, char **argv)
 
625
{
 
626
    struct timeval t1, t2;
 
627
    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
 
628
    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
 
629
    int c, cnt;
 
630
    char *buf;
 
631
    int64_t offset;
 
632
    int count;
 
633
    /* Some compilers get confused and warn if this is not initialized.  */
 
634
    int total = 0;
 
635
    int pattern = 0, pattern_offset = 0, pattern_count = 0;
 
636
 
 
637
    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
 
638
        switch (c) {
 
639
        case 'b':
 
640
            bflag = 1;
 
641
            break;
 
642
        case 'C':
 
643
            Cflag = 1;
 
644
            break;
 
645
        case 'l':
 
646
            lflag = 1;
 
647
            pattern_count = cvtnum(optarg);
 
648
            if (pattern_count < 0) {
 
649
                printf("non-numeric length argument -- %s\n", optarg);
 
650
                return 0;
 
651
            }
 
652
            break;
 
653
        case 'p':
 
654
            pflag = 1;
 
655
            break;
 
656
        case 'P':
 
657
            Pflag = 1;
 
658
            pattern = parse_pattern(optarg);
 
659
            if (pattern < 0) {
 
660
                return 0;
 
661
            }
 
662
            break;
 
663
        case 'q':
 
664
            qflag = 1;
 
665
            break;
 
666
        case 's':
 
667
            sflag = 1;
 
668
            pattern_offset = cvtnum(optarg);
 
669
            if (pattern_offset < 0) {
 
670
                printf("non-numeric length argument -- %s\n", optarg);
 
671
                return 0;
 
672
            }
 
673
            break;
 
674
        case 'v':
 
675
            vflag = 1;
 
676
            break;
 
677
        default:
 
678
            return qemuio_command_usage(&read_cmd);
 
679
        }
 
680
    }
 
681
 
 
682
    if (optind != argc - 2) {
 
683
        return qemuio_command_usage(&read_cmd);
 
684
    }
 
685
 
 
686
    if (bflag && pflag) {
 
687
        printf("-b and -p cannot be specified at the same time\n");
 
688
        return 0;
 
689
    }
 
690
 
 
691
    offset = cvtnum(argv[optind]);
 
692
    if (offset < 0) {
 
693
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
694
        return 0;
 
695
    }
 
696
 
 
697
    optind++;
 
698
    count = cvtnum(argv[optind]);
 
699
    if (count < 0) {
 
700
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
701
        return 0;
 
702
    }
 
703
 
 
704
    if (!Pflag && (lflag || sflag)) {
 
705
        return qemuio_command_usage(&read_cmd);
 
706
    }
 
707
 
 
708
    if (!lflag) {
 
709
        pattern_count = count - pattern_offset;
 
710
    }
 
711
 
 
712
    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
 
713
        printf("pattern verification range exceeds end of read data\n");
 
714
        return 0;
 
715
    }
 
716
 
 
717
    if (!pflag) {
 
718
        if (offset & 0x1ff) {
 
719
            printf("offset %" PRId64 " is not sector aligned\n",
 
720
                   offset);
 
721
            return 0;
 
722
        }
 
723
        if (count & 0x1ff) {
 
724
            printf("count %d is not sector aligned\n",
 
725
                   count);
 
726
            return 0;
 
727
        }
 
728
    }
 
729
 
 
730
    buf = qemu_io_alloc(bs, count, 0xab);
 
731
 
 
732
    gettimeofday(&t1, NULL);
 
733
    if (pflag) {
 
734
        cnt = do_pread(bs, buf, offset, count, &total);
 
735
    } else if (bflag) {
 
736
        cnt = do_load_vmstate(bs, buf, offset, count, &total);
 
737
    } else {
 
738
        cnt = do_read(bs, buf, offset, count, &total);
 
739
    }
 
740
    gettimeofday(&t2, NULL);
 
741
 
 
742
    if (cnt < 0) {
 
743
        printf("read failed: %s\n", strerror(-cnt));
 
744
        goto out;
 
745
    }
 
746
 
 
747
    if (Pflag) {
 
748
        void *cmp_buf = g_malloc(pattern_count);
 
749
        memset(cmp_buf, pattern, pattern_count);
 
750
        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
 
751
            printf("Pattern verification failed at offset %"
 
752
                   PRId64 ", %d bytes\n",
 
753
                   offset + pattern_offset, pattern_count);
 
754
        }
 
755
        g_free(cmp_buf);
 
756
    }
 
757
 
 
758
    if (qflag) {
 
759
        goto out;
 
760
    }
 
761
 
 
762
    if (vflag) {
 
763
        dump_buffer(buf, offset, count);
 
764
    }
 
765
 
 
766
    /* Finally, report back -- -C gives a parsable format */
 
767
    t2 = tsub(t2, t1);
 
768
    print_report("read", &t2, offset, count, total, cnt, Cflag);
 
769
 
 
770
out:
 
771
    qemu_io_free(buf);
 
772
 
 
773
    return 0;
 
774
}
 
775
 
 
776
static void readv_help(void)
 
777
{
 
778
    printf(
 
779
"\n"
 
780
" reads a range of bytes from the given offset into multiple buffers\n"
 
781
"\n"
 
782
" Example:\n"
 
783
" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
 
784
"\n"
 
785
" Reads a segment of the currently open file, optionally dumping it to the\n"
 
786
" standard output stream (with -v option) for subsequent inspection.\n"
 
787
" Uses multiple iovec buffers if more than one byte range is specified.\n"
 
788
" -C, -- report statistics in a machine parsable format\n"
 
789
" -P, -- use a pattern to verify read data\n"
 
790
" -v, -- dump buffer to standard output\n"
 
791
" -q, -- quiet mode, do not show I/O statistics\n"
 
792
"\n");
 
793
}
 
794
 
 
795
static int readv_f(BlockDriverState *bs, int argc, char **argv);
 
796
 
 
797
static const cmdinfo_t readv_cmd = {
 
798
    .name       = "readv",
 
799
    .cfunc      = readv_f,
 
800
    .argmin     = 2,
 
801
    .argmax     = -1,
 
802
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
 
803
    .oneline    = "reads a number of bytes at a specified offset",
 
804
    .help       = readv_help,
 
805
};
 
806
 
 
807
static int readv_f(BlockDriverState *bs, int argc, char **argv)
 
808
{
 
809
    struct timeval t1, t2;
 
810
    int Cflag = 0, qflag = 0, vflag = 0;
 
811
    int c, cnt;
 
812
    char *buf;
 
813
    int64_t offset;
 
814
    /* Some compilers get confused and warn if this is not initialized.  */
 
815
    int total = 0;
 
816
    int nr_iov;
 
817
    QEMUIOVector qiov;
 
818
    int pattern = 0;
 
819
    int Pflag = 0;
 
820
 
 
821
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
 
822
        switch (c) {
 
823
        case 'C':
 
824
            Cflag = 1;
 
825
            break;
 
826
        case 'P':
 
827
            Pflag = 1;
 
828
            pattern = parse_pattern(optarg);
 
829
            if (pattern < 0) {
 
830
                return 0;
 
831
            }
 
832
            break;
 
833
        case 'q':
 
834
            qflag = 1;
 
835
            break;
 
836
        case 'v':
 
837
            vflag = 1;
 
838
            break;
 
839
        default:
 
840
            return qemuio_command_usage(&readv_cmd);
 
841
        }
 
842
    }
 
843
 
 
844
    if (optind > argc - 2) {
 
845
        return qemuio_command_usage(&readv_cmd);
 
846
    }
 
847
 
 
848
 
 
849
    offset = cvtnum(argv[optind]);
 
850
    if (offset < 0) {
 
851
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
852
        return 0;
 
853
    }
 
854
    optind++;
 
855
 
 
856
    if (offset & 0x1ff) {
 
857
        printf("offset %" PRId64 " is not sector aligned\n",
 
858
               offset);
 
859
        return 0;
 
860
    }
 
861
 
 
862
    nr_iov = argc - optind;
 
863
    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
 
864
    if (buf == NULL) {
 
865
        return 0;
 
866
    }
 
867
 
 
868
    gettimeofday(&t1, NULL);
 
869
    cnt = do_aio_readv(bs, &qiov, offset, &total);
 
870
    gettimeofday(&t2, NULL);
 
871
 
 
872
    if (cnt < 0) {
 
873
        printf("readv failed: %s\n", strerror(-cnt));
 
874
        goto out;
 
875
    }
 
876
 
 
877
    if (Pflag) {
 
878
        void *cmp_buf = g_malloc(qiov.size);
 
879
        memset(cmp_buf, pattern, qiov.size);
 
880
        if (memcmp(buf, cmp_buf, qiov.size)) {
 
881
            printf("Pattern verification failed at offset %"
 
882
                   PRId64 ", %zd bytes\n", offset, qiov.size);
 
883
        }
 
884
        g_free(cmp_buf);
 
885
    }
 
886
 
 
887
    if (qflag) {
 
888
        goto out;
 
889
    }
 
890
 
 
891
    if (vflag) {
 
892
        dump_buffer(buf, offset, qiov.size);
 
893
    }
 
894
 
 
895
    /* Finally, report back -- -C gives a parsable format */
 
896
    t2 = tsub(t2, t1);
 
897
    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
 
898
 
 
899
out:
 
900
    qemu_iovec_destroy(&qiov);
 
901
    qemu_io_free(buf);
 
902
    return 0;
 
903
}
 
904
 
 
905
static void write_help(void)
 
906
{
 
907
    printf(
 
908
"\n"
 
909
" writes a range of bytes from the given offset\n"
 
910
"\n"
 
911
" Example:\n"
 
912
" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
 
913
"\n"
 
914
" Writes into a segment of the currently open file, using a buffer\n"
 
915
" filled with a set pattern (0xcdcdcdcd).\n"
 
916
" -b, -- write to the VM state rather than the virtual disk\n"
 
917
" -c, -- write compressed data with bdrv_write_compressed\n"
 
918
" -p, -- use bdrv_pwrite to write the file\n"
 
919
" -P, -- use different pattern to fill file\n"
 
920
" -C, -- report statistics in a machine parsable format\n"
 
921
" -q, -- quiet mode, do not show I/O statistics\n"
 
922
" -z, -- write zeroes using bdrv_co_write_zeroes\n"
 
923
"\n");
 
924
}
 
925
 
 
926
static int write_f(BlockDriverState *bs, int argc, char **argv);
 
927
 
 
928
static const cmdinfo_t write_cmd = {
 
929
    .name       = "write",
 
930
    .altname    = "w",
 
931
    .cfunc      = write_f,
 
932
    .argmin     = 2,
 
933
    .argmax     = -1,
 
934
    .args       = "[-bcCpqz] [-P pattern ] off len",
 
935
    .oneline    = "writes a number of bytes at a specified offset",
 
936
    .help       = write_help,
 
937
};
 
938
 
 
939
static int write_f(BlockDriverState *bs, int argc, char **argv)
 
940
{
 
941
    struct timeval t1, t2;
 
942
    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
 
943
    int cflag = 0;
 
944
    int c, cnt;
 
945
    char *buf = NULL;
 
946
    int64_t offset;
 
947
    int count;
 
948
    /* Some compilers get confused and warn if this is not initialized.  */
 
949
    int total = 0;
 
950
    int pattern = 0xcd;
 
951
 
 
952
    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
 
953
        switch (c) {
 
954
        case 'b':
 
955
            bflag = 1;
 
956
            break;
 
957
        case 'c':
 
958
            cflag = 1;
 
959
            break;
 
960
        case 'C':
 
961
            Cflag = 1;
 
962
            break;
 
963
        case 'p':
 
964
            pflag = 1;
 
965
            break;
 
966
        case 'P':
 
967
            Pflag = 1;
 
968
            pattern = parse_pattern(optarg);
 
969
            if (pattern < 0) {
 
970
                return 0;
 
971
            }
 
972
            break;
 
973
        case 'q':
 
974
            qflag = 1;
 
975
            break;
 
976
        case 'z':
 
977
            zflag = 1;
 
978
            break;
 
979
        default:
 
980
            return qemuio_command_usage(&write_cmd);
 
981
        }
 
982
    }
 
983
 
 
984
    if (optind != argc - 2) {
 
985
        return qemuio_command_usage(&write_cmd);
 
986
    }
 
987
 
 
988
    if (bflag + pflag + zflag > 1) {
 
989
        printf("-b, -p, or -z cannot be specified at the same time\n");
 
990
        return 0;
 
991
    }
 
992
 
 
993
    if (zflag && Pflag) {
 
994
        printf("-z and -P cannot be specified at the same time\n");
 
995
        return 0;
 
996
    }
 
997
 
 
998
    offset = cvtnum(argv[optind]);
 
999
    if (offset < 0) {
 
1000
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
1001
        return 0;
 
1002
    }
 
1003
 
 
1004
    optind++;
 
1005
    count = cvtnum(argv[optind]);
 
1006
    if (count < 0) {
 
1007
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
1008
        return 0;
 
1009
    }
 
1010
 
 
1011
    if (!pflag) {
 
1012
        if (offset & 0x1ff) {
 
1013
            printf("offset %" PRId64 " is not sector aligned\n",
 
1014
                   offset);
 
1015
            return 0;
 
1016
        }
 
1017
 
 
1018
        if (count & 0x1ff) {
 
1019
            printf("count %d is not sector aligned\n",
 
1020
                   count);
 
1021
            return 0;
 
1022
        }
 
1023
    }
 
1024
 
 
1025
    if (!zflag) {
 
1026
        buf = qemu_io_alloc(bs, count, pattern);
 
1027
    }
 
1028
 
 
1029
    gettimeofday(&t1, NULL);
 
1030
    if (pflag) {
 
1031
        cnt = do_pwrite(bs, buf, offset, count, &total);
 
1032
    } else if (bflag) {
 
1033
        cnt = do_save_vmstate(bs, buf, offset, count, &total);
 
1034
    } else if (zflag) {
 
1035
        cnt = do_co_write_zeroes(bs, offset, count, &total);
 
1036
    } else if (cflag) {
 
1037
        cnt = do_write_compressed(bs, buf, offset, count, &total);
 
1038
    } else {
 
1039
        cnt = do_write(bs, buf, offset, count, &total);
 
1040
    }
 
1041
    gettimeofday(&t2, NULL);
 
1042
 
 
1043
    if (cnt < 0) {
 
1044
        printf("write failed: %s\n", strerror(-cnt));
 
1045
        goto out;
 
1046
    }
 
1047
 
 
1048
    if (qflag) {
 
1049
        goto out;
 
1050
    }
 
1051
 
 
1052
    /* Finally, report back -- -C gives a parsable format */
 
1053
    t2 = tsub(t2, t1);
 
1054
    print_report("wrote", &t2, offset, count, total, cnt, Cflag);
 
1055
 
 
1056
out:
 
1057
    if (!zflag) {
 
1058
        qemu_io_free(buf);
 
1059
    }
 
1060
 
 
1061
    return 0;
 
1062
}
 
1063
 
 
1064
static void
 
1065
writev_help(void)
 
1066
{
 
1067
    printf(
 
1068
"\n"
 
1069
" writes a range of bytes from the given offset source from multiple buffers\n"
 
1070
"\n"
 
1071
" Example:\n"
 
1072
" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
 
1073
"\n"
 
1074
" Writes into a segment of the currently open file, using a buffer\n"
 
1075
" filled with a set pattern (0xcdcdcdcd).\n"
 
1076
" -P, -- use different pattern to fill file\n"
 
1077
" -C, -- report statistics in a machine parsable format\n"
 
1078
" -q, -- quiet mode, do not show I/O statistics\n"
 
1079
"\n");
 
1080
}
 
1081
 
 
1082
static int writev_f(BlockDriverState *bs, int argc, char **argv);
 
1083
 
 
1084
static const cmdinfo_t writev_cmd = {
 
1085
    .name       = "writev",
 
1086
    .cfunc      = writev_f,
 
1087
    .argmin     = 2,
 
1088
    .argmax     = -1,
 
1089
    .args       = "[-Cq] [-P pattern ] off len [len..]",
 
1090
    .oneline    = "writes a number of bytes at a specified offset",
 
1091
    .help       = writev_help,
 
1092
};
 
1093
 
 
1094
static int writev_f(BlockDriverState *bs, int argc, char **argv)
 
1095
{
 
1096
    struct timeval t1, t2;
 
1097
    int Cflag = 0, qflag = 0;
 
1098
    int c, cnt;
 
1099
    char *buf;
 
1100
    int64_t offset;
 
1101
    /* Some compilers get confused and warn if this is not initialized.  */
 
1102
    int total = 0;
 
1103
    int nr_iov;
 
1104
    int pattern = 0xcd;
 
1105
    QEMUIOVector qiov;
 
1106
 
 
1107
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
 
1108
        switch (c) {
 
1109
        case 'C':
 
1110
            Cflag = 1;
 
1111
            break;
 
1112
        case 'q':
 
1113
            qflag = 1;
 
1114
            break;
 
1115
        case 'P':
 
1116
            pattern = parse_pattern(optarg);
 
1117
            if (pattern < 0) {
 
1118
                return 0;
 
1119
            }
 
1120
            break;
 
1121
        default:
 
1122
            return qemuio_command_usage(&writev_cmd);
 
1123
        }
 
1124
    }
 
1125
 
 
1126
    if (optind > argc - 2) {
 
1127
        return qemuio_command_usage(&writev_cmd);
 
1128
    }
 
1129
 
 
1130
    offset = cvtnum(argv[optind]);
 
1131
    if (offset < 0) {
 
1132
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
1133
        return 0;
 
1134
    }
 
1135
    optind++;
 
1136
 
 
1137
    if (offset & 0x1ff) {
 
1138
        printf("offset %" PRId64 " is not sector aligned\n",
 
1139
               offset);
 
1140
        return 0;
 
1141
    }
 
1142
 
 
1143
    nr_iov = argc - optind;
 
1144
    buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
 
1145
    if (buf == NULL) {
 
1146
        return 0;
 
1147
    }
 
1148
 
 
1149
    gettimeofday(&t1, NULL);
 
1150
    cnt = do_aio_writev(bs, &qiov, offset, &total);
 
1151
    gettimeofday(&t2, NULL);
 
1152
 
 
1153
    if (cnt < 0) {
 
1154
        printf("writev failed: %s\n", strerror(-cnt));
 
1155
        goto out;
 
1156
    }
 
1157
 
 
1158
    if (qflag) {
 
1159
        goto out;
 
1160
    }
 
1161
 
 
1162
    /* Finally, report back -- -C gives a parsable format */
 
1163
    t2 = tsub(t2, t1);
 
1164
    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
 
1165
out:
 
1166
    qemu_iovec_destroy(&qiov);
 
1167
    qemu_io_free(buf);
 
1168
    return 0;
 
1169
}
 
1170
 
 
1171
static void multiwrite_help(void)
 
1172
{
 
1173
    printf(
 
1174
"\n"
 
1175
" writes a range of bytes from the given offset source from multiple buffers,\n"
 
1176
" in a batch of requests that may be merged by qemu\n"
 
1177
"\n"
 
1178
" Example:\n"
 
1179
" 'multiwrite 512 1k 1k ; 4k 1k'\n"
 
1180
"  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
 
1181
"\n"
 
1182
" Writes into a segment of the currently open file, using a buffer\n"
 
1183
" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
 
1184
" by one for each request contained in the multiwrite command.\n"
 
1185
" -P, -- use different pattern to fill file\n"
 
1186
" -C, -- report statistics in a machine parsable format\n"
 
1187
" -q, -- quiet mode, do not show I/O statistics\n"
 
1188
"\n");
 
1189
}
 
1190
 
 
1191
static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
 
1192
 
 
1193
static const cmdinfo_t multiwrite_cmd = {
 
1194
    .name       = "multiwrite",
 
1195
    .cfunc      = multiwrite_f,
 
1196
    .argmin     = 2,
 
1197
    .argmax     = -1,
 
1198
    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
 
1199
    .oneline    = "issues multiple write requests at once",
 
1200
    .help       = multiwrite_help,
 
1201
};
 
1202
 
 
1203
static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
 
1204
{
 
1205
    struct timeval t1, t2;
 
1206
    int Cflag = 0, qflag = 0;
 
1207
    int c, cnt;
 
1208
    char **buf;
 
1209
    int64_t offset, first_offset = 0;
 
1210
    /* Some compilers get confused and warn if this is not initialized.  */
 
1211
    int total = 0;
 
1212
    int nr_iov;
 
1213
    int nr_reqs;
 
1214
    int pattern = 0xcd;
 
1215
    QEMUIOVector *qiovs;
 
1216
    int i;
 
1217
    BlockRequest *reqs;
 
1218
 
 
1219
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
 
1220
        switch (c) {
 
1221
        case 'C':
 
1222
            Cflag = 1;
 
1223
            break;
 
1224
        case 'q':
 
1225
            qflag = 1;
 
1226
            break;
 
1227
        case 'P':
 
1228
            pattern = parse_pattern(optarg);
 
1229
            if (pattern < 0) {
 
1230
                return 0;
 
1231
            }
 
1232
            break;
 
1233
        default:
 
1234
            return qemuio_command_usage(&writev_cmd);
 
1235
        }
 
1236
    }
 
1237
 
 
1238
    if (optind > argc - 2) {
 
1239
        return qemuio_command_usage(&writev_cmd);
 
1240
    }
 
1241
 
 
1242
    nr_reqs = 1;
 
1243
    for (i = optind; i < argc; i++) {
 
1244
        if (!strcmp(argv[i], ";")) {
 
1245
            nr_reqs++;
 
1246
        }
 
1247
    }
 
1248
 
 
1249
    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
 
1250
    buf = g_malloc0(nr_reqs * sizeof(*buf));
 
1251
    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
 
1252
 
 
1253
    for (i = 0; i < nr_reqs && optind < argc; i++) {
 
1254
        int j;
 
1255
 
 
1256
        /* Read the offset of the request */
 
1257
        offset = cvtnum(argv[optind]);
 
1258
        if (offset < 0) {
 
1259
            printf("non-numeric offset argument -- %s\n", argv[optind]);
 
1260
            goto out;
 
1261
        }
 
1262
        optind++;
 
1263
 
 
1264
        if (offset & 0x1ff) {
 
1265
            printf("offset %lld is not sector aligned\n",
 
1266
                   (long long)offset);
 
1267
            goto out;
 
1268
        }
 
1269
 
 
1270
        if (i == 0) {
 
1271
            first_offset = offset;
 
1272
        }
 
1273
 
 
1274
        /* Read lengths for qiov entries */
 
1275
        for (j = optind; j < argc; j++) {
 
1276
            if (!strcmp(argv[j], ";")) {
 
1277
                break;
 
1278
            }
 
1279
        }
 
1280
 
 
1281
        nr_iov = j - optind;
 
1282
 
 
1283
        /* Build request */
 
1284
        buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
 
1285
        if (buf[i] == NULL) {
 
1286
            goto out;
 
1287
        }
 
1288
 
 
1289
        reqs[i].qiov = &qiovs[i];
 
1290
        reqs[i].sector = offset >> 9;
 
1291
        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
 
1292
 
 
1293
        optind = j + 1;
 
1294
 
 
1295
        pattern++;
 
1296
    }
 
1297
 
 
1298
    /* If there were empty requests at the end, ignore them */
 
1299
    nr_reqs = i;
 
1300
 
 
1301
    gettimeofday(&t1, NULL);
 
1302
    cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
 
1303
    gettimeofday(&t2, NULL);
 
1304
 
 
1305
    if (cnt < 0) {
 
1306
        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
 
1307
        goto out;
 
1308
    }
 
1309
 
 
1310
    if (qflag) {
 
1311
        goto out;
 
1312
    }
 
1313
 
 
1314
    /* Finally, report back -- -C gives a parsable format */
 
1315
    t2 = tsub(t2, t1);
 
1316
    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
 
1317
out:
 
1318
    for (i = 0; i < nr_reqs; i++) {
 
1319
        qemu_io_free(buf[i]);
 
1320
        if (reqs[i].qiov != NULL) {
 
1321
            qemu_iovec_destroy(&qiovs[i]);
 
1322
        }
 
1323
    }
 
1324
    g_free(buf);
 
1325
    g_free(reqs);
 
1326
    g_free(qiovs);
 
1327
    return 0;
 
1328
}
 
1329
 
 
1330
struct aio_ctx {
 
1331
    QEMUIOVector qiov;
 
1332
    int64_t offset;
 
1333
    char *buf;
 
1334
    int qflag;
 
1335
    int vflag;
 
1336
    int Cflag;
 
1337
    int Pflag;
 
1338
    int pattern;
 
1339
    struct timeval t1;
 
1340
};
 
1341
 
 
1342
static void aio_write_done(void *opaque, int ret)
 
1343
{
 
1344
    struct aio_ctx *ctx = opaque;
 
1345
    struct timeval t2;
 
1346
 
 
1347
    gettimeofday(&t2, NULL);
 
1348
 
 
1349
 
 
1350
    if (ret < 0) {
 
1351
        printf("aio_write failed: %s\n", strerror(-ret));
 
1352
        goto out;
 
1353
    }
 
1354
 
 
1355
    if (ctx->qflag) {
 
1356
        goto out;
 
1357
    }
 
1358
 
 
1359
    /* Finally, report back -- -C gives a parsable format */
 
1360
    t2 = tsub(t2, ctx->t1);
 
1361
    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
 
1362
                 ctx->qiov.size, 1, ctx->Cflag);
 
1363
out:
 
1364
    qemu_io_free(ctx->buf);
 
1365
    qemu_iovec_destroy(&ctx->qiov);
 
1366
    g_free(ctx);
 
1367
}
 
1368
 
 
1369
static void aio_read_done(void *opaque, int ret)
 
1370
{
 
1371
    struct aio_ctx *ctx = opaque;
 
1372
    struct timeval t2;
 
1373
 
 
1374
    gettimeofday(&t2, NULL);
 
1375
 
 
1376
    if (ret < 0) {
 
1377
        printf("readv failed: %s\n", strerror(-ret));
 
1378
        goto out;
 
1379
    }
 
1380
 
 
1381
    if (ctx->Pflag) {
 
1382
        void *cmp_buf = g_malloc(ctx->qiov.size);
 
1383
 
 
1384
        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
 
1385
        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
 
1386
            printf("Pattern verification failed at offset %"
 
1387
                   PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
 
1388
        }
 
1389
        g_free(cmp_buf);
 
1390
    }
 
1391
 
 
1392
    if (ctx->qflag) {
 
1393
        goto out;
 
1394
    }
 
1395
 
 
1396
    if (ctx->vflag) {
 
1397
        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
 
1398
    }
 
1399
 
 
1400
    /* Finally, report back -- -C gives a parsable format */
 
1401
    t2 = tsub(t2, ctx->t1);
 
1402
    print_report("read", &t2, ctx->offset, ctx->qiov.size,
 
1403
                 ctx->qiov.size, 1, ctx->Cflag);
 
1404
out:
 
1405
    qemu_io_free(ctx->buf);
 
1406
    qemu_iovec_destroy(&ctx->qiov);
 
1407
    g_free(ctx);
 
1408
}
 
1409
 
 
1410
static void aio_read_help(void)
 
1411
{
 
1412
    printf(
 
1413
"\n"
 
1414
" asynchronously reads a range of bytes from the given offset\n"
 
1415
"\n"
 
1416
" Example:\n"
 
1417
" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
 
1418
"\n"
 
1419
" Reads a segment of the currently open file, optionally dumping it to the\n"
 
1420
" standard output stream (with -v option) for subsequent inspection.\n"
 
1421
" The read is performed asynchronously and the aio_flush command must be\n"
 
1422
" used to ensure all outstanding aio requests have been completed.\n"
 
1423
" -C, -- report statistics in a machine parsable format\n"
 
1424
" -P, -- use a pattern to verify read data\n"
 
1425
" -v, -- dump buffer to standard output\n"
 
1426
" -q, -- quiet mode, do not show I/O statistics\n"
 
1427
"\n");
 
1428
}
 
1429
 
 
1430
static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
 
1431
 
 
1432
static const cmdinfo_t aio_read_cmd = {
 
1433
    .name       = "aio_read",
 
1434
    .cfunc      = aio_read_f,
 
1435
    .argmin     = 2,
 
1436
    .argmax     = -1,
 
1437
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
 
1438
    .oneline    = "asynchronously reads a number of bytes",
 
1439
    .help       = aio_read_help,
 
1440
};
 
1441
 
 
1442
static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
 
1443
{
 
1444
    int nr_iov, c;
 
1445
    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
 
1446
 
 
1447
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
 
1448
        switch (c) {
 
1449
        case 'C':
 
1450
            ctx->Cflag = 1;
 
1451
            break;
 
1452
        case 'P':
 
1453
            ctx->Pflag = 1;
 
1454
            ctx->pattern = parse_pattern(optarg);
 
1455
            if (ctx->pattern < 0) {
 
1456
                g_free(ctx);
 
1457
                return 0;
 
1458
            }
 
1459
            break;
 
1460
        case 'q':
 
1461
            ctx->qflag = 1;
 
1462
            break;
 
1463
        case 'v':
 
1464
            ctx->vflag = 1;
 
1465
            break;
 
1466
        default:
 
1467
            g_free(ctx);
 
1468
            return qemuio_command_usage(&aio_read_cmd);
 
1469
        }
 
1470
    }
 
1471
 
 
1472
    if (optind > argc - 2) {
 
1473
        g_free(ctx);
 
1474
        return qemuio_command_usage(&aio_read_cmd);
 
1475
    }
 
1476
 
 
1477
    ctx->offset = cvtnum(argv[optind]);
 
1478
    if (ctx->offset < 0) {
 
1479
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
1480
        g_free(ctx);
 
1481
        return 0;
 
1482
    }
 
1483
    optind++;
 
1484
 
 
1485
    if (ctx->offset & 0x1ff) {
 
1486
        printf("offset %" PRId64 " is not sector aligned\n",
 
1487
               ctx->offset);
 
1488
        g_free(ctx);
 
1489
        return 0;
 
1490
    }
 
1491
 
 
1492
    nr_iov = argc - optind;
 
1493
    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
 
1494
    if (ctx->buf == NULL) {
 
1495
        g_free(ctx);
 
1496
        return 0;
 
1497
    }
 
1498
 
 
1499
    gettimeofday(&ctx->t1, NULL);
 
1500
    bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
 
1501
                   ctx->qiov.size >> 9, aio_read_done, ctx);
 
1502
    return 0;
 
1503
}
 
1504
 
 
1505
static void aio_write_help(void)
 
1506
{
 
1507
    printf(
 
1508
"\n"
 
1509
" asynchronously writes a range of bytes from the given offset source\n"
 
1510
" from multiple buffers\n"
 
1511
"\n"
 
1512
" Example:\n"
 
1513
" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
 
1514
"\n"
 
1515
" Writes into a segment of the currently open file, using a buffer\n"
 
1516
" filled with a set pattern (0xcdcdcdcd).\n"
 
1517
" The write is performed asynchronously and the aio_flush command must be\n"
 
1518
" used to ensure all outstanding aio requests have been completed.\n"
 
1519
" -P, -- use different pattern to fill file\n"
 
1520
" -C, -- report statistics in a machine parsable format\n"
 
1521
" -q, -- quiet mode, do not show I/O statistics\n"
 
1522
"\n");
 
1523
}
 
1524
 
 
1525
static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
 
1526
 
 
1527
static const cmdinfo_t aio_write_cmd = {
 
1528
    .name       = "aio_write",
 
1529
    .cfunc      = aio_write_f,
 
1530
    .argmin     = 2,
 
1531
    .argmax     = -1,
 
1532
    .args       = "[-Cq] [-P pattern ] off len [len..]",
 
1533
    .oneline    = "asynchronously writes a number of bytes",
 
1534
    .help       = aio_write_help,
 
1535
};
 
1536
 
 
1537
static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
 
1538
{
 
1539
    int nr_iov, c;
 
1540
    int pattern = 0xcd;
 
1541
    struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
 
1542
 
 
1543
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
 
1544
        switch (c) {
 
1545
        case 'C':
 
1546
            ctx->Cflag = 1;
 
1547
            break;
 
1548
        case 'q':
 
1549
            ctx->qflag = 1;
 
1550
            break;
 
1551
        case 'P':
 
1552
            pattern = parse_pattern(optarg);
 
1553
            if (pattern < 0) {
 
1554
                g_free(ctx);
 
1555
                return 0;
 
1556
            }
 
1557
            break;
 
1558
        default:
 
1559
            g_free(ctx);
 
1560
            return qemuio_command_usage(&aio_write_cmd);
 
1561
        }
 
1562
    }
 
1563
 
 
1564
    if (optind > argc - 2) {
 
1565
        g_free(ctx);
 
1566
        return qemuio_command_usage(&aio_write_cmd);
 
1567
    }
 
1568
 
 
1569
    ctx->offset = cvtnum(argv[optind]);
 
1570
    if (ctx->offset < 0) {
 
1571
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
1572
        g_free(ctx);
 
1573
        return 0;
 
1574
    }
 
1575
    optind++;
 
1576
 
 
1577
    if (ctx->offset & 0x1ff) {
 
1578
        printf("offset %" PRId64 " is not sector aligned\n",
 
1579
               ctx->offset);
 
1580
        g_free(ctx);
 
1581
        return 0;
 
1582
    }
 
1583
 
 
1584
    nr_iov = argc - optind;
 
1585
    ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
 
1586
    if (ctx->buf == NULL) {
 
1587
        g_free(ctx);
 
1588
        return 0;
 
1589
    }
 
1590
 
 
1591
    gettimeofday(&ctx->t1, NULL);
 
1592
    bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
 
1593
                    ctx->qiov.size >> 9, aio_write_done, ctx);
 
1594
    return 0;
 
1595
}
 
1596
 
 
1597
static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
 
1598
{
 
1599
    bdrv_drain_all();
 
1600
    return 0;
 
1601
}
 
1602
 
 
1603
static const cmdinfo_t aio_flush_cmd = {
 
1604
    .name       = "aio_flush",
 
1605
    .cfunc      = aio_flush_f,
 
1606
    .oneline    = "completes all outstanding aio requests"
 
1607
};
 
1608
 
 
1609
static int flush_f(BlockDriverState *bs, int argc, char **argv)
 
1610
{
 
1611
    bdrv_flush(bs);
 
1612
    return 0;
 
1613
}
 
1614
 
 
1615
static const cmdinfo_t flush_cmd = {
 
1616
    .name       = "flush",
 
1617
    .altname    = "f",
 
1618
    .cfunc      = flush_f,
 
1619
    .oneline    = "flush all in-core file state to disk",
 
1620
};
 
1621
 
 
1622
static int truncate_f(BlockDriverState *bs, int argc, char **argv)
 
1623
{
 
1624
    int64_t offset;
 
1625
    int ret;
 
1626
 
 
1627
    offset = cvtnum(argv[1]);
 
1628
    if (offset < 0) {
 
1629
        printf("non-numeric truncate argument -- %s\n", argv[1]);
 
1630
        return 0;
 
1631
    }
 
1632
 
 
1633
    ret = bdrv_truncate(bs, offset);
 
1634
    if (ret < 0) {
 
1635
        printf("truncate: %s\n", strerror(-ret));
 
1636
        return 0;
 
1637
    }
 
1638
 
 
1639
    return 0;
 
1640
}
 
1641
 
 
1642
static const cmdinfo_t truncate_cmd = {
 
1643
    .name       = "truncate",
 
1644
    .altname    = "t",
 
1645
    .cfunc      = truncate_f,
 
1646
    .argmin     = 1,
 
1647
    .argmax     = 1,
 
1648
    .args       = "off",
 
1649
    .oneline    = "truncates the current file at the given offset",
 
1650
};
 
1651
 
 
1652
static int length_f(BlockDriverState *bs, int argc, char **argv)
 
1653
{
 
1654
    int64_t size;
 
1655
    char s1[64];
 
1656
 
 
1657
    size = bdrv_getlength(bs);
 
1658
    if (size < 0) {
 
1659
        printf("getlength: %s\n", strerror(-size));
 
1660
        return 0;
 
1661
    }
 
1662
 
 
1663
    cvtstr(size, s1, sizeof(s1));
 
1664
    printf("%s\n", s1);
 
1665
    return 0;
 
1666
}
 
1667
 
 
1668
 
 
1669
static const cmdinfo_t length_cmd = {
 
1670
    .name   = "length",
 
1671
    .altname    = "l",
 
1672
    .cfunc      = length_f,
 
1673
    .oneline    = "gets the length of the current file",
 
1674
};
 
1675
 
 
1676
 
 
1677
static int info_f(BlockDriverState *bs, int argc, char **argv)
 
1678
{
 
1679
    BlockDriverInfo bdi;
 
1680
    char s1[64], s2[64];
 
1681
    int ret;
 
1682
 
 
1683
    if (bs->drv && bs->drv->format_name) {
 
1684
        printf("format name: %s\n", bs->drv->format_name);
 
1685
    }
 
1686
    if (bs->drv && bs->drv->protocol_name) {
 
1687
        printf("format name: %s\n", bs->drv->protocol_name);
 
1688
    }
 
1689
 
 
1690
    ret = bdrv_get_info(bs, &bdi);
 
1691
    if (ret) {
 
1692
        return 0;
 
1693
    }
 
1694
 
 
1695
    cvtstr(bdi.cluster_size, s1, sizeof(s1));
 
1696
    cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
 
1697
 
 
1698
    printf("cluster size: %s\n", s1);
 
1699
    printf("vm state offset: %s\n", s2);
 
1700
 
 
1701
    return 0;
 
1702
}
 
1703
 
 
1704
 
 
1705
 
 
1706
static const cmdinfo_t info_cmd = {
 
1707
    .name       = "info",
 
1708
    .altname    = "i",
 
1709
    .cfunc      = info_f,
 
1710
    .oneline    = "prints information about the current file",
 
1711
};
 
1712
 
 
1713
static void discard_help(void)
 
1714
{
 
1715
    printf(
 
1716
"\n"
 
1717
" discards a range of bytes from the given offset\n"
 
1718
"\n"
 
1719
" Example:\n"
 
1720
" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
 
1721
"\n"
 
1722
" Discards a segment of the currently open file.\n"
 
1723
" -C, -- report statistics in a machine parsable format\n"
 
1724
" -q, -- quiet mode, do not show I/O statistics\n"
 
1725
"\n");
 
1726
}
 
1727
 
 
1728
static int discard_f(BlockDriverState *bs, int argc, char **argv);
 
1729
 
 
1730
static const cmdinfo_t discard_cmd = {
 
1731
    .name       = "discard",
 
1732
    .altname    = "d",
 
1733
    .cfunc      = discard_f,
 
1734
    .argmin     = 2,
 
1735
    .argmax     = -1,
 
1736
    .args       = "[-Cq] off len",
 
1737
    .oneline    = "discards a number of bytes at a specified offset",
 
1738
    .help       = discard_help,
 
1739
};
 
1740
 
 
1741
static int discard_f(BlockDriverState *bs, int argc, char **argv)
 
1742
{
 
1743
    struct timeval t1, t2;
 
1744
    int Cflag = 0, qflag = 0;
 
1745
    int c, ret;
 
1746
    int64_t offset;
 
1747
    int count;
 
1748
 
 
1749
    while ((c = getopt(argc, argv, "Cq")) != EOF) {
 
1750
        switch (c) {
 
1751
        case 'C':
 
1752
            Cflag = 1;
 
1753
            break;
 
1754
        case 'q':
 
1755
            qflag = 1;
 
1756
            break;
 
1757
        default:
 
1758
            return qemuio_command_usage(&discard_cmd);
 
1759
        }
 
1760
    }
 
1761
 
 
1762
    if (optind != argc - 2) {
 
1763
        return qemuio_command_usage(&discard_cmd);
 
1764
    }
 
1765
 
 
1766
    offset = cvtnum(argv[optind]);
 
1767
    if (offset < 0) {
 
1768
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
1769
        return 0;
 
1770
    }
 
1771
 
 
1772
    optind++;
 
1773
    count = cvtnum(argv[optind]);
 
1774
    if (count < 0) {
 
1775
        printf("non-numeric length argument -- %s\n", argv[optind]);
 
1776
        return 0;
 
1777
    }
 
1778
 
 
1779
    gettimeofday(&t1, NULL);
 
1780
    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
 
1781
                       count >> BDRV_SECTOR_BITS);
 
1782
    gettimeofday(&t2, NULL);
 
1783
 
 
1784
    if (ret < 0) {
 
1785
        printf("discard failed: %s\n", strerror(-ret));
 
1786
        goto out;
 
1787
    }
 
1788
 
 
1789
    /* Finally, report back -- -C gives a parsable format */
 
1790
    if (!qflag) {
 
1791
        t2 = tsub(t2, t1);
 
1792
        print_report("discard", &t2, offset, count, count, 1, Cflag);
 
1793
    }
 
1794
 
 
1795
out:
 
1796
    return 0;
 
1797
}
 
1798
 
 
1799
static int alloc_f(BlockDriverState *bs, int argc, char **argv)
 
1800
{
 
1801
    int64_t offset, sector_num;
 
1802
    int nb_sectors, remaining;
 
1803
    char s1[64];
 
1804
    int num, sum_alloc;
 
1805
    int ret;
 
1806
 
 
1807
    offset = cvtnum(argv[1]);
 
1808
    if (offset < 0) {
 
1809
        printf("non-numeric offset argument -- %s\n", argv[1]);
 
1810
        return 0;
 
1811
    } else if (offset & 0x1ff) {
 
1812
        printf("offset %" PRId64 " is not sector aligned\n",
 
1813
               offset);
 
1814
        return 0;
 
1815
    }
 
1816
 
 
1817
    if (argc == 3) {
 
1818
        nb_sectors = cvtnum(argv[2]);
 
1819
        if (nb_sectors < 0) {
 
1820
            printf("non-numeric length argument -- %s\n", argv[2]);
 
1821
            return 0;
 
1822
        }
 
1823
    } else {
 
1824
        nb_sectors = 1;
 
1825
    }
 
1826
 
 
1827
    remaining = nb_sectors;
 
1828
    sum_alloc = 0;
 
1829
    sector_num = offset >> 9;
 
1830
    while (remaining) {
 
1831
        ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
 
1832
        if (ret < 0) {
 
1833
            printf("is_allocated failed: %s\n", strerror(-ret));
 
1834
            return 0;
 
1835
        }
 
1836
        sector_num += num;
 
1837
        remaining -= num;
 
1838
        if (ret) {
 
1839
            sum_alloc += num;
 
1840
        }
 
1841
        if (num == 0) {
 
1842
            nb_sectors -= remaining;
 
1843
            remaining = 0;
 
1844
        }
 
1845
    }
 
1846
 
 
1847
    cvtstr(offset, s1, sizeof(s1));
 
1848
 
 
1849
    printf("%d/%d sectors allocated at offset %s\n",
 
1850
           sum_alloc, nb_sectors, s1);
 
1851
    return 0;
 
1852
}
 
1853
 
 
1854
static const cmdinfo_t alloc_cmd = {
 
1855
    .name       = "alloc",
 
1856
    .altname    = "a",
 
1857
    .argmin     = 1,
 
1858
    .argmax     = 2,
 
1859
    .cfunc      = alloc_f,
 
1860
    .args       = "off [sectors]",
 
1861
    .oneline    = "checks if a sector is present in the file",
 
1862
};
 
1863
 
 
1864
 
 
1865
static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
 
1866
                            int64_t nb_sectors, int64_t *pnum)
 
1867
{
 
1868
    int num, num_checked;
 
1869
    int ret, firstret;
 
1870
 
 
1871
    num_checked = MIN(nb_sectors, INT_MAX);
 
1872
    ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
 
1873
    if (ret < 0) {
 
1874
        return ret;
 
1875
    }
 
1876
 
 
1877
    firstret = ret;
 
1878
    *pnum = num;
 
1879
 
 
1880
    while (nb_sectors > 0 && ret == firstret) {
 
1881
        sector_num += num;
 
1882
        nb_sectors -= num;
 
1883
 
 
1884
        num_checked = MIN(nb_sectors, INT_MAX);
 
1885
        ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
 
1886
        if (ret == firstret) {
 
1887
            *pnum += num;
 
1888
        } else {
 
1889
            break;
 
1890
        }
 
1891
    }
 
1892
 
 
1893
    return firstret;
 
1894
}
 
1895
 
 
1896
static int map_f(BlockDriverState *bs, int argc, char **argv)
 
1897
{
 
1898
    int64_t offset;
 
1899
    int64_t nb_sectors;
 
1900
    char s1[64];
 
1901
    int64_t num;
 
1902
    int ret;
 
1903
    const char *retstr;
 
1904
 
 
1905
    offset = 0;
 
1906
    nb_sectors = bs->total_sectors;
 
1907
 
 
1908
    do {
 
1909
        ret = map_is_allocated(bs, offset, nb_sectors, &num);
 
1910
        if (ret < 0) {
 
1911
            error_report("Failed to get allocation status: %s", strerror(-ret));
 
1912
            return 0;
 
1913
        }
 
1914
 
 
1915
        retstr = ret ? "    allocated" : "not allocated";
 
1916
        cvtstr(offset << 9ULL, s1, sizeof(s1));
 
1917
        printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
 
1918
               "at offset %s (%d)\n",
 
1919
               offset << 9ULL, num, nb_sectors, retstr, s1, ret);
 
1920
 
 
1921
        offset += num;
 
1922
        nb_sectors -= num;
 
1923
    } while (offset < bs->total_sectors);
 
1924
 
 
1925
    return 0;
 
1926
}
 
1927
 
 
1928
static const cmdinfo_t map_cmd = {
 
1929
       .name           = "map",
 
1930
       .argmin         = 0,
 
1931
       .argmax         = 0,
 
1932
       .cfunc          = map_f,
 
1933
       .args           = "",
 
1934
       .oneline        = "prints the allocated areas of a file",
 
1935
};
 
1936
 
 
1937
static int break_f(BlockDriverState *bs, int argc, char **argv)
 
1938
{
 
1939
    int ret;
 
1940
 
 
1941
    ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
 
1942
    if (ret < 0) {
 
1943
        printf("Could not set breakpoint: %s\n", strerror(-ret));
 
1944
    }
 
1945
 
 
1946
    return 0;
 
1947
}
 
1948
 
 
1949
static const cmdinfo_t break_cmd = {
 
1950
       .name           = "break",
 
1951
       .argmin         = 2,
 
1952
       .argmax         = 2,
 
1953
       .cfunc          = break_f,
 
1954
       .args           = "event tag",
 
1955
       .oneline        = "sets a breakpoint on event and tags the stopped "
 
1956
                         "request as tag",
 
1957
};
 
1958
 
 
1959
static int resume_f(BlockDriverState *bs, int argc, char **argv)
 
1960
{
 
1961
    int ret;
 
1962
 
 
1963
    ret = bdrv_debug_resume(bs, argv[1]);
 
1964
    if (ret < 0) {
 
1965
        printf("Could not resume request: %s\n", strerror(-ret));
 
1966
    }
 
1967
 
 
1968
    return 0;
 
1969
}
 
1970
 
 
1971
static const cmdinfo_t resume_cmd = {
 
1972
       .name           = "resume",
 
1973
       .argmin         = 1,
 
1974
       .argmax         = 1,
 
1975
       .cfunc          = resume_f,
 
1976
       .args           = "tag",
 
1977
       .oneline        = "resumes the request tagged as tag",
 
1978
};
 
1979
 
 
1980
static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
 
1981
{
 
1982
    while (!bdrv_debug_is_suspended(bs, argv[1])) {
 
1983
        qemu_aio_wait();
 
1984
    }
 
1985
 
 
1986
    return 0;
 
1987
}
 
1988
 
 
1989
static const cmdinfo_t wait_break_cmd = {
 
1990
       .name           = "wait_break",
 
1991
       .argmin         = 1,
 
1992
       .argmax         = 1,
 
1993
       .cfunc          = wait_break_f,
 
1994
       .args           = "tag",
 
1995
       .oneline        = "waits for the suspension of a request",
 
1996
};
 
1997
 
 
1998
static int abort_f(BlockDriverState *bs, int argc, char **argv)
 
1999
{
 
2000
    abort();
 
2001
}
 
2002
 
 
2003
static const cmdinfo_t abort_cmd = {
 
2004
       .name           = "abort",
 
2005
       .cfunc          = abort_f,
 
2006
       .flags          = CMD_NOFILE_OK,
 
2007
       .oneline        = "simulate a program crash using abort(3)",
 
2008
};
 
2009
 
 
2010
static void help_oneline(const char *cmd, const cmdinfo_t *ct)
 
2011
{
 
2012
    if (cmd) {
 
2013
        printf("%s ", cmd);
 
2014
    } else {
 
2015
        printf("%s ", ct->name);
 
2016
        if (ct->altname) {
 
2017
            printf("(or %s) ", ct->altname);
 
2018
        }
 
2019
    }
 
2020
 
 
2021
    if (ct->args) {
 
2022
        printf("%s ", ct->args);
 
2023
    }
 
2024
    printf("-- %s\n", ct->oneline);
 
2025
}
 
2026
 
 
2027
static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
 
2028
{
 
2029
    help_oneline(cmd, ct);
 
2030
    if (ct->help) {
 
2031
        ct->help();
 
2032
    }
 
2033
}
 
2034
 
 
2035
static void help_all(void)
 
2036
{
 
2037
    const cmdinfo_t *ct;
 
2038
 
 
2039
    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
 
2040
        help_oneline(ct->name, ct);
 
2041
    }
 
2042
    printf("\nUse 'help commandname' for extended help.\n");
 
2043
}
 
2044
 
 
2045
static int help_f(BlockDriverState *bs, int argc, char **argv)
 
2046
{
 
2047
    const cmdinfo_t *ct;
 
2048
 
 
2049
    if (argc == 1) {
 
2050
        help_all();
 
2051
        return 0;
 
2052
    }
 
2053
 
 
2054
    ct = find_command(argv[1]);
 
2055
    if (ct == NULL) {
 
2056
        printf("command %s not found\n", argv[1]);
 
2057
        return 0;
 
2058
    }
 
2059
 
 
2060
    help_onecmd(argv[1], ct);
 
2061
    return 0;
 
2062
}
 
2063
 
 
2064
static const cmdinfo_t help_cmd = {
 
2065
    .name       = "help",
 
2066
    .altname    = "?",
 
2067
    .cfunc      = help_f,
 
2068
    .argmin     = 0,
 
2069
    .argmax     = 1,
 
2070
    .flags      = CMD_FLAG_GLOBAL,
 
2071
    .args       = "[command]",
 
2072
    .oneline    = "help for one or all commands",
 
2073
};
 
2074
 
 
2075
bool qemuio_command(BlockDriverState *bs, const char *cmd)
 
2076
{
 
2077
    char *input;
 
2078
    const cmdinfo_t *ct;
 
2079
    char **v;
 
2080
    int c;
 
2081
    bool done = false;
 
2082
 
 
2083
    input = g_strdup(cmd);
 
2084
    v = breakline(input, &c);
 
2085
    if (c) {
 
2086
        ct = find_command(v[0]);
 
2087
        if (ct) {
 
2088
            done = command(bs, ct, c, v);
 
2089
        } else {
 
2090
            fprintf(stderr, "command \"%s\" not found\n", v[0]);
 
2091
        }
 
2092
    }
 
2093
    g_free(input);
 
2094
    g_free(v);
 
2095
 
 
2096
    return done;
 
2097
}
 
2098
 
 
2099
static void __attribute((constructor)) init_qemuio_commands(void)
 
2100
{
 
2101
    /* initialize commands */
 
2102
    qemuio_add_command(&help_cmd);
 
2103
    qemuio_add_command(&read_cmd);
 
2104
    qemuio_add_command(&readv_cmd);
 
2105
    qemuio_add_command(&write_cmd);
 
2106
    qemuio_add_command(&writev_cmd);
 
2107
    qemuio_add_command(&multiwrite_cmd);
 
2108
    qemuio_add_command(&aio_read_cmd);
 
2109
    qemuio_add_command(&aio_write_cmd);
 
2110
    qemuio_add_command(&aio_flush_cmd);
 
2111
    qemuio_add_command(&flush_cmd);
 
2112
    qemuio_add_command(&truncate_cmd);
 
2113
    qemuio_add_command(&length_cmd);
 
2114
    qemuio_add_command(&info_cmd);
 
2115
    qemuio_add_command(&discard_cmd);
 
2116
    qemuio_add_command(&alloc_cmd);
 
2117
    qemuio_add_command(&map_cmd);
 
2118
    qemuio_add_command(&break_cmd);
 
2119
    qemuio_add_command(&resume_cmd);
 
2120
    qemuio_add_command(&wait_break_cmd);
 
2121
    qemuio_add_command(&abort_cmd);
 
2122
}