]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-io-cmds.c
iotests: Test mirror-top filter permissions
[mirror_qemu.git] / qemu-io-cmds.c
CommitLineData
797ac58c
KW
1/*
2 * Command line utility to exercise the QEMU I/O path.
3 *
093ea232 4 * Copyright (C) 2009-2016 Red Hat, Inc.
797ac58c
KW
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
80c71a24 11#include "qemu/osdep.h"
da34e65c 12#include "qapi/error.h"
dc900c35 13#include "qapi/qmp/qdict.h"
3d21994f 14#include "qemu-io.h"
4c7b7e9b
HR
15#include "sysemu/block-backend.h"
16#include "block/block.h"
17#include "block/block_int.h" /* for info_f() */
a8d8ecb7 18#include "block/qapi.h"
d49b6836 19#include "qemu/error-report.h"
6a1751b7 20#include "qemu/main-loop.h"
922a01a0 21#include "qemu/option.h"
cd33d02a 22#include "qemu/timer.h"
f348b6d1 23#include "qemu/cutils.h"
797ac58c
KW
24
25#define CMD_NOFILE_OK 0x01
26
f9883880 27bool qemuio_misalign;
797ac58c 28
c2cdf5c5
KW
29static cmdinfo_t *cmdtab;
30static int ncmds;
31
32static int compare_cmdname(const void *a, const void *b)
33{
34 return strcmp(((const cmdinfo_t *)a)->name,
35 ((const cmdinfo_t *)b)->name);
36}
37
38void qemuio_add_command(const cmdinfo_t *ci)
39{
6aabeb58
PM
40 /* ci->perm assumes a file is open, but the GLOBAL and NOFILE_OK
41 * flags allow it not to be, so that combination is invalid.
42 * Catch it now rather than letting it manifest as a crash if a
43 * particular set of command line options are used.
44 */
45 assert(ci->perm == 0 ||
46 (ci->flags & (CMD_FLAG_GLOBAL | CMD_NOFILE_OK)) == 0);
02c4f26b 47 cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds);
c2cdf5c5
KW
48 cmdtab[ncmds - 1] = *ci;
49 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
50}
51
b444d0e9 52void qemuio_command_usage(const cmdinfo_t *ci)
c2cdf5c5
KW
53{
54 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
c2cdf5c5
KW
55}
56
4c7b7e9b 57static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
c2cdf5c5
KW
58{
59 if (ct->flags & CMD_FLAG_GLOBAL) {
60 return 1;
61 }
4c7b7e9b 62 if (!(ct->flags & CMD_NOFILE_OK) && !blk) {
c2cdf5c5
KW
63 fprintf(stderr, "no file open, try 'help open'\n");
64 return 0;
65 }
66 return 1;
67}
68
b32d7a39
HR
69static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
70 char **argv)
c2cdf5c5
KW
71{
72 char *cmd = argv[0];
73
4c7b7e9b 74 if (!init_check_command(blk, ct)) {
b32d7a39 75 return -EINVAL;
c2cdf5c5
KW
76 }
77
78 if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
79 if (ct->argmax == -1) {
80 fprintf(stderr,
81 "bad argument count %d to %s, expected at least %d arguments\n",
82 argc-1, cmd, ct->argmin);
83 } else if (ct->argmin == ct->argmax) {
84 fprintf(stderr,
85 "bad argument count %d to %s, expected %d arguments\n",
86 argc-1, cmd, ct->argmin);
87 } else {
88 fprintf(stderr,
89 "bad argument count %d to %s, expected between %d and %d arguments\n",
90 argc-1, cmd, ct->argmin, ct->argmax);
91 }
b32d7a39 92 return -EINVAL;
c2cdf5c5 93 }
887354bd
KW
94
95 /* Request additional permissions if necessary for this command. The caller
96 * is responsible for restoring the original permissions afterwards if this
97 * is what it wants. */
98 if (ct->perm && blk_is_available(blk)) {
99 uint64_t orig_perm, orig_shared_perm;
100 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
101
102 if (ct->perm & ~orig_perm) {
103 uint64_t new_perm;
104 Error *local_err = NULL;
105 int ret;
106
107 new_perm = orig_perm | ct->perm;
108
109 ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
110 if (ret < 0) {
111 error_report_err(local_err);
b32d7a39 112 return ret;
887354bd
KW
113 }
114 }
115 }
116
d339d766 117 qemu_reset_optind();
b32d7a39 118 return ct->cfunc(blk, argc, argv);
c2cdf5c5
KW
119}
120
121static const cmdinfo_t *find_command(const char *cmd)
122{
123 cmdinfo_t *ct;
124
125 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
126 if (strcmp(ct->name, cmd) == 0 ||
127 (ct->altname && strcmp(ct->altname, cmd) == 0))
128 {
129 return (const cmdinfo_t *)ct;
130 }
131 }
132 return NULL;
133}
134
4694020d
SH
135/* Invoke fn() for commands with a matching prefix */
136void qemuio_complete_command(const char *input,
137 void (*fn)(const char *cmd, void *opaque),
138 void *opaque)
139{
140 cmdinfo_t *ct;
141 size_t input_len = strlen(input);
142
143 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
144 if (strncmp(input, ct->name, input_len) == 0) {
145 fn(ct->name, opaque);
146 }
147 }
148}
149
c2cdf5c5
KW
150static char **breakline(char *input, int *count)
151{
152 int c = 0;
153 char *p;
5839e53b 154 char **rval = g_new0(char *, 1);
c2cdf5c5
KW
155
156 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
157 if (!*p) {
158 continue;
159 }
160 c++;
08193dd5 161 rval = g_renew(char *, rval, (c + 1));
c2cdf5c5
KW
162 rval[c - 1] = p;
163 rval[c] = NULL;
164 }
165 *count = c;
166 return rval;
167}
168
797ac58c
KW
169static int64_t cvtnum(const char *s)
170{
f17fd4fd 171 int err;
f46bfdbf 172 uint64_t value;
ef5a7885 173
f17fd4fd
MA
174 err = qemu_strtosz(s, NULL, &value);
175 if (err < 0) {
176 return err;
177 }
f46bfdbf
MA
178 if (value > INT64_MAX) {
179 return -ERANGE;
180 }
f17fd4fd 181 return value;
797ac58c
KW
182}
183
a9ecfa00
JS
184static void print_cvtnum_err(int64_t rc, const char *arg)
185{
186 switch (rc) {
187 case -EINVAL:
188 printf("Parsing error: non-numeric argument,"
189 " or extraneous/unrecognized suffix -- %s\n", arg);
190 break;
191 case -ERANGE:
192 printf("Parsing error: argument too large -- %s\n", arg);
193 break;
194 default:
195 printf("Parsing error: %s\n", arg);
196 }
197}
198
0b613881
KW
199#define EXABYTES(x) ((long long)(x) << 60)
200#define PETABYTES(x) ((long long)(x) << 50)
201#define TERABYTES(x) ((long long)(x) << 40)
202#define GIGABYTES(x) ((long long)(x) << 30)
203#define MEGABYTES(x) ((long long)(x) << 20)
204#define KILOBYTES(x) ((long long)(x) << 10)
205
206#define TO_EXABYTES(x) ((x) / EXABYTES(1))
207#define TO_PETABYTES(x) ((x) / PETABYTES(1))
208#define TO_TERABYTES(x) ((x) / TERABYTES(1))
209#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
210#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
211#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
212
213static void cvtstr(double value, char *str, size_t size)
214{
215 char *trim;
216 const char *suffix;
217
218 if (value >= EXABYTES(1)) {
219 suffix = " EiB";
220 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
221 } else if (value >= PETABYTES(1)) {
222 suffix = " PiB";
223 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
224 } else if (value >= TERABYTES(1)) {
225 suffix = " TiB";
226 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
227 } else if (value >= GIGABYTES(1)) {
228 suffix = " GiB";
229 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
230 } else if (value >= MEGABYTES(1)) {
231 suffix = " MiB";
232 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
233 } else if (value >= KILOBYTES(1)) {
234 suffix = " KiB";
235 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
236 } else {
237 suffix = " bytes";
238 snprintf(str, size - 6, "%f", value);
239 }
240
241 trim = strstr(str, ".000");
242 if (trim) {
243 strcpy(trim, suffix);
244 } else {
245 strcat(str, suffix);
246 }
247}
248
249
250
50290c00 251static struct timespec tsub(struct timespec t1, struct timespec t2)
0b613881 252{
50290c00
AB
253 t1.tv_nsec -= t2.tv_nsec;
254 if (t1.tv_nsec < 0) {
255 t1.tv_nsec += NANOSECONDS_PER_SECOND;
0b613881
KW
256 t1.tv_sec--;
257 }
258 t1.tv_sec -= t2.tv_sec;
259 return t1;
260}
261
50290c00 262static double tdiv(double value, struct timespec tv)
0b613881 263{
50290c00
AB
264 double seconds = tv.tv_sec + (tv.tv_nsec / 1e9);
265 return value / seconds;
0b613881
KW
266}
267
268#define HOURS(sec) ((sec) / (60 * 60))
269#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
270#define SECONDS(sec) ((sec) % 60)
271
272enum {
273 DEFAULT_TIME = 0x0,
274 TERSE_FIXED_TIME = 0x1,
275 VERBOSE_FIXED_TIME = 0x2,
276};
277
50290c00 278static void timestr(struct timespec *tv, char *ts, size_t size, int format)
0b613881 279{
50290c00 280 double frac_sec = tv->tv_nsec / 1e9;
0b613881
KW
281
282 if (format & TERSE_FIXED_TIME) {
283 if (!HOURS(tv->tv_sec)) {
50290c00
AB
284 snprintf(ts, size, "%u:%05.2f",
285 (unsigned int) MINUTES(tv->tv_sec),
286 SECONDS(tv->tv_sec) + frac_sec);
0b613881
KW
287 return;
288 }
289 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
290 }
291
292 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
50290c00 293 snprintf(ts, size, "%u:%02u:%05.2f",
0b613881
KW
294 (unsigned int) HOURS(tv->tv_sec),
295 (unsigned int) MINUTES(tv->tv_sec),
50290c00 296 SECONDS(tv->tv_sec) + frac_sec);
0b613881 297 } else {
50290c00 298 snprintf(ts, size, "%05.2f sec", frac_sec);
0b613881
KW
299 }
300}
301
797ac58c
KW
302/*
303 * Parse the pattern argument to various sub-commands.
304 *
305 * Because the pattern is used as an argument to memset it must evaluate
306 * to an unsigned integer that fits into a single byte.
307 */
308static int parse_pattern(const char *arg)
309{
310 char *endptr = NULL;
311 long pattern;
312
313 pattern = strtol(arg, &endptr, 0);
314 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
315 printf("%s is not a valid pattern byte\n", arg);
316 return -1;
317 }
318
319 return pattern;
320}
321
322/*
323 * Memory allocation helpers.
324 *
325 * Make sure memory is aligned by default, or purposefully misaligned if
326 * that is specified on the command line.
327 */
328
329#define MISALIGN_OFFSET 16
4c7b7e9b 330static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern)
797ac58c
KW
331{
332 void *buf;
333
334 if (qemuio_misalign) {
335 len += MISALIGN_OFFSET;
336 }
4c7b7e9b 337 buf = blk_blockalign(blk, len);
797ac58c
KW
338 memset(buf, pattern, len);
339 if (qemuio_misalign) {
340 buf += MISALIGN_OFFSET;
341 }
342 return buf;
343}
344
345static void qemu_io_free(void *p)
346{
347 if (qemuio_misalign) {
348 p -= MISALIGN_OFFSET;
349 }
350 qemu_vfree(p);
351}
352
4d731510
DP
353/*
354 * qemu_io_alloc_from_file()
355 *
356 * Allocates the buffer and populates it with the content of the given file
357 * up to @len bytes. If the file length is less than @len, then the buffer
358 * is populated with the file content cyclically.
359 *
360 * @blk - the block backend where the buffer content is going to be written to
361 * @len - the buffer length
362 * @file_name - the file to read the content from
363 *
364 * Returns: the buffer pointer on success
365 * NULL on error
366 */
367static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
368 const char *file_name)
369{
370 char *buf, *buf_origin;
371 FILE *f = fopen(file_name, "r");
372 int pattern_len;
373
374 if (!f) {
375 perror(file_name);
376 return NULL;
377 }
378
379 if (qemuio_misalign) {
380 len += MISALIGN_OFFSET;
381 }
382
383 buf_origin = buf = blk_blockalign(blk, len);
384
385 if (qemuio_misalign) {
386 buf_origin += MISALIGN_OFFSET;
387 buf += MISALIGN_OFFSET;
388 len -= MISALIGN_OFFSET;
389 }
390
391 pattern_len = fread(buf_origin, 1, len, f);
392
393 if (ferror(f)) {
394 perror(file_name);
395 goto error;
396 }
397
398 if (pattern_len == 0) {
399 fprintf(stderr, "%s: file is empty\n", file_name);
400 goto error;
401 }
402
403 fclose(f);
c8e68b43 404 f = NULL;
4d731510
DP
405
406 if (len > pattern_len) {
407 len -= pattern_len;
408 buf += pattern_len;
409
410 while (len > 0) {
411 size_t len_to_copy = MIN(pattern_len, len);
412
413 memcpy(buf, buf_origin, len_to_copy);
414
415 len -= len_to_copy;
416 buf += len_to_copy;
417 }
418 }
419
420 return buf_origin;
421
422error:
423 qemu_io_free(buf_origin);
c8e68b43
KW
424 if (f) {
425 fclose(f);
426 }
4d731510
DP
427 return NULL;
428}
429
9b0beaf3 430static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
797ac58c 431{
9b0beaf3
JS
432 uint64_t i;
433 int j;
797ac58c
KW
434 const uint8_t *p;
435
436 for (i = 0, p = buffer; i < len; i += 16) {
437 const uint8_t *s = p;
438
439 printf("%08" PRIx64 ": ", offset + i);
440 for (j = 0; j < 16 && i + j < len; j++, p++) {
441 printf("%02x ", *p);
442 }
443 printf(" ");
444 for (j = 0; j < 16 && i + j < len; j++, s++) {
445 if (isalnum(*s)) {
446 printf("%c", *s);
447 } else {
448 printf(".");
449 }
450 }
451 printf("\n");
452 }
453}
454
50290c00 455static void print_report(const char *op, struct timespec *t, int64_t offset,
dc38852a 456 int64_t count, int64_t total, int cnt, bool Cflag)
797ac58c
KW
457{
458 char s1[64], s2[64], ts[64];
459
460 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
461 if (!Cflag) {
462 cvtstr((double)total, s1, sizeof(s1));
463 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
9b0beaf3 464 printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n",
797ac58c
KW
465 op, total, count, offset);
466 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
467 s1, cnt, ts, s2, tdiv((double)cnt, *t));
468 } else {/* bytes,ops,time,bytes/sec,ops/sec */
9b0beaf3 469 printf("%"PRId64",%d,%s,%.3f,%.3f\n",
797ac58c
KW
470 total, cnt, ts,
471 tdiv((double)total, *t),
472 tdiv((double)cnt, *t));
473 }
474}
475
476/*
477 * Parse multiple length statements for vectored I/O, and construct an I/O
478 * vector matching it.
479 */
480static void *
4c7b7e9b 481create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
797ac58c
KW
482 int pattern)
483{
484 size_t *sizes = g_new0(size_t, nr_iov);
485 size_t count = 0;
486 void *buf = NULL;
487 void *p;
488 int i;
489
490 for (i = 0; i < nr_iov; i++) {
491 char *arg = argv[i];
492 int64_t len;
493
494 len = cvtnum(arg);
495 if (len < 0) {
a9ecfa00 496 print_cvtnum_err(len, arg);
797ac58c
KW
497 goto fail;
498 }
499
3026c468
AG
500 if (len > BDRV_REQUEST_MAX_BYTES) {
501 printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg,
502 (uint64_t)BDRV_REQUEST_MAX_BYTES);
503 goto fail;
504 }
505
506 if (count > BDRV_REQUEST_MAX_BYTES - len) {
507 printf("The total number of bytes exceed the maximum size %" PRIu64
508 "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES);
797ac58c
KW
509 goto fail;
510 }
511
797ac58c
KW
512 sizes[i] = len;
513 count += len;
514 }
515
516 qemu_iovec_init(qiov, nr_iov);
517
4c7b7e9b 518 buf = p = qemu_io_alloc(blk, count, pattern);
797ac58c
KW
519
520 for (i = 0; i < nr_iov; i++) {
521 qemu_iovec_add(qiov, p, sizes[i]);
522 p += sizes[i];
523 }
524
525fail:
526 g_free(sizes);
527 return buf;
528}
529
9b0beaf3 530static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
f5a5ca79 531 int64_t bytes, int64_t *total)
797ac58c 532{
f5a5ca79 533 if (bytes > INT_MAX) {
9b0beaf3
JS
534 return -ERANGE;
535 }
536
f5a5ca79 537 *total = blk_pread(blk, offset, (uint8_t *)buf, bytes);
797ac58c
KW
538 if (*total < 0) {
539 return *total;
540 }
541 return 1;
542}
543
9b0beaf3 544static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
f5a5ca79 545 int64_t bytes, int flags, int64_t *total)
797ac58c 546{
f5a5ca79 547 if (bytes > INT_MAX) {
9b0beaf3
JS
548 return -ERANGE;
549 }
550
f5a5ca79 551 *total = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
797ac58c
KW
552 if (*total < 0) {
553 return *total;
554 }
555 return 1;
556}
557
558typedef struct {
4c7b7e9b 559 BlockBackend *blk;
797ac58c 560 int64_t offset;
f5a5ca79 561 int64_t bytes;
9b0beaf3 562 int64_t *total;
770e0e0e 563 int flags;
797ac58c
KW
564 int ret;
565 bool done;
566} CoWriteZeroes;
567
d004bd52 568static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
797ac58c
KW
569{
570 CoWriteZeroes *data = opaque;
571
f5a5ca79 572 data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
d004bd52 573 data->flags);
797ac58c
KW
574 data->done = true;
575 if (data->ret < 0) {
576 *data->total = data->ret;
577 return;
578 }
579
f5a5ca79 580 *data->total = data->bytes;
797ac58c
KW
581}
582
d004bd52 583static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
f5a5ca79 584 int64_t bytes, int flags, int64_t *total)
797ac58c
KW
585{
586 Coroutine *co;
587 CoWriteZeroes data = {
4c7b7e9b 588 .blk = blk,
797ac58c 589 .offset = offset,
f5a5ca79 590 .bytes = bytes,
797ac58c 591 .total = total,
770e0e0e 592 .flags = flags,
797ac58c
KW
593 .done = false,
594 };
595
f5a5ca79 596 if (bytes > INT_MAX) {
9b0beaf3
JS
597 return -ERANGE;
598 }
599
0b8b8753 600 co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
324ec3e4 601 bdrv_coroutine_enter(blk_bs(blk), co);
797ac58c 602 while (!data.done) {
4c7b7e9b 603 aio_poll(blk_get_aio_context(blk), true);
797ac58c
KW
604 }
605 if (data.ret < 0) {
606 return data.ret;
607 } else {
608 return 1;
609 }
610}
611
4c7b7e9b 612static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
f5a5ca79 613 int64_t bytes, int64_t *total)
797ac58c
KW
614{
615 int ret;
616
41ae31e3 617 if (bytes > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3
JS
618 return -ERANGE;
619 }
620
f5a5ca79 621 ret = blk_pwrite_compressed(blk, offset, buf, bytes);
797ac58c
KW
622 if (ret < 0) {
623 return ret;
624 }
f5a5ca79 625 *total = bytes;
797ac58c
KW
626 return 1;
627}
628
4c7b7e9b 629static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset,
9b0beaf3 630 int64_t count, int64_t *total)
797ac58c 631{
9b0beaf3
JS
632 if (count > INT_MAX) {
633 return -ERANGE;
634 }
635
4c7b7e9b 636 *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count);
797ac58c
KW
637 if (*total < 0) {
638 return *total;
639 }
640 return 1;
641}
642
4c7b7e9b 643static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset,
9b0beaf3 644 int64_t count, int64_t *total)
797ac58c 645{
9b0beaf3
JS
646 if (count > INT_MAX) {
647 return -ERANGE;
648 }
649
4c7b7e9b 650 *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count);
797ac58c
KW
651 if (*total < 0) {
652 return *total;
653 }
654 return 1;
655}
656
657#define NOT_DONE 0x7fffffff
658static void aio_rw_done(void *opaque, int ret)
659{
660 *(int *)opaque = ret;
661}
662
4c7b7e9b 663static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
797ac58c
KW
664 int64_t offset, int *total)
665{
666 int async_ret = NOT_DONE;
667
7b3f9712 668 blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret);
797ac58c
KW
669 while (async_ret == NOT_DONE) {
670 main_loop_wait(false);
671 }
672
673 *total = qiov->size;
674 return async_ret < 0 ? async_ret : 1;
675}
676
4c7b7e9b 677static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
770e0e0e 678 int64_t offset, int flags, int *total)
797ac58c
KW
679{
680 int async_ret = NOT_DONE;
681
770e0e0e 682 blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret);
797ac58c
KW
683 while (async_ret == NOT_DONE) {
684 main_loop_wait(false);
685 }
686
687 *total = qiov->size;
688 return async_ret < 0 ? async_ret : 1;
689}
690
797ac58c
KW
691static void read_help(void)
692{
693 printf(
694"\n"
695" reads a range of bytes from the given offset\n"
696"\n"
697" Example:\n"
698" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
699"\n"
700" Reads a segment of the currently open file, optionally dumping it to the\n"
701" standard output stream (with -v option) for subsequent inspection.\n"
702" -b, -- read from the VM state rather than the virtual disk\n"
703" -C, -- report statistics in a machine parsable format\n"
704" -l, -- length for pattern verification (only with -P)\n"
093ea232 705" -p, -- ignored for backwards compatibility\n"
797ac58c
KW
706" -P, -- use a pattern to verify read data\n"
707" -q, -- quiet mode, do not show I/O statistics\n"
708" -s, -- start offset for pattern verification (only with -P)\n"
709" -v, -- dump buffer to standard output\n"
710"\n");
711}
712
b32d7a39 713static int read_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
714
715static const cmdinfo_t read_cmd = {
716 .name = "read",
717 .altname = "r",
718 .cfunc = read_f,
719 .argmin = 2,
720 .argmax = -1,
093ea232 721 .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len",
797ac58c
KW
722 .oneline = "reads a number of bytes at a specified offset",
723 .help = read_help,
724};
725
b32d7a39 726static int read_f(BlockBackend *blk, int argc, char **argv)
797ac58c 727{
50290c00 728 struct timespec t1, t2;
093ea232 729 bool Cflag = false, qflag = false, vflag = false;
dc38852a 730 bool Pflag = false, sflag = false, lflag = false, bflag = false;
b32d7a39 731 int c, cnt, ret;
797ac58c
KW
732 char *buf;
733 int64_t offset;
9b0beaf3 734 int64_t count;
797ac58c 735 /* Some compilers get confused and warn if this is not initialized. */
9b0beaf3
JS
736 int64_t total = 0;
737 int pattern = 0;
738 int64_t pattern_offset = 0, pattern_count = 0;
797ac58c 739
b062ad86 740 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
797ac58c
KW
741 switch (c) {
742 case 'b':
dc38852a 743 bflag = true;
797ac58c
KW
744 break;
745 case 'C':
dc38852a 746 Cflag = true;
797ac58c
KW
747 break;
748 case 'l':
dc38852a 749 lflag = true;
797ac58c
KW
750 pattern_count = cvtnum(optarg);
751 if (pattern_count < 0) {
a9ecfa00 752 print_cvtnum_err(pattern_count, optarg);
b32d7a39 753 return pattern_count;
797ac58c
KW
754 }
755 break;
756 case 'p':
093ea232 757 /* Ignored for backwards compatibility */
797ac58c
KW
758 break;
759 case 'P':
dc38852a 760 Pflag = true;
797ac58c
KW
761 pattern = parse_pattern(optarg);
762 if (pattern < 0) {
b32d7a39 763 return -EINVAL;
797ac58c
KW
764 }
765 break;
766 case 'q':
dc38852a 767 qflag = true;
797ac58c
KW
768 break;
769 case 's':
dc38852a 770 sflag = true;
797ac58c
KW
771 pattern_offset = cvtnum(optarg);
772 if (pattern_offset < 0) {
a9ecfa00 773 print_cvtnum_err(pattern_offset, optarg);
b32d7a39 774 return pattern_offset;
797ac58c
KW
775 }
776 break;
777 case 'v':
dc38852a 778 vflag = true;
797ac58c
KW
779 break;
780 default:
b444d0e9 781 qemuio_command_usage(&read_cmd);
b32d7a39 782 return -EINVAL;
797ac58c
KW
783 }
784 }
785
786 if (optind != argc - 2) {
b444d0e9 787 qemuio_command_usage(&read_cmd);
b32d7a39 788 return -EINVAL;
797ac58c
KW
789 }
790
797ac58c
KW
791 offset = cvtnum(argv[optind]);
792 if (offset < 0) {
a9ecfa00 793 print_cvtnum_err(offset, argv[optind]);
b32d7a39 794 return offset;
797ac58c
KW
795 }
796
797 optind++;
798 count = cvtnum(argv[optind]);
799 if (count < 0) {
a9ecfa00 800 print_cvtnum_err(count, argv[optind]);
b32d7a39 801 return count;
3026c468 802 } else if (count > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 803 printf("length cannot exceed %" PRIu64 ", given %s\n",
3026c468 804 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 805 return -EINVAL;
797ac58c
KW
806 }
807
808 if (!Pflag && (lflag || sflag)) {
b444d0e9 809 qemuio_command_usage(&read_cmd);
b32d7a39 810 return -EINVAL;
797ac58c
KW
811 }
812
813 if (!lflag) {
814 pattern_count = count - pattern_offset;
815 }
816
817 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
818 printf("pattern verification range exceeds end of read data\n");
b32d7a39 819 return -EINVAL;
797ac58c
KW
820 }
821
093ea232 822 if (bflag) {
1bce6b4c
EB
823 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
824 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
797ac58c 825 offset);
b32d7a39 826 return -EINVAL;
797ac58c 827 }
1bce6b4c
EB
828 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
829 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
797ac58c 830 count);
b32d7a39 831 return -EINVAL;
797ac58c
KW
832 }
833 }
834
4c7b7e9b 835 buf = qemu_io_alloc(blk, count, 0xab);
797ac58c 836
50290c00 837 clock_gettime(CLOCK_MONOTONIC, &t1);
7b3f9712 838 if (bflag) {
b32d7a39 839 ret = do_load_vmstate(blk, buf, offset, count, &total);
797ac58c 840 } else {
b32d7a39 841 ret = do_pread(blk, buf, offset, count, &total);
797ac58c 842 }
50290c00 843 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c 844
b32d7a39
HR
845 if (ret < 0) {
846 printf("read failed: %s\n", strerror(-ret));
797ac58c
KW
847 goto out;
848 }
b32d7a39
HR
849 cnt = ret;
850
851 ret = 0;
797ac58c
KW
852
853 if (Pflag) {
854 void *cmp_buf = g_malloc(pattern_count);
855 memset(cmp_buf, pattern, pattern_count);
856 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
857 printf("Pattern verification failed at offset %"
9b0beaf3 858 PRId64 ", %"PRId64" bytes\n",
797ac58c 859 offset + pattern_offset, pattern_count);
b32d7a39 860 ret = -EINVAL;
797ac58c
KW
861 }
862 g_free(cmp_buf);
863 }
864
865 if (qflag) {
866 goto out;
867 }
868
869 if (vflag) {
870 dump_buffer(buf, offset, count);
871 }
872
873 /* Finally, report back -- -C gives a parsable format */
874 t2 = tsub(t2, t1);
875 print_report("read", &t2, offset, count, total, cnt, Cflag);
876
877out:
878 qemu_io_free(buf);
b32d7a39 879 return ret;
797ac58c
KW
880}
881
882static void readv_help(void)
883{
884 printf(
885"\n"
886" reads a range of bytes from the given offset into multiple buffers\n"
887"\n"
888" Example:\n"
889" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
890"\n"
891" Reads a segment of the currently open file, optionally dumping it to the\n"
892" standard output stream (with -v option) for subsequent inspection.\n"
893" Uses multiple iovec buffers if more than one byte range is specified.\n"
894" -C, -- report statistics in a machine parsable format\n"
895" -P, -- use a pattern to verify read data\n"
896" -v, -- dump buffer to standard output\n"
897" -q, -- quiet mode, do not show I/O statistics\n"
898"\n");
899}
900
b32d7a39 901static int readv_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
902
903static const cmdinfo_t readv_cmd = {
904 .name = "readv",
905 .cfunc = readv_f,
906 .argmin = 2,
907 .argmax = -1,
093ea232 908 .args = "[-Cqv] [-P pattern] off len [len..]",
797ac58c
KW
909 .oneline = "reads a number of bytes at a specified offset",
910 .help = readv_help,
911};
912
b32d7a39 913static int readv_f(BlockBackend *blk, int argc, char **argv)
797ac58c 914{
50290c00 915 struct timespec t1, t2;
dc38852a 916 bool Cflag = false, qflag = false, vflag = false;
b32d7a39 917 int c, cnt, ret;
797ac58c
KW
918 char *buf;
919 int64_t offset;
920 /* Some compilers get confused and warn if this is not initialized. */
921 int total = 0;
922 int nr_iov;
923 QEMUIOVector qiov;
924 int pattern = 0;
dc38852a 925 bool Pflag = false;
797ac58c 926
b062ad86 927 while ((c = getopt(argc, argv, "CP:qv")) != -1) {
797ac58c
KW
928 switch (c) {
929 case 'C':
dc38852a 930 Cflag = true;
797ac58c
KW
931 break;
932 case 'P':
dc38852a 933 Pflag = true;
797ac58c
KW
934 pattern = parse_pattern(optarg);
935 if (pattern < 0) {
b32d7a39 936 return -EINVAL;
797ac58c
KW
937 }
938 break;
939 case 'q':
dc38852a 940 qflag = true;
797ac58c
KW
941 break;
942 case 'v':
dc38852a 943 vflag = true;
797ac58c
KW
944 break;
945 default:
b444d0e9 946 qemuio_command_usage(&readv_cmd);
b32d7a39 947 return -EINVAL;
797ac58c
KW
948 }
949 }
950
951 if (optind > argc - 2) {
b444d0e9 952 qemuio_command_usage(&readv_cmd);
b32d7a39 953 return -EINVAL;
797ac58c
KW
954 }
955
956
957 offset = cvtnum(argv[optind]);
958 if (offset < 0) {
a9ecfa00 959 print_cvtnum_err(offset, argv[optind]);
b32d7a39 960 return offset;
797ac58c
KW
961 }
962 optind++;
963
797ac58c 964 nr_iov = argc - optind;
4c7b7e9b 965 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
797ac58c 966 if (buf == NULL) {
b32d7a39 967 return -EINVAL;
797ac58c
KW
968 }
969
50290c00 970 clock_gettime(CLOCK_MONOTONIC, &t1);
b32d7a39 971 ret = do_aio_readv(blk, &qiov, offset, &total);
50290c00 972 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c 973
b32d7a39
HR
974 if (ret < 0) {
975 printf("readv failed: %s\n", strerror(-ret));
797ac58c
KW
976 goto out;
977 }
b32d7a39
HR
978 cnt = ret;
979
980 ret = 0;
797ac58c
KW
981
982 if (Pflag) {
983 void *cmp_buf = g_malloc(qiov.size);
984 memset(cmp_buf, pattern, qiov.size);
985 if (memcmp(buf, cmp_buf, qiov.size)) {
986 printf("Pattern verification failed at offset %"
cf67b692 987 PRId64 ", %zu bytes\n", offset, qiov.size);
b32d7a39 988 ret = -EINVAL;
797ac58c
KW
989 }
990 g_free(cmp_buf);
991 }
992
993 if (qflag) {
994 goto out;
995 }
996
997 if (vflag) {
998 dump_buffer(buf, offset, qiov.size);
999 }
1000
1001 /* Finally, report back -- -C gives a parsable format */
1002 t2 = tsub(t2, t1);
1003 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
1004
1005out:
1006 qemu_iovec_destroy(&qiov);
1007 qemu_io_free(buf);
b32d7a39 1008 return ret;
797ac58c
KW
1009}
1010
1011static void write_help(void)
1012{
1013 printf(
1014"\n"
1015" writes a range of bytes from the given offset\n"
1016"\n"
1017" Example:\n"
1018" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
1019"\n"
1020" Writes into a segment of the currently open file, using a buffer\n"
1021" filled with a set pattern (0xcdcdcdcd).\n"
1022" -b, -- write to the VM state rather than the virtual disk\n"
4c7b7e9b 1023" -c, -- write compressed data with blk_write_compressed\n"
770e0e0e 1024" -f, -- use Force Unit Access semantics\n"
c6e3f520 1025" -n, -- with -z, don't allow slow fallback\n"
093ea232 1026" -p, -- ignored for backwards compatibility\n"
797ac58c 1027" -P, -- use different pattern to fill file\n"
4d731510 1028" -s, -- use a pattern file to fill the write buffer\n"
797ac58c
KW
1029" -C, -- report statistics in a machine parsable format\n"
1030" -q, -- quiet mode, do not show I/O statistics\n"
c2e001cc 1031" -u, -- with -z, allow unmapping\n"
d004bd52 1032" -z, -- write zeroes using blk_co_pwrite_zeroes\n"
797ac58c
KW
1033"\n");
1034}
1035
b32d7a39 1036static int write_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1037
1038static const cmdinfo_t write_cmd = {
1039 .name = "write",
1040 .altname = "w",
1041 .cfunc = write_f,
887354bd 1042 .perm = BLK_PERM_WRITE,
797ac58c
KW
1043 .argmin = 2,
1044 .argmax = -1,
4d731510 1045 .args = "[-bcCfnquz] [-P pattern | -s source_file] off len",
797ac58c
KW
1046 .oneline = "writes a number of bytes at a specified offset",
1047 .help = write_help,
1048};
1049
b32d7a39 1050static int write_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1051{
50290c00 1052 struct timespec t1, t2;
093ea232 1053 bool Cflag = false, qflag = false, bflag = false;
4d731510 1054 bool Pflag = false, zflag = false, cflag = false, sflag = false;
770e0e0e 1055 int flags = 0;
b32d7a39 1056 int c, cnt, ret;
797ac58c
KW
1057 char *buf = NULL;
1058 int64_t offset;
9b0beaf3 1059 int64_t count;
797ac58c 1060 /* Some compilers get confused and warn if this is not initialized. */
9b0beaf3 1061 int64_t total = 0;
797ac58c 1062 int pattern = 0xcd;
4d731510 1063 const char *file_name = NULL;
797ac58c 1064
4d731510 1065 while ((c = getopt(argc, argv, "bcCfnpP:qs:uz")) != -1) {
797ac58c
KW
1066 switch (c) {
1067 case 'b':
dc38852a 1068 bflag = true;
797ac58c
KW
1069 break;
1070 case 'c':
dc38852a 1071 cflag = true;
797ac58c
KW
1072 break;
1073 case 'C':
dc38852a 1074 Cflag = true;
797ac58c 1075 break;
770e0e0e
EB
1076 case 'f':
1077 flags |= BDRV_REQ_FUA;
1078 break;
c6e3f520
KW
1079 case 'n':
1080 flags |= BDRV_REQ_NO_FALLBACK;
1081 break;
797ac58c 1082 case 'p':
093ea232 1083 /* Ignored for backwards compatibility */
797ac58c
KW
1084 break;
1085 case 'P':
dc38852a 1086 Pflag = true;
797ac58c
KW
1087 pattern = parse_pattern(optarg);
1088 if (pattern < 0) {
b32d7a39 1089 return -EINVAL;
797ac58c
KW
1090 }
1091 break;
1092 case 'q':
dc38852a 1093 qflag = true;
797ac58c 1094 break;
4d731510
DP
1095 case 's':
1096 sflag = true;
1097 file_name = optarg;
1098 break;
c2e001cc
EB
1099 case 'u':
1100 flags |= BDRV_REQ_MAY_UNMAP;
1101 break;
797ac58c 1102 case 'z':
dc38852a 1103 zflag = true;
797ac58c
KW
1104 break;
1105 default:
b444d0e9 1106 qemuio_command_usage(&write_cmd);
b32d7a39 1107 return -EINVAL;
797ac58c
KW
1108 }
1109 }
1110
1111 if (optind != argc - 2) {
b444d0e9 1112 qemuio_command_usage(&write_cmd);
b32d7a39 1113 return -EINVAL;
797ac58c
KW
1114 }
1115
093ea232
EB
1116 if (bflag && zflag) {
1117 printf("-b and -z cannot be specified at the same time\n");
b32d7a39 1118 return -EINVAL;
797ac58c
KW
1119 }
1120
770e0e0e
EB
1121 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
1122 printf("-f and -b or -c cannot be specified at the same time\n");
b32d7a39 1123 return -EINVAL;
770e0e0e
EB
1124 }
1125
c6e3f520
KW
1126 if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
1127 printf("-n requires -z to be specified\n");
1128 return -EINVAL;
1129 }
1130
c2e001cc
EB
1131 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
1132 printf("-u requires -z to be specified\n");
b32d7a39 1133 return -EINVAL;
c2e001cc
EB
1134 }
1135
4d731510
DP
1136 if (zflag + Pflag + sflag > 1) {
1137 printf("Only one of -z, -P, and -s "
1138 "can be specified at the same time\n");
b32d7a39 1139 return -EINVAL;
797ac58c
KW
1140 }
1141
1142 offset = cvtnum(argv[optind]);
1143 if (offset < 0) {
a9ecfa00 1144 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1145 return offset;
797ac58c
KW
1146 }
1147
1148 optind++;
1149 count = cvtnum(argv[optind]);
1150 if (count < 0) {
a9ecfa00 1151 print_cvtnum_err(count, argv[optind]);
b32d7a39 1152 return count;
3026c468 1153 } else if (count > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 1154 printf("length cannot exceed %" PRIu64 ", given %s\n",
3026c468 1155 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 1156 return -EINVAL;
797ac58c
KW
1157 }
1158
093ea232 1159 if (bflag || cflag) {
1bce6b4c
EB
1160 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
1161 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
797ac58c 1162 offset);
b32d7a39 1163 return -EINVAL;
797ac58c
KW
1164 }
1165
1bce6b4c
EB
1166 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
1167 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
797ac58c 1168 count);
b32d7a39 1169 return -EINVAL;
797ac58c
KW
1170 }
1171 }
1172
1173 if (!zflag) {
4d731510
DP
1174 if (sflag) {
1175 buf = qemu_io_alloc_from_file(blk, count, file_name);
1176 if (!buf) {
1177 return -EINVAL;
1178 }
1179 } else {
1180 buf = qemu_io_alloc(blk, count, pattern);
1181 }
797ac58c
KW
1182 }
1183
50290c00 1184 clock_gettime(CLOCK_MONOTONIC, &t1);
7b3f9712 1185 if (bflag) {
b32d7a39 1186 ret = do_save_vmstate(blk, buf, offset, count, &total);
797ac58c 1187 } else if (zflag) {
b32d7a39 1188 ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
797ac58c 1189 } else if (cflag) {
b32d7a39 1190 ret = do_write_compressed(blk, buf, offset, count, &total);
797ac58c 1191 } else {
b32d7a39 1192 ret = do_pwrite(blk, buf, offset, count, flags, &total);
797ac58c 1193 }
50290c00 1194 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c 1195
b32d7a39
HR
1196 if (ret < 0) {
1197 printf("write failed: %s\n", strerror(-ret));
797ac58c
KW
1198 goto out;
1199 }
b32d7a39
HR
1200 cnt = ret;
1201
1202 ret = 0;
797ac58c
KW
1203
1204 if (qflag) {
1205 goto out;
1206 }
1207
1208 /* Finally, report back -- -C gives a parsable format */
1209 t2 = tsub(t2, t1);
1210 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1211
1212out:
1213 if (!zflag) {
1214 qemu_io_free(buf);
1215 }
b32d7a39 1216 return ret;
797ac58c
KW
1217}
1218
1219static void
1220writev_help(void)
1221{
1222 printf(
1223"\n"
1224" writes a range of bytes from the given offset source from multiple buffers\n"
1225"\n"
1226" Example:\n"
6e6507c0 1227" 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
797ac58c
KW
1228"\n"
1229" Writes into a segment of the currently open file, using a buffer\n"
1230" filled with a set pattern (0xcdcdcdcd).\n"
1231" -P, -- use different pattern to fill file\n"
1232" -C, -- report statistics in a machine parsable format\n"
770e0e0e 1233" -f, -- use Force Unit Access semantics\n"
797ac58c
KW
1234" -q, -- quiet mode, do not show I/O statistics\n"
1235"\n");
1236}
1237
b32d7a39 1238static int writev_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1239
1240static const cmdinfo_t writev_cmd = {
1241 .name = "writev",
1242 .cfunc = writev_f,
887354bd 1243 .perm = BLK_PERM_WRITE,
797ac58c
KW
1244 .argmin = 2,
1245 .argmax = -1,
770e0e0e 1246 .args = "[-Cfq] [-P pattern] off len [len..]",
797ac58c
KW
1247 .oneline = "writes a number of bytes at a specified offset",
1248 .help = writev_help,
1249};
1250
b32d7a39 1251static int writev_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1252{
50290c00 1253 struct timespec t1, t2;
dc38852a 1254 bool Cflag = false, qflag = false;
770e0e0e 1255 int flags = 0;
b32d7a39 1256 int c, cnt, ret;
797ac58c
KW
1257 char *buf;
1258 int64_t offset;
1259 /* Some compilers get confused and warn if this is not initialized. */
1260 int total = 0;
1261 int nr_iov;
1262 int pattern = 0xcd;
1263 QEMUIOVector qiov;
1264
4ca1d340 1265 while ((c = getopt(argc, argv, "CfqP:")) != -1) {
797ac58c
KW
1266 switch (c) {
1267 case 'C':
dc38852a 1268 Cflag = true;
797ac58c 1269 break;
770e0e0e
EB
1270 case 'f':
1271 flags |= BDRV_REQ_FUA;
1272 break;
797ac58c 1273 case 'q':
dc38852a 1274 qflag = true;
797ac58c
KW
1275 break;
1276 case 'P':
1277 pattern = parse_pattern(optarg);
1278 if (pattern < 0) {
b32d7a39 1279 return -EINVAL;
797ac58c
KW
1280 }
1281 break;
1282 default:
b444d0e9 1283 qemuio_command_usage(&writev_cmd);
b32d7a39 1284 return -EINVAL;
797ac58c
KW
1285 }
1286 }
1287
1288 if (optind > argc - 2) {
b444d0e9 1289 qemuio_command_usage(&writev_cmd);
b32d7a39 1290 return -EINVAL;
797ac58c
KW
1291 }
1292
1293 offset = cvtnum(argv[optind]);
1294 if (offset < 0) {
a9ecfa00 1295 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1296 return offset;
797ac58c
KW
1297 }
1298 optind++;
1299
797ac58c 1300 nr_iov = argc - optind;
4c7b7e9b 1301 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
797ac58c 1302 if (buf == NULL) {
b32d7a39 1303 return -EINVAL;
797ac58c
KW
1304 }
1305
50290c00 1306 clock_gettime(CLOCK_MONOTONIC, &t1);
b32d7a39 1307 ret = do_aio_writev(blk, &qiov, offset, flags, &total);
50290c00 1308 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c 1309
b32d7a39
HR
1310 if (ret < 0) {
1311 printf("writev failed: %s\n", strerror(-ret));
797ac58c
KW
1312 goto out;
1313 }
b32d7a39
HR
1314 cnt = ret;
1315
1316 ret = 0;
797ac58c
KW
1317
1318 if (qflag) {
1319 goto out;
1320 }
1321
1322 /* Finally, report back -- -C gives a parsable format */
1323 t2 = tsub(t2, t1);
1324 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1325out:
1326 qemu_iovec_destroy(&qiov);
1327 qemu_io_free(buf);
b32d7a39 1328 return ret;
797ac58c
KW
1329}
1330
797ac58c 1331struct aio_ctx {
4c7b7e9b 1332 BlockBackend *blk;
797ac58c
KW
1333 QEMUIOVector qiov;
1334 int64_t offset;
1335 char *buf;
dc38852a
EB
1336 bool qflag;
1337 bool vflag;
1338 bool Cflag;
1339 bool Pflag;
1340 bool zflag;
a91f9584 1341 BlockAcctCookie acct;
797ac58c 1342 int pattern;
50290c00 1343 struct timespec t1;
797ac58c
KW
1344};
1345
1346static void aio_write_done(void *opaque, int ret)
1347{
1348 struct aio_ctx *ctx = opaque;
50290c00 1349 struct timespec t2;
797ac58c 1350
50290c00 1351 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c
KW
1352
1353
1354 if (ret < 0) {
1355 printf("aio_write failed: %s\n", strerror(-ret));
556c2b60 1356 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
797ac58c
KW
1357 goto out;
1358 }
1359
4c7b7e9b 1360 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
a91f9584 1361
797ac58c
KW
1362 if (ctx->qflag) {
1363 goto out;
1364 }
1365
1366 /* Finally, report back -- -C gives a parsable format */
1367 t2 = tsub(t2, ctx->t1);
1368 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1369 ctx->qiov.size, 1, ctx->Cflag);
1370out:
5ceb7765
KW
1371 if (!ctx->zflag) {
1372 qemu_io_free(ctx->buf);
1373 qemu_iovec_destroy(&ctx->qiov);
1374 }
797ac58c
KW
1375 g_free(ctx);
1376}
1377
1378static void aio_read_done(void *opaque, int ret)
1379{
1380 struct aio_ctx *ctx = opaque;
50290c00 1381 struct timespec t2;
797ac58c 1382
50290c00 1383 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c
KW
1384
1385 if (ret < 0) {
1386 printf("readv failed: %s\n", strerror(-ret));
556c2b60 1387 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
797ac58c
KW
1388 goto out;
1389 }
1390
1391 if (ctx->Pflag) {
1392 void *cmp_buf = g_malloc(ctx->qiov.size);
1393
1394 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1395 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1396 printf("Pattern verification failed at offset %"
cf67b692 1397 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
797ac58c
KW
1398 }
1399 g_free(cmp_buf);
1400 }
1401
4c7b7e9b 1402 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
a91f9584 1403
797ac58c
KW
1404 if (ctx->qflag) {
1405 goto out;
1406 }
1407
1408 if (ctx->vflag) {
1409 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1410 }
1411
1412 /* Finally, report back -- -C gives a parsable format */
1413 t2 = tsub(t2, ctx->t1);
1414 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1415 ctx->qiov.size, 1, ctx->Cflag);
1416out:
1417 qemu_io_free(ctx->buf);
1418 qemu_iovec_destroy(&ctx->qiov);
1419 g_free(ctx);
1420}
1421
1422static void aio_read_help(void)
1423{
1424 printf(
1425"\n"
1426" asynchronously reads a range of bytes from the given offset\n"
1427"\n"
1428" Example:\n"
1429" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1430"\n"
1431" Reads a segment of the currently open file, optionally dumping it to the\n"
1432" standard output stream (with -v option) for subsequent inspection.\n"
1433" The read is performed asynchronously and the aio_flush command must be\n"
1434" used to ensure all outstanding aio requests have been completed.\n"
b32d7a39
HR
1435" Note that due to its asynchronous nature, this command will be\n"
1436" considered successful once the request is submitted, independently\n"
1437" of potential I/O errors or pattern mismatches.\n"
797ac58c
KW
1438" -C, -- report statistics in a machine parsable format\n"
1439" -P, -- use a pattern to verify read data\n"
37546ff2 1440" -i, -- treat request as invalid, for exercising stats\n"
797ac58c
KW
1441" -v, -- dump buffer to standard output\n"
1442" -q, -- quiet mode, do not show I/O statistics\n"
1443"\n");
1444}
1445
b32d7a39 1446static int aio_read_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1447
1448static const cmdinfo_t aio_read_cmd = {
1449 .name = "aio_read",
1450 .cfunc = aio_read_f,
1451 .argmin = 2,
1452 .argmax = -1,
37546ff2 1453 .args = "[-Ciqv] [-P pattern] off len [len..]",
797ac58c
KW
1454 .oneline = "asynchronously reads a number of bytes",
1455 .help = aio_read_help,
1456};
1457
b32d7a39 1458static int aio_read_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1459{
1460 int nr_iov, c;
1461 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1462
4c7b7e9b 1463 ctx->blk = blk;
37546ff2 1464 while ((c = getopt(argc, argv, "CP:iqv")) != -1) {
797ac58c
KW
1465 switch (c) {
1466 case 'C':
dc38852a 1467 ctx->Cflag = true;
797ac58c
KW
1468 break;
1469 case 'P':
dc38852a 1470 ctx->Pflag = true;
797ac58c
KW
1471 ctx->pattern = parse_pattern(optarg);
1472 if (ctx->pattern < 0) {
1473 g_free(ctx);
b32d7a39 1474 return -EINVAL;
797ac58c
KW
1475 }
1476 break;
37546ff2
EB
1477 case 'i':
1478 printf("injecting invalid read request\n");
1479 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1480 g_free(ctx);
b32d7a39 1481 return 0;
797ac58c 1482 case 'q':
dc38852a 1483 ctx->qflag = true;
797ac58c
KW
1484 break;
1485 case 'v':
dc38852a 1486 ctx->vflag = true;
797ac58c
KW
1487 break;
1488 default:
1489 g_free(ctx);
b444d0e9 1490 qemuio_command_usage(&aio_read_cmd);
b32d7a39 1491 return -EINVAL;
797ac58c
KW
1492 }
1493 }
1494
1495 if (optind > argc - 2) {
1496 g_free(ctx);
b444d0e9 1497 qemuio_command_usage(&aio_read_cmd);
b32d7a39 1498 return -EINVAL;
797ac58c
KW
1499 }
1500
1501 ctx->offset = cvtnum(argv[optind]);
1502 if (ctx->offset < 0) {
b32d7a39
HR
1503 int ret = ctx->offset;
1504 print_cvtnum_err(ret, argv[optind]);
797ac58c 1505 g_free(ctx);
b32d7a39 1506 return ret;
797ac58c
KW
1507 }
1508 optind++;
1509
797ac58c 1510 nr_iov = argc - optind;
4c7b7e9b 1511 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
797ac58c 1512 if (ctx->buf == NULL) {
556c2b60 1513 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
797ac58c 1514 g_free(ctx);
b32d7a39 1515 return -EINVAL;
797ac58c
KW
1516 }
1517
50290c00 1518 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
4c7b7e9b
HR
1519 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1520 BLOCK_ACCT_READ);
7b3f9712 1521 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
b32d7a39 1522 return 0;
797ac58c
KW
1523}
1524
1525static void aio_write_help(void)
1526{
1527 printf(
1528"\n"
1529" asynchronously writes a range of bytes from the given offset source\n"
1530" from multiple buffers\n"
1531"\n"
1532" Example:\n"
1533" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1534"\n"
1535" Writes into a segment of the currently open file, using a buffer\n"
1536" filled with a set pattern (0xcdcdcdcd).\n"
1537" The write is performed asynchronously and the aio_flush command must be\n"
1538" used to ensure all outstanding aio requests have been completed.\n"
b32d7a39
HR
1539" Note that due to its asynchronous nature, this command will be\n"
1540" considered successful once the request is submitted, independently\n"
1541" of potential I/O errors or pattern mismatches.\n"
797ac58c
KW
1542" -P, -- use different pattern to fill file\n"
1543" -C, -- report statistics in a machine parsable format\n"
770e0e0e 1544" -f, -- use Force Unit Access semantics\n"
37546ff2 1545" -i, -- treat request as invalid, for exercising stats\n"
797ac58c 1546" -q, -- quiet mode, do not show I/O statistics\n"
c2e001cc 1547" -u, -- with -z, allow unmapping\n"
d004bd52 1548" -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
797ac58c
KW
1549"\n");
1550}
1551
b32d7a39 1552static int aio_write_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1553
1554static const cmdinfo_t aio_write_cmd = {
1555 .name = "aio_write",
1556 .cfunc = aio_write_f,
887354bd 1557 .perm = BLK_PERM_WRITE,
797ac58c
KW
1558 .argmin = 2,
1559 .argmax = -1,
37546ff2 1560 .args = "[-Cfiquz] [-P pattern] off len [len..]",
797ac58c
KW
1561 .oneline = "asynchronously writes a number of bytes",
1562 .help = aio_write_help,
1563};
1564
b32d7a39 1565static int aio_write_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1566{
1567 int nr_iov, c;
1568 int pattern = 0xcd;
1569 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
770e0e0e 1570 int flags = 0;
797ac58c 1571
4c7b7e9b 1572 ctx->blk = blk;
37546ff2 1573 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
797ac58c
KW
1574 switch (c) {
1575 case 'C':
dc38852a 1576 ctx->Cflag = true;
797ac58c 1577 break;
770e0e0e
EB
1578 case 'f':
1579 flags |= BDRV_REQ_FUA;
1580 break;
797ac58c 1581 case 'q':
dc38852a 1582 ctx->qflag = true;
797ac58c 1583 break;
c2e001cc
EB
1584 case 'u':
1585 flags |= BDRV_REQ_MAY_UNMAP;
1586 break;
797ac58c
KW
1587 case 'P':
1588 pattern = parse_pattern(optarg);
1589 if (pattern < 0) {
1590 g_free(ctx);
b32d7a39 1591 return -EINVAL;
797ac58c
KW
1592 }
1593 break;
37546ff2
EB
1594 case 'i':
1595 printf("injecting invalid write request\n");
1596 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1597 g_free(ctx);
b32d7a39 1598 return 0;
5ceb7765 1599 case 'z':
dc38852a 1600 ctx->zflag = true;
5ceb7765 1601 break;
797ac58c
KW
1602 default:
1603 g_free(ctx);
b444d0e9 1604 qemuio_command_usage(&aio_write_cmd);
b32d7a39 1605 return -EINVAL;
797ac58c
KW
1606 }
1607 }
1608
1609 if (optind > argc - 2) {
1610 g_free(ctx);
b444d0e9 1611 qemuio_command_usage(&aio_write_cmd);
b32d7a39 1612 return -EINVAL;
797ac58c
KW
1613 }
1614
5ceb7765
KW
1615 if (ctx->zflag && optind != argc - 2) {
1616 printf("-z supports only a single length parameter\n");
1617 g_free(ctx);
b32d7a39 1618 return -EINVAL;
5ceb7765
KW
1619 }
1620
c2e001cc
EB
1621 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
1622 printf("-u requires -z to be specified\n");
4ca1d340 1623 g_free(ctx);
b32d7a39 1624 return -EINVAL;
c2e001cc
EB
1625 }
1626
5ceb7765
KW
1627 if (ctx->zflag && ctx->Pflag) {
1628 printf("-z and -P cannot be specified at the same time\n");
1629 g_free(ctx);
b32d7a39 1630 return -EINVAL;
5ceb7765
KW
1631 }
1632
797ac58c
KW
1633 ctx->offset = cvtnum(argv[optind]);
1634 if (ctx->offset < 0) {
b32d7a39
HR
1635 int ret = ctx->offset;
1636 print_cvtnum_err(ret, argv[optind]);
797ac58c 1637 g_free(ctx);
b32d7a39 1638 return ret;
797ac58c
KW
1639 }
1640 optind++;
1641
5ceb7765
KW
1642 if (ctx->zflag) {
1643 int64_t count = cvtnum(argv[optind]);
1644 if (count < 0) {
1645 print_cvtnum_err(count, argv[optind]);
0e01b76e 1646 g_free(ctx);
b32d7a39 1647 return count;
5ceb7765 1648 }
797ac58c 1649
5ceb7765 1650 ctx->qiov.size = count;
d004bd52
EB
1651 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done,
1652 ctx);
5ceb7765
KW
1653 } else {
1654 nr_iov = argc - optind;
1655 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
1656 pattern);
1657 if (ctx->buf == NULL) {
1658 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1659 g_free(ctx);
b32d7a39 1660 return -EINVAL;
5ceb7765
KW
1661 }
1662
50290c00 1663 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
5ceb7765
KW
1664 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1665 BLOCK_ACCT_WRITE);
1666
770e0e0e
EB
1667 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
1668 ctx);
5ceb7765 1669 }
b32d7a39
HR
1670
1671 return 0;
797ac58c
KW
1672}
1673
b32d7a39 1674static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1675{
556c2b60
AG
1676 BlockAcctCookie cookie;
1677 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
4c7b7e9b 1678 blk_drain_all();
556c2b60 1679 block_acct_done(blk_get_stats(blk), &cookie);
b32d7a39 1680 return 0;
797ac58c
KW
1681}
1682
1683static const cmdinfo_t aio_flush_cmd = {
1684 .name = "aio_flush",
1685 .cfunc = aio_flush_f,
1686 .oneline = "completes all outstanding aio requests"
1687};
1688
b32d7a39 1689static int flush_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1690{
b32d7a39 1691 return blk_flush(blk);
797ac58c
KW
1692}
1693
1694static const cmdinfo_t flush_cmd = {
1695 .name = "flush",
1696 .altname = "f",
1697 .cfunc = flush_f,
1698 .oneline = "flush all in-core file state to disk",
1699};
1700
42ba0225
VSO
1701static int truncate_f(BlockBackend *blk, int argc, char **argv);
1702static const cmdinfo_t truncate_cmd = {
1703 .name = "truncate",
1704 .altname = "t",
1705 .cfunc = truncate_f,
1706 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
1707 .argmin = 1,
1708 .argmax = 3,
1709 .args = "[-m prealloc_mode] off",
1710 .oneline = "truncates the current file at the given offset",
1711};
1712
b32d7a39 1713static int truncate_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1714{
ed3d2ec9 1715 Error *local_err = NULL;
797ac58c 1716 int64_t offset;
42ba0225
VSO
1717 int c, ret;
1718 PreallocMode prealloc = PREALLOC_MODE_OFF;
797ac58c 1719
42ba0225
VSO
1720 while ((c = getopt(argc, argv, "m:")) != -1) {
1721 switch (c) {
1722 case 'm':
1723 prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
1724 PREALLOC_MODE__MAX, NULL);
1725 if (prealloc == PREALLOC_MODE__MAX) {
1726 error_report("Invalid preallocation mode '%s'", optarg);
1727 return -EINVAL;
1728 }
1729 break;
1730 default:
1731 qemuio_command_usage(&truncate_cmd);
1732 return -EINVAL;
1733 }
1734 }
1735
1736 offset = cvtnum(argv[optind]);
797ac58c 1737 if (offset < 0) {
a9ecfa00 1738 print_cvtnum_err(offset, argv[1]);
b32d7a39 1739 return offset;
797ac58c
KW
1740 }
1741
e8d04f92
HR
1742 /*
1743 * qemu-io is a debugging tool, so let us be strict here and pass
1744 * exact=true. It is better to err on the "emit more errors" side
1745 * than to be overly permissive.
1746 */
42ba0225 1747 ret = blk_truncate(blk, offset, false, prealloc, 0, &local_err);
797ac58c 1748 if (ret < 0) {
ed3d2ec9 1749 error_report_err(local_err);
b32d7a39 1750 return ret;
797ac58c 1751 }
b32d7a39
HR
1752
1753 return 0;
797ac58c
KW
1754}
1755
b32d7a39 1756static int length_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1757{
1758 int64_t size;
1759 char s1[64];
1760
4c7b7e9b 1761 size = blk_getlength(blk);
797ac58c
KW
1762 if (size < 0) {
1763 printf("getlength: %s\n", strerror(-size));
b32d7a39 1764 return size;
797ac58c
KW
1765 }
1766
1767 cvtstr(size, s1, sizeof(s1));
1768 printf("%s\n", s1);
b32d7a39 1769 return 0;
797ac58c
KW
1770}
1771
1772
1773static const cmdinfo_t length_cmd = {
1774 .name = "length",
1775 .altname = "l",
1776 .cfunc = length_f,
1777 .oneline = "gets the length of the current file",
1778};
1779
1780
b32d7a39 1781static int info_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1782{
4c7b7e9b 1783 BlockDriverState *bs = blk_bs(blk);
797ac58c 1784 BlockDriverInfo bdi;
a8d8ecb7 1785 ImageInfoSpecific *spec_info;
1bf6e9ca 1786 Error *local_err = NULL;
797ac58c
KW
1787 char s1[64], s2[64];
1788 int ret;
1789
1790 if (bs->drv && bs->drv->format_name) {
1791 printf("format name: %s\n", bs->drv->format_name);
1792 }
1793 if (bs->drv && bs->drv->protocol_name) {
1794 printf("format name: %s\n", bs->drv->protocol_name);
1795 }
1796
1797 ret = bdrv_get_info(bs, &bdi);
1798 if (ret) {
b32d7a39 1799 return ret;
797ac58c
KW
1800 }
1801
1802 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1803 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1804
1805 printf("cluster size: %s\n", s1);
1806 printf("vm state offset: %s\n", s2);
1807
1bf6e9ca
AS
1808 spec_info = bdrv_get_specific_info(bs, &local_err);
1809 if (local_err) {
1810 error_report_err(local_err);
1811 return -EIO;
1812 }
a8d8ecb7
HR
1813 if (spec_info) {
1814 printf("Format specific information:\n");
e1ce7d74 1815 bdrv_image_info_specific_dump(spec_info);
a8d8ecb7
HR
1816 qapi_free_ImageInfoSpecific(spec_info);
1817 }
b32d7a39
HR
1818
1819 return 0;
797ac58c
KW
1820}
1821
1822
1823
1824static const cmdinfo_t info_cmd = {
1825 .name = "info",
1826 .altname = "i",
1827 .cfunc = info_f,
1828 .oneline = "prints information about the current file",
1829};
1830
1831static void discard_help(void)
1832{
1833 printf(
1834"\n"
1835" discards a range of bytes from the given offset\n"
1836"\n"
1837" Example:\n"
1838" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1839"\n"
1840" Discards a segment of the currently open file.\n"
1841" -C, -- report statistics in a machine parsable format\n"
1842" -q, -- quiet mode, do not show I/O statistics\n"
1843"\n");
1844}
1845
b32d7a39 1846static int discard_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1847
1848static const cmdinfo_t discard_cmd = {
1849 .name = "discard",
1850 .altname = "d",
1851 .cfunc = discard_f,
887354bd 1852 .perm = BLK_PERM_WRITE,
797ac58c
KW
1853 .argmin = 2,
1854 .argmax = -1,
1855 .args = "[-Cq] off len",
1856 .oneline = "discards a number of bytes at a specified offset",
1857 .help = discard_help,
1858};
1859
b32d7a39 1860static int discard_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1861{
50290c00 1862 struct timespec t1, t2;
dc38852a 1863 bool Cflag = false, qflag = false;
797ac58c 1864 int c, ret;
f5a5ca79 1865 int64_t offset, bytes;
797ac58c 1866
b062ad86 1867 while ((c = getopt(argc, argv, "Cq")) != -1) {
797ac58c
KW
1868 switch (c) {
1869 case 'C':
dc38852a 1870 Cflag = true;
797ac58c
KW
1871 break;
1872 case 'q':
dc38852a 1873 qflag = true;
797ac58c
KW
1874 break;
1875 default:
b444d0e9 1876 qemuio_command_usage(&discard_cmd);
b32d7a39 1877 return -EINVAL;
797ac58c
KW
1878 }
1879 }
1880
1881 if (optind != argc - 2) {
b444d0e9 1882 qemuio_command_usage(&discard_cmd);
b32d7a39 1883 return -EINVAL;
797ac58c
KW
1884 }
1885
1886 offset = cvtnum(argv[optind]);
1887 if (offset < 0) {
a9ecfa00 1888 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1889 return offset;
797ac58c
KW
1890 }
1891
1892 optind++;
f5a5ca79
MP
1893 bytes = cvtnum(argv[optind]);
1894 if (bytes < 0) {
1895 print_cvtnum_err(bytes, argv[optind]);
b32d7a39 1896 return bytes;
41ae31e3 1897 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 1898 printf("length cannot exceed %"PRIu64", given %s\n",
41ae31e3 1899 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 1900 return -EINVAL;
797ac58c
KW
1901 }
1902
50290c00 1903 clock_gettime(CLOCK_MONOTONIC, &t1);
f5a5ca79 1904 ret = blk_pdiscard(blk, offset, bytes);
50290c00 1905 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c
KW
1906
1907 if (ret < 0) {
1908 printf("discard failed: %s\n", strerror(-ret));
b32d7a39 1909 return ret;
797ac58c
KW
1910 }
1911
1912 /* Finally, report back -- -C gives a parsable format */
1913 if (!qflag) {
1914 t2 = tsub(t2, t1);
f5a5ca79 1915 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
797ac58c 1916 }
b32d7a39
HR
1917
1918 return 0;
797ac58c
KW
1919}
1920
b32d7a39 1921static int alloc_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1922{
4c7b7e9b 1923 BlockDriverState *bs = blk_bs(blk);
d6a644bb 1924 int64_t offset, start, remaining, count;
797ac58c 1925 char s1[64];
d6a644bb
EB
1926 int ret;
1927 int64_t num, sum_alloc;
797ac58c 1928
d6a644bb 1929 start = offset = cvtnum(argv[1]);
797ac58c 1930 if (offset < 0) {
a9ecfa00 1931 print_cvtnum_err(offset, argv[1]);
b32d7a39 1932 return offset;
797ac58c
KW
1933 }
1934
1935 if (argc == 3) {
4401fdc7
EB
1936 count = cvtnum(argv[2]);
1937 if (count < 0) {
1938 print_cvtnum_err(count, argv[2]);
b32d7a39 1939 return count;
797ac58c
KW
1940 }
1941 } else {
4401fdc7
EB
1942 count = BDRV_SECTOR_SIZE;
1943 }
797ac58c 1944
d6a644bb 1945 remaining = count;
797ac58c 1946 sum_alloc = 0;
797ac58c 1947 while (remaining) {
d6a644bb 1948 ret = bdrv_is_allocated(bs, offset, remaining, &num);
d663640c
PB
1949 if (ret < 0) {
1950 printf("is_allocated failed: %s\n", strerror(-ret));
b32d7a39 1951 return ret;
d663640c 1952 }
d6a644bb 1953 offset += num;
797ac58c
KW
1954 remaining -= num;
1955 if (ret) {
1956 sum_alloc += num;
1957 }
1958 if (num == 0) {
d6a644bb 1959 count -= remaining;
797ac58c
KW
1960 remaining = 0;
1961 }
1962 }
1963
d6a644bb 1964 cvtstr(start, s1, sizeof(s1));
797ac58c 1965
4401fdc7 1966 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
d6a644bb 1967 sum_alloc, count, s1);
b32d7a39 1968 return 0;
797ac58c
KW
1969}
1970
1971static const cmdinfo_t alloc_cmd = {
1972 .name = "alloc",
1973 .altname = "a",
1974 .argmin = 1,
1975 .argmax = 2,
1976 .cfunc = alloc_f,
4401fdc7
EB
1977 .args = "offset [count]",
1978 .oneline = "checks if offset is allocated in the file",
797ac58c
KW
1979};
1980
1981
d6a644bb
EB
1982static int map_is_allocated(BlockDriverState *bs, int64_t offset,
1983 int64_t bytes, int64_t *pnum)
797ac58c 1984{
d6a644bb
EB
1985 int64_t num;
1986 int num_checked;
797ac58c
KW
1987 int ret, firstret;
1988
d6a644bb
EB
1989 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1990 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
797ac58c
KW
1991 if (ret < 0) {
1992 return ret;
1993 }
1994
1995 firstret = ret;
1996 *pnum = num;
1997
d6a644bb
EB
1998 while (bytes > 0 && ret == firstret) {
1999 offset += num;
2000 bytes -= num;
797ac58c 2001
d6a644bb
EB
2002 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
2003 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
4b25bbc4 2004 if (ret == firstret && num) {
797ac58c
KW
2005 *pnum += num;
2006 } else {
2007 break;
2008 }
2009 }
2010
2011 return firstret;
2012}
2013
b32d7a39 2014static int map_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2015{
d6a644bb 2016 int64_t offset, bytes;
6f3c90af 2017 char s1[64], s2[64];
797ac58c
KW
2018 int64_t num;
2019 int ret;
2020 const char *retstr;
2021
2022 offset = 0;
d6a644bb
EB
2023 bytes = blk_getlength(blk);
2024 if (bytes < 0) {
2025 error_report("Failed to query image length: %s", strerror(-bytes));
b32d7a39 2026 return bytes;
4c7b7e9b
HR
2027 }
2028
d6a644bb
EB
2029 while (bytes) {
2030 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
797ac58c
KW
2031 if (ret < 0) {
2032 error_report("Failed to get allocation status: %s", strerror(-ret));
b32d7a39 2033 return ret;
4b25bbc4
HR
2034 } else if (!num) {
2035 error_report("Unexpected end of image");
b32d7a39 2036 return -EIO;
797ac58c
KW
2037 }
2038
2039 retstr = ret ? " allocated" : "not allocated";
d6a644bb
EB
2040 cvtstr(num, s1, sizeof(s1));
2041 cvtstr(offset, s2, sizeof(s2));
6f3c90af 2042 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
d6a644bb 2043 s1, num, retstr, s2, offset);
797ac58c
KW
2044
2045 offset += num;
d6a644bb
EB
2046 bytes -= num;
2047 }
b32d7a39
HR
2048
2049 return 0;
797ac58c
KW
2050}
2051
2052static const cmdinfo_t map_cmd = {
2053 .name = "map",
2054 .argmin = 0,
2055 .argmax = 0,
2056 .cfunc = map_f,
2057 .args = "",
2058 .oneline = "prints the allocated areas of a file",
2059};
2060
5bbd2e59
KW
2061static void reopen_help(void)
2062{
2063 printf(
2064"\n"
2065" Changes the open options of an already opened image\n"
2066"\n"
2067" Example:\n"
2068" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2069"\n"
2070" -r, -- Reopen the image read-only\n"
ea92203c 2071" -w, -- Reopen the image read-write\n"
5bbd2e59
KW
2072" -c, -- Change the cache mode to the given value\n"
2073" -o, -- Changes block driver options (cf. 'open' command)\n"
2074"\n");
2075}
2076
b32d7a39 2077static int reopen_f(BlockBackend *blk, int argc, char **argv);
5bbd2e59
KW
2078
2079static QemuOptsList reopen_opts = {
2080 .name = "reopen",
2081 .merge_lists = true,
2082 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2083 .desc = {
2084 /* no elements => accept any params */
2085 { /* end of list */ }
2086 },
2087};
2088
2089static const cmdinfo_t reopen_cmd = {
2090 .name = "reopen",
2091 .argmin = 0,
2092 .argmax = -1,
2093 .cfunc = reopen_f,
ea92203c 2094 .args = "[(-r|-w)] [-c cache] [-o options]",
5bbd2e59
KW
2095 .oneline = "reopens an image with new options",
2096 .help = reopen_help,
2097};
2098
b32d7a39 2099static int reopen_f(BlockBackend *blk, int argc, char **argv)
5bbd2e59
KW
2100{
2101 BlockDriverState *bs = blk_bs(blk);
2102 QemuOpts *qopts;
2103 QDict *opts;
2104 int c;
2105 int flags = bs->open_flags;
19dbecdc 2106 bool writethrough = !blk_enable_write_cache(blk);
ea92203c 2107 bool has_rw_option = false;
dc900c35 2108 bool has_cache_option = false;
5bbd2e59
KW
2109
2110 BlockReopenQueue *brq;
2111 Error *local_err = NULL;
2112
ea92203c 2113 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
5bbd2e59
KW
2114 switch (c) {
2115 case 'c':
19dbecdc 2116 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
5bbd2e59 2117 error_report("Invalid cache option: %s", optarg);
b32d7a39 2118 return -EINVAL;
5bbd2e59 2119 }
dc900c35 2120 has_cache_option = true;
5bbd2e59
KW
2121 break;
2122 case 'o':
2123 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2124 qemu_opts_reset(&reopen_opts);
b32d7a39 2125 return -EINVAL;
5bbd2e59
KW
2126 }
2127 break;
2128 case 'r':
ea92203c
KW
2129 if (has_rw_option) {
2130 error_report("Only one -r/-w option may be given");
b32d7a39 2131 return -EINVAL;
ea92203c 2132 }
5bbd2e59 2133 flags &= ~BDRV_O_RDWR;
ea92203c
KW
2134 has_rw_option = true;
2135 break;
2136 case 'w':
2137 if (has_rw_option) {
2138 error_report("Only one -r/-w option may be given");
b32d7a39 2139 return -EINVAL;
ea92203c
KW
2140 }
2141 flags |= BDRV_O_RDWR;
2142 has_rw_option = true;
5bbd2e59
KW
2143 break;
2144 default:
2145 qemu_opts_reset(&reopen_opts);
b444d0e9 2146 qemuio_command_usage(&reopen_cmd);
b32d7a39 2147 return -EINVAL;
5bbd2e59
KW
2148 }
2149 }
2150
2151 if (optind != argc) {
2152 qemu_opts_reset(&reopen_opts);
b444d0e9 2153 qemuio_command_usage(&reopen_cmd);
b32d7a39 2154 return -EINVAL;
5bbd2e59
KW
2155 }
2156
a8003ec4 2157 if (!writethrough != blk_enable_write_cache(blk) &&
19dbecdc
KW
2158 blk_get_attached_dev(blk))
2159 {
2160 error_report("Cannot change cache.writeback: Device attached");
2161 qemu_opts_reset(&reopen_opts);
b32d7a39 2162 return -EBUSY;
19dbecdc
KW
2163 }
2164
f3adefb2
KW
2165 if (!(flags & BDRV_O_RDWR)) {
2166 uint64_t orig_perm, orig_shared_perm;
2167
2168 bdrv_drain(bs);
2169
2170 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2171 blk_set_perm(blk,
2172 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2173 orig_shared_perm,
2174 &error_abort);
2175 }
2176
5bbd2e59 2177 qopts = qemu_opts_find(&reopen_opts, NULL);
dc900c35 2178 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
5bbd2e59
KW
2179 qemu_opts_reset(&reopen_opts);
2180
dc900c35
AG
2181 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2182 if (has_rw_option) {
2183 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2184 qobject_unref(opts);
2185 return -EINVAL;
2186 }
2187 } else {
2188 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2189 }
2190
2191 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2192 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2193 if (has_cache_option) {
2194 error_report("Cannot set both -c and the cache options");
2195 qobject_unref(opts);
2196 return -EINVAL;
2197 }
2198 } else {
2199 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2200 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2201 }
2202
1a63a907 2203 bdrv_subtree_drained_begin(bs);
077e8e20 2204 brq = bdrv_reopen_queue(NULL, bs, opts, true);
5019aece 2205 bdrv_reopen_multiple(brq, &local_err);
1a63a907
KW
2206 bdrv_subtree_drained_end(bs);
2207
5bbd2e59
KW
2208 if (local_err) {
2209 error_report_err(local_err);
b32d7a39 2210 return -EINVAL;
5bbd2e59 2211 }
b32d7a39
HR
2212
2213 blk_set_enable_write_cache(blk, !writethrough);
2214 return 0;
5bbd2e59
KW
2215}
2216
b32d7a39 2217static int break_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2218{
2219 int ret;
2220
4c7b7e9b 2221 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
797ac58c
KW
2222 if (ret < 0) {
2223 printf("Could not set breakpoint: %s\n", strerror(-ret));
b32d7a39 2224 return ret;
797ac58c 2225 }
b32d7a39
HR
2226
2227 return 0;
797ac58c
KW
2228}
2229
b32d7a39 2230static int remove_break_f(BlockBackend *blk, int argc, char **argv)
4cc70e93
FZ
2231{
2232 int ret;
2233
4c7b7e9b 2234 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
4cc70e93
FZ
2235 if (ret < 0) {
2236 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
b32d7a39 2237 return ret;
4cc70e93 2238 }
b32d7a39
HR
2239
2240 return 0;
4cc70e93
FZ
2241}
2242
797ac58c
KW
2243static const cmdinfo_t break_cmd = {
2244 .name = "break",
2245 .argmin = 2,
2246 .argmax = 2,
2247 .cfunc = break_f,
2248 .args = "event tag",
2249 .oneline = "sets a breakpoint on event and tags the stopped "
2250 "request as tag",
2251};
2252
4cc70e93
FZ
2253static const cmdinfo_t remove_break_cmd = {
2254 .name = "remove_break",
2255 .argmin = 1,
2256 .argmax = 1,
2257 .cfunc = remove_break_f,
2258 .args = "tag",
2259 .oneline = "remove a breakpoint by tag",
2260};
2261
b32d7a39 2262static int resume_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2263{
2264 int ret;
2265
4c7b7e9b 2266 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
797ac58c
KW
2267 if (ret < 0) {
2268 printf("Could not resume request: %s\n", strerror(-ret));
b32d7a39 2269 return ret;
797ac58c 2270 }
b32d7a39
HR
2271
2272 return 0;
797ac58c
KW
2273}
2274
2275static const cmdinfo_t resume_cmd = {
2276 .name = "resume",
2277 .argmin = 1,
2278 .argmax = 1,
2279 .cfunc = resume_f,
2280 .args = "tag",
2281 .oneline = "resumes the request tagged as tag",
2282};
2283
b32d7a39 2284static int wait_break_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2285{
4c7b7e9b
HR
2286 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2287 aio_poll(blk_get_aio_context(blk), true);
797ac58c 2288 }
b32d7a39 2289 return 0;
797ac58c
KW
2290}
2291
2292static const cmdinfo_t wait_break_cmd = {
2293 .name = "wait_break",
2294 .argmin = 1,
2295 .argmax = 1,
2296 .cfunc = wait_break_f,
2297 .args = "tag",
2298 .oneline = "waits for the suspension of a request",
2299};
2300
b32d7a39 2301static int abort_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2302{
2303 abort();
2304}
2305
2306static const cmdinfo_t abort_cmd = {
2307 .name = "abort",
2308 .cfunc = abort_f,
2309 .flags = CMD_NOFILE_OK,
2310 .oneline = "simulate a program crash using abort(3)",
2311};
2312
0e82dc7b
HR
2313static void sigraise_help(void)
2314{
2315 printf(
2316"\n"
2317" raises the given signal\n"
2318"\n"
2319" Example:\n"
2320" 'sigraise %i' - raises SIGTERM\n"
2321"\n"
2322" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2323" given to sigraise.\n"
2324"\n", SIGTERM);
2325}
2326
b32d7a39 2327static int sigraise_f(BlockBackend *blk, int argc, char **argv);
0e82dc7b
HR
2328
2329static const cmdinfo_t sigraise_cmd = {
2330 .name = "sigraise",
2331 .cfunc = sigraise_f,
2332 .argmin = 1,
2333 .argmax = 1,
2334 .flags = CMD_NOFILE_OK,
2335 .args = "signal",
2336 .oneline = "raises a signal",
2337 .help = sigraise_help,
2338};
2339
b32d7a39 2340static int sigraise_f(BlockBackend *blk, int argc, char **argv)
0e82dc7b 2341{
9b0beaf3 2342 int64_t sig = cvtnum(argv[1]);
0e82dc7b 2343 if (sig < 0) {
a9ecfa00 2344 print_cvtnum_err(sig, argv[1]);
b32d7a39 2345 return sig;
9b0beaf3
JS
2346 } else if (sig > NSIG) {
2347 printf("signal argument '%s' is too large to be a valid signal\n",
2348 argv[1]);
b32d7a39 2349 return -EINVAL;
0e82dc7b
HR
2350 }
2351
2352 /* Using raise() to kill this process does not necessarily flush all open
2353 * streams. At least stdout and stderr (although the latter should be
2354 * non-buffered anyway) should be flushed, though. */
2355 fflush(stdout);
2356 fflush(stderr);
2357
2358 raise(sig);
b32d7a39
HR
2359
2360 return 0;
0e82dc7b
HR
2361}
2362
cd33d02a
KW
2363static void sleep_cb(void *opaque)
2364{
2365 bool *expired = opaque;
2366 *expired = true;
2367}
2368
b32d7a39 2369static int sleep_f(BlockBackend *blk, int argc, char **argv)
cd33d02a
KW
2370{
2371 char *endptr;
2372 long ms;
2373 struct QEMUTimer *timer;
2374 bool expired = false;
2375
2376 ms = strtol(argv[1], &endptr, 0);
2377 if (ms < 0 || *endptr != '\0') {
2378 printf("%s is not a valid number\n", argv[1]);
b32d7a39 2379 return -EINVAL;
cd33d02a
KW
2380 }
2381
2382 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2383 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2384
2385 while (!expired) {
2386 main_loop_wait(false);
2387 }
2388
2389 timer_free(timer);
b32d7a39 2390 return 0;
cd33d02a
KW
2391}
2392
2393static const cmdinfo_t sleep_cmd = {
2394 .name = "sleep",
2395 .argmin = 1,
2396 .argmax = 1,
2397 .cfunc = sleep_f,
2398 .flags = CMD_NOFILE_OK,
2399 .oneline = "waits for the given value in milliseconds",
2400};
2401
f18a834a
KW
2402static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2403{
da16f4b8 2404 printf("%s ", cmd);
f18a834a
KW
2405
2406 if (ct->args) {
2407 printf("%s ", ct->args);
2408 }
2409 printf("-- %s\n", ct->oneline);
2410}
2411
2412static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2413{
2414 help_oneline(cmd, ct);
2415 if (ct->help) {
2416 ct->help();
2417 }
2418}
2419
2420static void help_all(void)
2421{
2422 const cmdinfo_t *ct;
2423
2424 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2425 help_oneline(ct->name, ct);
2426 }
2427 printf("\nUse 'help commandname' for extended help.\n");
2428}
2429
b32d7a39 2430static int help_f(BlockBackend *blk, int argc, char **argv)
f18a834a
KW
2431{
2432 const cmdinfo_t *ct;
2433
da16f4b8 2434 if (argc < 2) {
f18a834a 2435 help_all();
b32d7a39 2436 return 0;
f18a834a
KW
2437 }
2438
2439 ct = find_command(argv[1]);
2440 if (ct == NULL) {
2441 printf("command %s not found\n", argv[1]);
b32d7a39 2442 return -EINVAL;
f18a834a
KW
2443 }
2444
2445 help_onecmd(argv[1], ct);
b32d7a39 2446 return 0;
f18a834a
KW
2447}
2448
2449static const cmdinfo_t help_cmd = {
2450 .name = "help",
2451 .altname = "?",
2452 .cfunc = help_f,
2453 .argmin = 0,
2454 .argmax = 1,
2455 .flags = CMD_FLAG_GLOBAL,
2456 .args = "[command]",
2457 .oneline = "help for one or all commands",
2458};
2459
b32d7a39 2460int qemuio_command(BlockBackend *blk, const char *cmd)
dd583296 2461{
15afd94a 2462 AioContext *ctx;
dd583296
KW
2463 char *input;
2464 const cmdinfo_t *ct;
2465 char **v;
2466 int c;
b32d7a39 2467 int ret = 0;
dd583296
KW
2468
2469 input = g_strdup(cmd);
2470 v = breakline(input, &c);
2471 if (c) {
2472 ct = find_command(v[0]);
2473 if (ct) {
15afd94a
PB
2474 ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
2475 aio_context_acquire(ctx);
b32d7a39 2476 ret = command(blk, ct, c, v);
15afd94a 2477 aio_context_release(ctx);
dd583296
KW
2478 } else {
2479 fprintf(stderr, "command \"%s\" not found\n", v[0]);
b32d7a39 2480 ret = -EINVAL;
dd583296
KW
2481 }
2482 }
2483 g_free(input);
2484 g_free(v);
b32d7a39
HR
2485
2486 return ret;
dd583296
KW
2487}
2488
797ac58c
KW
2489static void __attribute((constructor)) init_qemuio_commands(void)
2490{
2491 /* initialize commands */
c2cdf5c5
KW
2492 qemuio_add_command(&help_cmd);
2493 qemuio_add_command(&read_cmd);
2494 qemuio_add_command(&readv_cmd);
2495 qemuio_add_command(&write_cmd);
2496 qemuio_add_command(&writev_cmd);
c2cdf5c5
KW
2497 qemuio_add_command(&aio_read_cmd);
2498 qemuio_add_command(&aio_write_cmd);
2499 qemuio_add_command(&aio_flush_cmd);
2500 qemuio_add_command(&flush_cmd);
2501 qemuio_add_command(&truncate_cmd);
2502 qemuio_add_command(&length_cmd);
2503 qemuio_add_command(&info_cmd);
2504 qemuio_add_command(&discard_cmd);
2505 qemuio_add_command(&alloc_cmd);
2506 qemuio_add_command(&map_cmd);
5bbd2e59 2507 qemuio_add_command(&reopen_cmd);
c2cdf5c5 2508 qemuio_add_command(&break_cmd);
4cc70e93 2509 qemuio_add_command(&remove_break_cmd);
c2cdf5c5
KW
2510 qemuio_add_command(&resume_cmd);
2511 qemuio_add_command(&wait_break_cmd);
2512 qemuio_add_command(&abort_cmd);
cd33d02a 2513 qemuio_add_command(&sleep_cmd);
0e82dc7b 2514 qemuio_add_command(&sigraise_cmd);
797ac58c 2515}