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