]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-io-cmds.c
block/copy-before-write: implement cbw-timeout option
[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{
f5a5ca79 544 if (bytes > INT_MAX) {
9b0beaf3
JS
545 return -ERANGE;
546 }
547
f5a5ca79 548 *total = blk_pread(blk, offset, (uint8_t *)buf, bytes);
797ac58c
KW
549 if (*total < 0) {
550 return *total;
551 }
552 return 1;
553}
554
9b0beaf3 555static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
f5a5ca79 556 int64_t bytes, int flags, int64_t *total)
797ac58c 557{
f5a5ca79 558 if (bytes > INT_MAX) {
9b0beaf3
JS
559 return -ERANGE;
560 }
561
f5a5ca79 562 *total = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
797ac58c
KW
563 if (*total < 0) {
564 return *total;
565 }
566 return 1;
567}
568
569typedef struct {
4c7b7e9b 570 BlockBackend *blk;
797ac58c 571 int64_t offset;
f5a5ca79 572 int64_t bytes;
9b0beaf3 573 int64_t *total;
770e0e0e 574 int flags;
797ac58c
KW
575 int ret;
576 bool done;
577} CoWriteZeroes;
578
d004bd52 579static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
797ac58c
KW
580{
581 CoWriteZeroes *data = opaque;
582
f5a5ca79 583 data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
d004bd52 584 data->flags);
797ac58c
KW
585 data->done = true;
586 if (data->ret < 0) {
587 *data->total = data->ret;
588 return;
589 }
590
f5a5ca79 591 *data->total = data->bytes;
797ac58c
KW
592}
593
d004bd52 594static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
f5a5ca79 595 int64_t bytes, int flags, int64_t *total)
797ac58c
KW
596{
597 Coroutine *co;
598 CoWriteZeroes data = {
4c7b7e9b 599 .blk = blk,
797ac58c 600 .offset = offset,
f5a5ca79 601 .bytes = bytes,
797ac58c 602 .total = total,
770e0e0e 603 .flags = flags,
797ac58c
KW
604 .done = false,
605 };
606
0b8b8753 607 co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
324ec3e4 608 bdrv_coroutine_enter(blk_bs(blk), co);
797ac58c 609 while (!data.done) {
4c7b7e9b 610 aio_poll(blk_get_aio_context(blk), true);
797ac58c
KW
611 }
612 if (data.ret < 0) {
613 return data.ret;
614 } else {
615 return 1;
616 }
617}
618
4c7b7e9b 619static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
f5a5ca79 620 int64_t bytes, int64_t *total)
797ac58c
KW
621{
622 int ret;
623
41ae31e3 624 if (bytes > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3
JS
625 return -ERANGE;
626 }
627
f5a5ca79 628 ret = blk_pwrite_compressed(blk, offset, buf, bytes);
797ac58c
KW
629 if (ret < 0) {
630 return ret;
631 }
f5a5ca79 632 *total = bytes;
797ac58c
KW
633 return 1;
634}
635
4c7b7e9b 636static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset,
9b0beaf3 637 int64_t count, int64_t *total)
797ac58c 638{
9b0beaf3
JS
639 if (count > INT_MAX) {
640 return -ERANGE;
641 }
642
4c7b7e9b 643 *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count);
797ac58c
KW
644 if (*total < 0) {
645 return *total;
646 }
647 return 1;
648}
649
4c7b7e9b 650static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset,
9b0beaf3 651 int64_t count, int64_t *total)
797ac58c 652{
9b0beaf3
JS
653 if (count > INT_MAX) {
654 return -ERANGE;
655 }
656
4c7b7e9b 657 *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count);
797ac58c
KW
658 if (*total < 0) {
659 return *total;
660 }
661 return 1;
662}
663
664#define NOT_DONE 0x7fffffff
665static void aio_rw_done(void *opaque, int ret)
666{
667 *(int *)opaque = ret;
668}
669
4c7b7e9b 670static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
797ac58c
KW
671 int64_t offset, int *total)
672{
673 int async_ret = NOT_DONE;
674
7b3f9712 675 blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret);
797ac58c
KW
676 while (async_ret == NOT_DONE) {
677 main_loop_wait(false);
678 }
679
680 *total = qiov->size;
681 return async_ret < 0 ? async_ret : 1;
682}
683
4c7b7e9b 684static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
770e0e0e 685 int64_t offset, int flags, int *total)
797ac58c
KW
686{
687 int async_ret = NOT_DONE;
688
770e0e0e 689 blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret);
797ac58c
KW
690 while (async_ret == NOT_DONE) {
691 main_loop_wait(false);
692 }
693
694 *total = qiov->size;
695 return async_ret < 0 ? async_ret : 1;
696}
697
797ac58c
KW
698static void read_help(void)
699{
700 printf(
701"\n"
702" reads a range of bytes from the given offset\n"
703"\n"
704" Example:\n"
705" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
706"\n"
707" Reads a segment of the currently open file, optionally dumping it to the\n"
708" standard output stream (with -v option) for subsequent inspection.\n"
709" -b, -- read from the VM state rather than the virtual disk\n"
710" -C, -- report statistics in a machine parsable format\n"
711" -l, -- length for pattern verification (only with -P)\n"
093ea232 712" -p, -- ignored for backwards compatibility\n"
797ac58c
KW
713" -P, -- use a pattern to verify read data\n"
714" -q, -- quiet mode, do not show I/O statistics\n"
715" -s, -- start offset for pattern verification (only with -P)\n"
716" -v, -- dump buffer to standard output\n"
717"\n");
718}
719
b32d7a39 720static int read_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
721
722static const cmdinfo_t read_cmd = {
723 .name = "read",
724 .altname = "r",
725 .cfunc = read_f,
726 .argmin = 2,
727 .argmax = -1,
093ea232 728 .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len",
797ac58c
KW
729 .oneline = "reads a number of bytes at a specified offset",
730 .help = read_help,
731};
732
b32d7a39 733static int read_f(BlockBackend *blk, int argc, char **argv)
797ac58c 734{
50290c00 735 struct timespec t1, t2;
093ea232 736 bool Cflag = false, qflag = false, vflag = false;
dc38852a 737 bool Pflag = false, sflag = false, lflag = false, bflag = false;
b32d7a39 738 int c, cnt, ret;
797ac58c
KW
739 char *buf;
740 int64_t offset;
9b0beaf3 741 int64_t count;
797ac58c 742 /* Some compilers get confused and warn if this is not initialized. */
9b0beaf3
JS
743 int64_t total = 0;
744 int pattern = 0;
745 int64_t pattern_offset = 0, pattern_count = 0;
797ac58c 746
b062ad86 747 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
797ac58c
KW
748 switch (c) {
749 case 'b':
dc38852a 750 bflag = true;
797ac58c
KW
751 break;
752 case 'C':
dc38852a 753 Cflag = true;
797ac58c
KW
754 break;
755 case 'l':
dc38852a 756 lflag = true;
797ac58c
KW
757 pattern_count = cvtnum(optarg);
758 if (pattern_count < 0) {
a9ecfa00 759 print_cvtnum_err(pattern_count, optarg);
b32d7a39 760 return pattern_count;
797ac58c
KW
761 }
762 break;
763 case 'p':
093ea232 764 /* Ignored for backwards compatibility */
797ac58c
KW
765 break;
766 case 'P':
dc38852a 767 Pflag = true;
797ac58c
KW
768 pattern = parse_pattern(optarg);
769 if (pattern < 0) {
b32d7a39 770 return -EINVAL;
797ac58c
KW
771 }
772 break;
773 case 'q':
dc38852a 774 qflag = true;
797ac58c
KW
775 break;
776 case 's':
dc38852a 777 sflag = true;
797ac58c
KW
778 pattern_offset = cvtnum(optarg);
779 if (pattern_offset < 0) {
a9ecfa00 780 print_cvtnum_err(pattern_offset, optarg);
b32d7a39 781 return pattern_offset;
797ac58c
KW
782 }
783 break;
784 case 'v':
dc38852a 785 vflag = true;
797ac58c
KW
786 break;
787 default:
b444d0e9 788 qemuio_command_usage(&read_cmd);
b32d7a39 789 return -EINVAL;
797ac58c
KW
790 }
791 }
792
793 if (optind != argc - 2) {
b444d0e9 794 qemuio_command_usage(&read_cmd);
b32d7a39 795 return -EINVAL;
797ac58c
KW
796 }
797
797ac58c
KW
798 offset = cvtnum(argv[optind]);
799 if (offset < 0) {
a9ecfa00 800 print_cvtnum_err(offset, argv[optind]);
b32d7a39 801 return offset;
797ac58c
KW
802 }
803
804 optind++;
805 count = cvtnum(argv[optind]);
806 if (count < 0) {
a9ecfa00 807 print_cvtnum_err(count, argv[optind]);
b32d7a39 808 return count;
3026c468 809 } else if (count > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 810 printf("length cannot exceed %" PRIu64 ", given %s\n",
3026c468 811 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 812 return -EINVAL;
797ac58c
KW
813 }
814
815 if (!Pflag && (lflag || sflag)) {
b444d0e9 816 qemuio_command_usage(&read_cmd);
b32d7a39 817 return -EINVAL;
797ac58c
KW
818 }
819
820 if (!lflag) {
821 pattern_count = count - pattern_offset;
822 }
823
824 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
825 printf("pattern verification range exceeds end of read data\n");
b32d7a39 826 return -EINVAL;
797ac58c
KW
827 }
828
093ea232 829 if (bflag) {
1bce6b4c
EB
830 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
831 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
797ac58c 832 offset);
b32d7a39 833 return -EINVAL;
797ac58c 834 }
1bce6b4c
EB
835 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
836 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
797ac58c 837 count);
b32d7a39 838 return -EINVAL;
797ac58c
KW
839 }
840 }
841
4c7b7e9b 842 buf = qemu_io_alloc(blk, count, 0xab);
797ac58c 843
50290c00 844 clock_gettime(CLOCK_MONOTONIC, &t1);
7b3f9712 845 if (bflag) {
b32d7a39 846 ret = do_load_vmstate(blk, buf, offset, count, &total);
797ac58c 847 } else {
b32d7a39 848 ret = do_pread(blk, buf, offset, count, &total);
797ac58c 849 }
50290c00 850 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c 851
b32d7a39
HR
852 if (ret < 0) {
853 printf("read failed: %s\n", strerror(-ret));
797ac58c
KW
854 goto out;
855 }
b32d7a39
HR
856 cnt = ret;
857
858 ret = 0;
797ac58c
KW
859
860 if (Pflag) {
861 void *cmp_buf = g_malloc(pattern_count);
862 memset(cmp_buf, pattern, pattern_count);
863 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
864 printf("Pattern verification failed at offset %"
9b0beaf3 865 PRId64 ", %"PRId64" bytes\n",
797ac58c 866 offset + pattern_offset, pattern_count);
b32d7a39 867 ret = -EINVAL;
797ac58c
KW
868 }
869 g_free(cmp_buf);
870 }
871
872 if (qflag) {
873 goto out;
874 }
875
876 if (vflag) {
877 dump_buffer(buf, offset, count);
878 }
879
880 /* Finally, report back -- -C gives a parsable format */
881 t2 = tsub(t2, t1);
882 print_report("read", &t2, offset, count, total, cnt, Cflag);
883
884out:
885 qemu_io_free(buf);
b32d7a39 886 return ret;
797ac58c
KW
887}
888
889static void readv_help(void)
890{
891 printf(
892"\n"
893" reads a range of bytes from the given offset into multiple buffers\n"
894"\n"
895" Example:\n"
896" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
897"\n"
898" Reads a segment of the currently open file, optionally dumping it to the\n"
899" standard output stream (with -v option) for subsequent inspection.\n"
900" Uses multiple iovec buffers if more than one byte range is specified.\n"
901" -C, -- report statistics in a machine parsable format\n"
902" -P, -- use a pattern to verify read data\n"
903" -v, -- dump buffer to standard output\n"
904" -q, -- quiet mode, do not show I/O statistics\n"
905"\n");
906}
907
b32d7a39 908static int readv_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
909
910static const cmdinfo_t readv_cmd = {
911 .name = "readv",
912 .cfunc = readv_f,
913 .argmin = 2,
914 .argmax = -1,
093ea232 915 .args = "[-Cqv] [-P pattern] off len [len..]",
797ac58c
KW
916 .oneline = "reads a number of bytes at a specified offset",
917 .help = readv_help,
918};
919
b32d7a39 920static int readv_f(BlockBackend *blk, int argc, char **argv)
797ac58c 921{
50290c00 922 struct timespec t1, t2;
dc38852a 923 bool Cflag = false, qflag = false, vflag = false;
b32d7a39 924 int c, cnt, ret;
797ac58c
KW
925 char *buf;
926 int64_t offset;
927 /* Some compilers get confused and warn if this is not initialized. */
928 int total = 0;
929 int nr_iov;
930 QEMUIOVector qiov;
931 int pattern = 0;
dc38852a 932 bool Pflag = false;
797ac58c 933
b062ad86 934 while ((c = getopt(argc, argv, "CP:qv")) != -1) {
797ac58c
KW
935 switch (c) {
936 case 'C':
dc38852a 937 Cflag = true;
797ac58c
KW
938 break;
939 case 'P':
dc38852a 940 Pflag = true;
797ac58c
KW
941 pattern = parse_pattern(optarg);
942 if (pattern < 0) {
b32d7a39 943 return -EINVAL;
797ac58c
KW
944 }
945 break;
946 case 'q':
dc38852a 947 qflag = true;
797ac58c
KW
948 break;
949 case 'v':
dc38852a 950 vflag = true;
797ac58c
KW
951 break;
952 default:
b444d0e9 953 qemuio_command_usage(&readv_cmd);
b32d7a39 954 return -EINVAL;
797ac58c
KW
955 }
956 }
957
958 if (optind > argc - 2) {
b444d0e9 959 qemuio_command_usage(&readv_cmd);
b32d7a39 960 return -EINVAL;
797ac58c
KW
961 }
962
963
964 offset = cvtnum(argv[optind]);
965 if (offset < 0) {
a9ecfa00 966 print_cvtnum_err(offset, argv[optind]);
b32d7a39 967 return offset;
797ac58c
KW
968 }
969 optind++;
970
797ac58c 971 nr_iov = argc - optind;
4c7b7e9b 972 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
797ac58c 973 if (buf == NULL) {
b32d7a39 974 return -EINVAL;
797ac58c
KW
975 }
976
50290c00 977 clock_gettime(CLOCK_MONOTONIC, &t1);
b32d7a39 978 ret = do_aio_readv(blk, &qiov, offset, &total);
50290c00 979 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c 980
b32d7a39
HR
981 if (ret < 0) {
982 printf("readv failed: %s\n", strerror(-ret));
797ac58c
KW
983 goto out;
984 }
b32d7a39
HR
985 cnt = ret;
986
987 ret = 0;
797ac58c
KW
988
989 if (Pflag) {
990 void *cmp_buf = g_malloc(qiov.size);
991 memset(cmp_buf, pattern, qiov.size);
992 if (memcmp(buf, cmp_buf, qiov.size)) {
993 printf("Pattern verification failed at offset %"
cf67b692 994 PRId64 ", %zu bytes\n", offset, qiov.size);
b32d7a39 995 ret = -EINVAL;
797ac58c
KW
996 }
997 g_free(cmp_buf);
998 }
999
1000 if (qflag) {
1001 goto out;
1002 }
1003
1004 if (vflag) {
1005 dump_buffer(buf, offset, qiov.size);
1006 }
1007
1008 /* Finally, report back -- -C gives a parsable format */
1009 t2 = tsub(t2, t1);
1010 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
1011
1012out:
1013 qemu_iovec_destroy(&qiov);
1014 qemu_io_free(buf);
b32d7a39 1015 return ret;
797ac58c
KW
1016}
1017
1018static void write_help(void)
1019{
1020 printf(
1021"\n"
1022" writes a range of bytes from the given offset\n"
1023"\n"
1024" Example:\n"
1025" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
1026"\n"
1027" Writes into a segment of the currently open file, using a buffer\n"
1028" filled with a set pattern (0xcdcdcdcd).\n"
1029" -b, -- write to the VM state rather than the virtual disk\n"
4c7b7e9b 1030" -c, -- write compressed data with blk_write_compressed\n"
770e0e0e 1031" -f, -- use Force Unit Access semantics\n"
c6e3f520 1032" -n, -- with -z, don't allow slow fallback\n"
093ea232 1033" -p, -- ignored for backwards compatibility\n"
797ac58c 1034" -P, -- use different pattern to fill file\n"
4d731510 1035" -s, -- use a pattern file to fill the write buffer\n"
797ac58c
KW
1036" -C, -- report statistics in a machine parsable format\n"
1037" -q, -- quiet mode, do not show I/O statistics\n"
c2e001cc 1038" -u, -- with -z, allow unmapping\n"
d004bd52 1039" -z, -- write zeroes using blk_co_pwrite_zeroes\n"
797ac58c
KW
1040"\n");
1041}
1042
b32d7a39 1043static int write_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1044
1045static const cmdinfo_t write_cmd = {
1046 .name = "write",
1047 .altname = "w",
1048 .cfunc = write_f,
887354bd 1049 .perm = BLK_PERM_WRITE,
797ac58c
KW
1050 .argmin = 2,
1051 .argmax = -1,
4d731510 1052 .args = "[-bcCfnquz] [-P pattern | -s source_file] off len",
797ac58c
KW
1053 .oneline = "writes a number of bytes at a specified offset",
1054 .help = write_help,
1055};
1056
b32d7a39 1057static int write_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1058{
50290c00 1059 struct timespec t1, t2;
093ea232 1060 bool Cflag = false, qflag = false, bflag = false;
4d731510 1061 bool Pflag = false, zflag = false, cflag = false, sflag = false;
770e0e0e 1062 int flags = 0;
b32d7a39 1063 int c, cnt, ret;
797ac58c
KW
1064 char *buf = NULL;
1065 int64_t offset;
9b0beaf3 1066 int64_t count;
797ac58c 1067 /* Some compilers get confused and warn if this is not initialized. */
9b0beaf3 1068 int64_t total = 0;
797ac58c 1069 int pattern = 0xcd;
4d731510 1070 const char *file_name = NULL;
797ac58c 1071
4d731510 1072 while ((c = getopt(argc, argv, "bcCfnpP:qs:uz")) != -1) {
797ac58c
KW
1073 switch (c) {
1074 case 'b':
dc38852a 1075 bflag = true;
797ac58c
KW
1076 break;
1077 case 'c':
dc38852a 1078 cflag = true;
797ac58c
KW
1079 break;
1080 case 'C':
dc38852a 1081 Cflag = true;
797ac58c 1082 break;
770e0e0e
EB
1083 case 'f':
1084 flags |= BDRV_REQ_FUA;
1085 break;
c6e3f520
KW
1086 case 'n':
1087 flags |= BDRV_REQ_NO_FALLBACK;
1088 break;
797ac58c 1089 case 'p':
093ea232 1090 /* Ignored for backwards compatibility */
797ac58c
KW
1091 break;
1092 case 'P':
dc38852a 1093 Pflag = true;
797ac58c
KW
1094 pattern = parse_pattern(optarg);
1095 if (pattern < 0) {
b32d7a39 1096 return -EINVAL;
797ac58c
KW
1097 }
1098 break;
1099 case 'q':
dc38852a 1100 qflag = true;
797ac58c 1101 break;
4d731510
DP
1102 case 's':
1103 sflag = true;
1104 file_name = optarg;
1105 break;
c2e001cc
EB
1106 case 'u':
1107 flags |= BDRV_REQ_MAY_UNMAP;
1108 break;
797ac58c 1109 case 'z':
dc38852a 1110 zflag = true;
797ac58c
KW
1111 break;
1112 default:
b444d0e9 1113 qemuio_command_usage(&write_cmd);
b32d7a39 1114 return -EINVAL;
797ac58c
KW
1115 }
1116 }
1117
1118 if (optind != argc - 2) {
b444d0e9 1119 qemuio_command_usage(&write_cmd);
b32d7a39 1120 return -EINVAL;
797ac58c
KW
1121 }
1122
093ea232
EB
1123 if (bflag && zflag) {
1124 printf("-b and -z cannot be specified at the same time\n");
b32d7a39 1125 return -EINVAL;
797ac58c
KW
1126 }
1127
770e0e0e
EB
1128 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
1129 printf("-f and -b or -c cannot be specified at the same time\n");
b32d7a39 1130 return -EINVAL;
770e0e0e
EB
1131 }
1132
c6e3f520
KW
1133 if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
1134 printf("-n requires -z to be specified\n");
1135 return -EINVAL;
1136 }
1137
c2e001cc
EB
1138 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
1139 printf("-u requires -z to be specified\n");
b32d7a39 1140 return -EINVAL;
c2e001cc
EB
1141 }
1142
4d731510
DP
1143 if (zflag + Pflag + sflag > 1) {
1144 printf("Only one of -z, -P, and -s "
1145 "can be specified at the same time\n");
b32d7a39 1146 return -EINVAL;
797ac58c
KW
1147 }
1148
1149 offset = cvtnum(argv[optind]);
1150 if (offset < 0) {
a9ecfa00 1151 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1152 return offset;
797ac58c
KW
1153 }
1154
1155 optind++;
1156 count = cvtnum(argv[optind]);
1157 if (count < 0) {
a9ecfa00 1158 print_cvtnum_err(count, argv[optind]);
b32d7a39 1159 return count;
395aecd0
EB
1160 } else if (count > BDRV_REQUEST_MAX_BYTES &&
1161 !(flags & BDRV_REQ_NO_FALLBACK)) {
1162 printf("length cannot exceed %" PRIu64 " without -n, given %s\n",
3026c468 1163 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 1164 return -EINVAL;
797ac58c
KW
1165 }
1166
093ea232 1167 if (bflag || cflag) {
1bce6b4c
EB
1168 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
1169 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
797ac58c 1170 offset);
b32d7a39 1171 return -EINVAL;
797ac58c
KW
1172 }
1173
1bce6b4c
EB
1174 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
1175 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
797ac58c 1176 count);
b32d7a39 1177 return -EINVAL;
797ac58c
KW
1178 }
1179 }
1180
1181 if (!zflag) {
4d731510
DP
1182 if (sflag) {
1183 buf = qemu_io_alloc_from_file(blk, count, file_name);
1184 if (!buf) {
1185 return -EINVAL;
1186 }
1187 } else {
1188 buf = qemu_io_alloc(blk, count, pattern);
1189 }
797ac58c
KW
1190 }
1191
50290c00 1192 clock_gettime(CLOCK_MONOTONIC, &t1);
7b3f9712 1193 if (bflag) {
b32d7a39 1194 ret = do_save_vmstate(blk, buf, offset, count, &total);
797ac58c 1195 } else if (zflag) {
b32d7a39 1196 ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
797ac58c 1197 } else if (cflag) {
b32d7a39 1198 ret = do_write_compressed(blk, buf, offset, count, &total);
797ac58c 1199 } else {
b32d7a39 1200 ret = do_pwrite(blk, buf, offset, count, flags, &total);
797ac58c 1201 }
50290c00 1202 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c 1203
b32d7a39
HR
1204 if (ret < 0) {
1205 printf("write failed: %s\n", strerror(-ret));
797ac58c
KW
1206 goto out;
1207 }
b32d7a39
HR
1208 cnt = ret;
1209
1210 ret = 0;
797ac58c
KW
1211
1212 if (qflag) {
1213 goto out;
1214 }
1215
1216 /* Finally, report back -- -C gives a parsable format */
1217 t2 = tsub(t2, t1);
1218 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1219
1220out:
1221 if (!zflag) {
1222 qemu_io_free(buf);
1223 }
b32d7a39 1224 return ret;
797ac58c
KW
1225}
1226
1227static void
1228writev_help(void)
1229{
1230 printf(
1231"\n"
1232" writes a range of bytes from the given offset source from multiple buffers\n"
1233"\n"
1234" Example:\n"
6e6507c0 1235" 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
797ac58c
KW
1236"\n"
1237" Writes into a segment of the currently open file, using a buffer\n"
1238" filled with a set pattern (0xcdcdcdcd).\n"
1239" -P, -- use different pattern to fill file\n"
1240" -C, -- report statistics in a machine parsable format\n"
770e0e0e 1241" -f, -- use Force Unit Access semantics\n"
797ac58c
KW
1242" -q, -- quiet mode, do not show I/O statistics\n"
1243"\n");
1244}
1245
b32d7a39 1246static int writev_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1247
1248static const cmdinfo_t writev_cmd = {
1249 .name = "writev",
1250 .cfunc = writev_f,
887354bd 1251 .perm = BLK_PERM_WRITE,
797ac58c
KW
1252 .argmin = 2,
1253 .argmax = -1,
770e0e0e 1254 .args = "[-Cfq] [-P pattern] off len [len..]",
797ac58c
KW
1255 .oneline = "writes a number of bytes at a specified offset",
1256 .help = writev_help,
1257};
1258
b32d7a39 1259static int writev_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1260{
50290c00 1261 struct timespec t1, t2;
dc38852a 1262 bool Cflag = false, qflag = false;
770e0e0e 1263 int flags = 0;
b32d7a39 1264 int c, cnt, ret;
797ac58c
KW
1265 char *buf;
1266 int64_t offset;
1267 /* Some compilers get confused and warn if this is not initialized. */
1268 int total = 0;
1269 int nr_iov;
1270 int pattern = 0xcd;
1271 QEMUIOVector qiov;
1272
4ca1d340 1273 while ((c = getopt(argc, argv, "CfqP:")) != -1) {
797ac58c
KW
1274 switch (c) {
1275 case 'C':
dc38852a 1276 Cflag = true;
797ac58c 1277 break;
770e0e0e
EB
1278 case 'f':
1279 flags |= BDRV_REQ_FUA;
1280 break;
797ac58c 1281 case 'q':
dc38852a 1282 qflag = true;
797ac58c
KW
1283 break;
1284 case 'P':
1285 pattern = parse_pattern(optarg);
1286 if (pattern < 0) {
b32d7a39 1287 return -EINVAL;
797ac58c
KW
1288 }
1289 break;
1290 default:
b444d0e9 1291 qemuio_command_usage(&writev_cmd);
b32d7a39 1292 return -EINVAL;
797ac58c
KW
1293 }
1294 }
1295
1296 if (optind > argc - 2) {
b444d0e9 1297 qemuio_command_usage(&writev_cmd);
b32d7a39 1298 return -EINVAL;
797ac58c
KW
1299 }
1300
1301 offset = cvtnum(argv[optind]);
1302 if (offset < 0) {
a9ecfa00 1303 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1304 return offset;
797ac58c
KW
1305 }
1306 optind++;
1307
797ac58c 1308 nr_iov = argc - optind;
4c7b7e9b 1309 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
797ac58c 1310 if (buf == NULL) {
b32d7a39 1311 return -EINVAL;
797ac58c
KW
1312 }
1313
50290c00 1314 clock_gettime(CLOCK_MONOTONIC, &t1);
b32d7a39 1315 ret = do_aio_writev(blk, &qiov, offset, flags, &total);
50290c00 1316 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c 1317
b32d7a39
HR
1318 if (ret < 0) {
1319 printf("writev failed: %s\n", strerror(-ret));
797ac58c
KW
1320 goto out;
1321 }
b32d7a39
HR
1322 cnt = ret;
1323
1324 ret = 0;
797ac58c
KW
1325
1326 if (qflag) {
1327 goto out;
1328 }
1329
1330 /* Finally, report back -- -C gives a parsable format */
1331 t2 = tsub(t2, t1);
1332 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1333out:
1334 qemu_iovec_destroy(&qiov);
1335 qemu_io_free(buf);
b32d7a39 1336 return ret;
797ac58c
KW
1337}
1338
797ac58c 1339struct aio_ctx {
4c7b7e9b 1340 BlockBackend *blk;
797ac58c
KW
1341 QEMUIOVector qiov;
1342 int64_t offset;
1343 char *buf;
dc38852a
EB
1344 bool qflag;
1345 bool vflag;
1346 bool Cflag;
1347 bool Pflag;
1348 bool zflag;
a91f9584 1349 BlockAcctCookie acct;
797ac58c 1350 int pattern;
50290c00 1351 struct timespec t1;
797ac58c
KW
1352};
1353
1354static void aio_write_done(void *opaque, int ret)
1355{
1356 struct aio_ctx *ctx = opaque;
50290c00 1357 struct timespec t2;
797ac58c 1358
50290c00 1359 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c
KW
1360
1361
1362 if (ret < 0) {
1363 printf("aio_write failed: %s\n", strerror(-ret));
556c2b60 1364 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
797ac58c
KW
1365 goto out;
1366 }
1367
4c7b7e9b 1368 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
a91f9584 1369
797ac58c
KW
1370 if (ctx->qflag) {
1371 goto out;
1372 }
1373
1374 /* Finally, report back -- -C gives a parsable format */
1375 t2 = tsub(t2, ctx->t1);
1376 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1377 ctx->qiov.size, 1, ctx->Cflag);
1378out:
5ceb7765
KW
1379 if (!ctx->zflag) {
1380 qemu_io_free(ctx->buf);
1381 qemu_iovec_destroy(&ctx->qiov);
1382 }
797ac58c
KW
1383 g_free(ctx);
1384}
1385
1386static void aio_read_done(void *opaque, int ret)
1387{
1388 struct aio_ctx *ctx = opaque;
50290c00 1389 struct timespec t2;
797ac58c 1390
50290c00 1391 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c
KW
1392
1393 if (ret < 0) {
1394 printf("readv failed: %s\n", strerror(-ret));
556c2b60 1395 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
797ac58c
KW
1396 goto out;
1397 }
1398
1399 if (ctx->Pflag) {
1400 void *cmp_buf = g_malloc(ctx->qiov.size);
1401
1402 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1403 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1404 printf("Pattern verification failed at offset %"
cf67b692 1405 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
797ac58c
KW
1406 }
1407 g_free(cmp_buf);
1408 }
1409
4c7b7e9b 1410 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
a91f9584 1411
797ac58c
KW
1412 if (ctx->qflag) {
1413 goto out;
1414 }
1415
1416 if (ctx->vflag) {
1417 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1418 }
1419
1420 /* Finally, report back -- -C gives a parsable format */
1421 t2 = tsub(t2, ctx->t1);
1422 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1423 ctx->qiov.size, 1, ctx->Cflag);
1424out:
1425 qemu_io_free(ctx->buf);
1426 qemu_iovec_destroy(&ctx->qiov);
1427 g_free(ctx);
1428}
1429
1430static void aio_read_help(void)
1431{
1432 printf(
1433"\n"
1434" asynchronously reads a range of bytes from the given offset\n"
1435"\n"
1436" Example:\n"
1437" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1438"\n"
1439" Reads a segment of the currently open file, optionally dumping it to the\n"
1440" standard output stream (with -v option) for subsequent inspection.\n"
1441" The read is performed asynchronously and the aio_flush command must be\n"
1442" used to ensure all outstanding aio requests have been completed.\n"
b32d7a39
HR
1443" Note that due to its asynchronous nature, this command will be\n"
1444" considered successful once the request is submitted, independently\n"
1445" of potential I/O errors or pattern mismatches.\n"
797ac58c
KW
1446" -C, -- report statistics in a machine parsable format\n"
1447" -P, -- use a pattern to verify read data\n"
37546ff2 1448" -i, -- treat request as invalid, for exercising stats\n"
797ac58c
KW
1449" -v, -- dump buffer to standard output\n"
1450" -q, -- quiet mode, do not show I/O statistics\n"
1451"\n");
1452}
1453
b32d7a39 1454static int aio_read_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1455
1456static const cmdinfo_t aio_read_cmd = {
1457 .name = "aio_read",
1458 .cfunc = aio_read_f,
1459 .argmin = 2,
1460 .argmax = -1,
37546ff2 1461 .args = "[-Ciqv] [-P pattern] off len [len..]",
797ac58c
KW
1462 .oneline = "asynchronously reads a number of bytes",
1463 .help = aio_read_help,
1464};
1465
b32d7a39 1466static int aio_read_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1467{
1468 int nr_iov, c;
1469 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1470
4c7b7e9b 1471 ctx->blk = blk;
37546ff2 1472 while ((c = getopt(argc, argv, "CP:iqv")) != -1) {
797ac58c
KW
1473 switch (c) {
1474 case 'C':
dc38852a 1475 ctx->Cflag = true;
797ac58c
KW
1476 break;
1477 case 'P':
dc38852a 1478 ctx->Pflag = true;
797ac58c
KW
1479 ctx->pattern = parse_pattern(optarg);
1480 if (ctx->pattern < 0) {
1481 g_free(ctx);
b32d7a39 1482 return -EINVAL;
797ac58c
KW
1483 }
1484 break;
37546ff2
EB
1485 case 'i':
1486 printf("injecting invalid read request\n");
1487 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1488 g_free(ctx);
b32d7a39 1489 return 0;
797ac58c 1490 case 'q':
dc38852a 1491 ctx->qflag = true;
797ac58c
KW
1492 break;
1493 case 'v':
dc38852a 1494 ctx->vflag = true;
797ac58c
KW
1495 break;
1496 default:
1497 g_free(ctx);
b444d0e9 1498 qemuio_command_usage(&aio_read_cmd);
b32d7a39 1499 return -EINVAL;
797ac58c
KW
1500 }
1501 }
1502
1503 if (optind > argc - 2) {
1504 g_free(ctx);
b444d0e9 1505 qemuio_command_usage(&aio_read_cmd);
b32d7a39 1506 return -EINVAL;
797ac58c
KW
1507 }
1508
1509 ctx->offset = cvtnum(argv[optind]);
1510 if (ctx->offset < 0) {
b32d7a39
HR
1511 int ret = ctx->offset;
1512 print_cvtnum_err(ret, argv[optind]);
797ac58c 1513 g_free(ctx);
b32d7a39 1514 return ret;
797ac58c
KW
1515 }
1516 optind++;
1517
797ac58c 1518 nr_iov = argc - optind;
4c7b7e9b 1519 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
797ac58c 1520 if (ctx->buf == NULL) {
556c2b60 1521 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
797ac58c 1522 g_free(ctx);
b32d7a39 1523 return -EINVAL;
797ac58c
KW
1524 }
1525
50290c00 1526 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
4c7b7e9b
HR
1527 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1528 BLOCK_ACCT_READ);
7b3f9712 1529 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
b32d7a39 1530 return 0;
797ac58c
KW
1531}
1532
1533static void aio_write_help(void)
1534{
1535 printf(
1536"\n"
1537" asynchronously writes a range of bytes from the given offset source\n"
1538" from multiple buffers\n"
1539"\n"
1540" Example:\n"
1541" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1542"\n"
1543" Writes into a segment of the currently open file, using a buffer\n"
1544" filled with a set pattern (0xcdcdcdcd).\n"
1545" The write is performed asynchronously and the aio_flush command must be\n"
1546" used to ensure all outstanding aio requests have been completed.\n"
b32d7a39
HR
1547" Note that due to its asynchronous nature, this command will be\n"
1548" considered successful once the request is submitted, independently\n"
1549" of potential I/O errors or pattern mismatches.\n"
797ac58c
KW
1550" -P, -- use different pattern to fill file\n"
1551" -C, -- report statistics in a machine parsable format\n"
770e0e0e 1552" -f, -- use Force Unit Access semantics\n"
37546ff2 1553" -i, -- treat request as invalid, for exercising stats\n"
797ac58c 1554" -q, -- quiet mode, do not show I/O statistics\n"
c2e001cc 1555" -u, -- with -z, allow unmapping\n"
d004bd52 1556" -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
797ac58c
KW
1557"\n");
1558}
1559
b32d7a39 1560static int aio_write_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1561
1562static const cmdinfo_t aio_write_cmd = {
1563 .name = "aio_write",
1564 .cfunc = aio_write_f,
887354bd 1565 .perm = BLK_PERM_WRITE,
797ac58c
KW
1566 .argmin = 2,
1567 .argmax = -1,
37546ff2 1568 .args = "[-Cfiquz] [-P pattern] off len [len..]",
797ac58c
KW
1569 .oneline = "asynchronously writes a number of bytes",
1570 .help = aio_write_help,
1571};
1572
b32d7a39 1573static int aio_write_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1574{
1575 int nr_iov, c;
1576 int pattern = 0xcd;
1577 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
770e0e0e 1578 int flags = 0;
797ac58c 1579
4c7b7e9b 1580 ctx->blk = blk;
37546ff2 1581 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
797ac58c
KW
1582 switch (c) {
1583 case 'C':
dc38852a 1584 ctx->Cflag = true;
797ac58c 1585 break;
770e0e0e
EB
1586 case 'f':
1587 flags |= BDRV_REQ_FUA;
1588 break;
797ac58c 1589 case 'q':
dc38852a 1590 ctx->qflag = true;
797ac58c 1591 break;
c2e001cc
EB
1592 case 'u':
1593 flags |= BDRV_REQ_MAY_UNMAP;
1594 break;
797ac58c
KW
1595 case 'P':
1596 pattern = parse_pattern(optarg);
1597 if (pattern < 0) {
1598 g_free(ctx);
b32d7a39 1599 return -EINVAL;
797ac58c
KW
1600 }
1601 break;
37546ff2
EB
1602 case 'i':
1603 printf("injecting invalid write request\n");
1604 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1605 g_free(ctx);
b32d7a39 1606 return 0;
5ceb7765 1607 case 'z':
dc38852a 1608 ctx->zflag = true;
5ceb7765 1609 break;
797ac58c
KW
1610 default:
1611 g_free(ctx);
b444d0e9 1612 qemuio_command_usage(&aio_write_cmd);
b32d7a39 1613 return -EINVAL;
797ac58c
KW
1614 }
1615 }
1616
1617 if (optind > argc - 2) {
1618 g_free(ctx);
b444d0e9 1619 qemuio_command_usage(&aio_write_cmd);
b32d7a39 1620 return -EINVAL;
797ac58c
KW
1621 }
1622
5ceb7765
KW
1623 if (ctx->zflag && optind != argc - 2) {
1624 printf("-z supports only a single length parameter\n");
1625 g_free(ctx);
b32d7a39 1626 return -EINVAL;
5ceb7765
KW
1627 }
1628
c2e001cc
EB
1629 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
1630 printf("-u requires -z to be specified\n");
4ca1d340 1631 g_free(ctx);
b32d7a39 1632 return -EINVAL;
c2e001cc
EB
1633 }
1634
5ceb7765
KW
1635 if (ctx->zflag && ctx->Pflag) {
1636 printf("-z and -P cannot be specified at the same time\n");
1637 g_free(ctx);
b32d7a39 1638 return -EINVAL;
5ceb7765
KW
1639 }
1640
797ac58c
KW
1641 ctx->offset = cvtnum(argv[optind]);
1642 if (ctx->offset < 0) {
b32d7a39
HR
1643 int ret = ctx->offset;
1644 print_cvtnum_err(ret, argv[optind]);
797ac58c 1645 g_free(ctx);
b32d7a39 1646 return ret;
797ac58c
KW
1647 }
1648 optind++;
1649
5ceb7765
KW
1650 if (ctx->zflag) {
1651 int64_t count = cvtnum(argv[optind]);
1652 if (count < 0) {
1653 print_cvtnum_err(count, argv[optind]);
0e01b76e 1654 g_free(ctx);
b32d7a39 1655 return count;
5ceb7765 1656 }
797ac58c 1657
5ceb7765 1658 ctx->qiov.size = count;
d004bd52
EB
1659 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done,
1660 ctx);
5ceb7765
KW
1661 } else {
1662 nr_iov = argc - optind;
1663 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
1664 pattern);
1665 if (ctx->buf == NULL) {
1666 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1667 g_free(ctx);
b32d7a39 1668 return -EINVAL;
5ceb7765
KW
1669 }
1670
50290c00 1671 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
5ceb7765
KW
1672 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1673 BLOCK_ACCT_WRITE);
1674
770e0e0e
EB
1675 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
1676 ctx);
5ceb7765 1677 }
b32d7a39
HR
1678
1679 return 0;
797ac58c
KW
1680}
1681
b32d7a39 1682static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1683{
556c2b60
AG
1684 BlockAcctCookie cookie;
1685 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
4c7b7e9b 1686 blk_drain_all();
556c2b60 1687 block_acct_done(blk_get_stats(blk), &cookie);
b32d7a39 1688 return 0;
797ac58c
KW
1689}
1690
1691static const cmdinfo_t aio_flush_cmd = {
1692 .name = "aio_flush",
1693 .cfunc = aio_flush_f,
1694 .oneline = "completes all outstanding aio requests"
1695};
1696
b32d7a39 1697static int flush_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1698{
b32d7a39 1699 return blk_flush(blk);
797ac58c
KW
1700}
1701
1702static const cmdinfo_t flush_cmd = {
1703 .name = "flush",
1704 .altname = "f",
1705 .cfunc = flush_f,
1706 .oneline = "flush all in-core file state to disk",
1707};
1708
42ba0225
VSO
1709static int truncate_f(BlockBackend *blk, int argc, char **argv);
1710static const cmdinfo_t truncate_cmd = {
1711 .name = "truncate",
1712 .altname = "t",
1713 .cfunc = truncate_f,
1714 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
1715 .argmin = 1,
1716 .argmax = 3,
1717 .args = "[-m prealloc_mode] off",
1718 .oneline = "truncates the current file at the given offset",
1719};
1720
b32d7a39 1721static int truncate_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1722{
ed3d2ec9 1723 Error *local_err = NULL;
797ac58c 1724 int64_t offset;
42ba0225
VSO
1725 int c, ret;
1726 PreallocMode prealloc = PREALLOC_MODE_OFF;
797ac58c 1727
42ba0225
VSO
1728 while ((c = getopt(argc, argv, "m:")) != -1) {
1729 switch (c) {
1730 case 'm':
1731 prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
1732 PREALLOC_MODE__MAX, NULL);
1733 if (prealloc == PREALLOC_MODE__MAX) {
1734 error_report("Invalid preallocation mode '%s'", optarg);
1735 return -EINVAL;
1736 }
1737 break;
1738 default:
1739 qemuio_command_usage(&truncate_cmd);
1740 return -EINVAL;
1741 }
1742 }
1743
1744 offset = cvtnum(argv[optind]);
797ac58c 1745 if (offset < 0) {
a9ecfa00 1746 print_cvtnum_err(offset, argv[1]);
b32d7a39 1747 return offset;
797ac58c
KW
1748 }
1749
e8d04f92
HR
1750 /*
1751 * qemu-io is a debugging tool, so let us be strict here and pass
1752 * exact=true. It is better to err on the "emit more errors" side
1753 * than to be overly permissive.
1754 */
42ba0225 1755 ret = blk_truncate(blk, offset, false, prealloc, 0, &local_err);
797ac58c 1756 if (ret < 0) {
ed3d2ec9 1757 error_report_err(local_err);
b32d7a39 1758 return ret;
797ac58c 1759 }
b32d7a39
HR
1760
1761 return 0;
797ac58c
KW
1762}
1763
b32d7a39 1764static int length_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1765{
1766 int64_t size;
1767 char s1[64];
1768
4c7b7e9b 1769 size = blk_getlength(blk);
797ac58c
KW
1770 if (size < 0) {
1771 printf("getlength: %s\n", strerror(-size));
b32d7a39 1772 return size;
797ac58c
KW
1773 }
1774
1775 cvtstr(size, s1, sizeof(s1));
1776 printf("%s\n", s1);
b32d7a39 1777 return 0;
797ac58c
KW
1778}
1779
1780
1781static const cmdinfo_t length_cmd = {
1782 .name = "length",
1783 .altname = "l",
1784 .cfunc = length_f,
1785 .oneline = "gets the length of the current file",
1786};
1787
1788
b32d7a39 1789static int info_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1790{
4c7b7e9b 1791 BlockDriverState *bs = blk_bs(blk);
797ac58c 1792 BlockDriverInfo bdi;
a8d8ecb7 1793 ImageInfoSpecific *spec_info;
1bf6e9ca 1794 Error *local_err = NULL;
797ac58c
KW
1795 char s1[64], s2[64];
1796 int ret;
1797
1798 if (bs->drv && bs->drv->format_name) {
1799 printf("format name: %s\n", bs->drv->format_name);
1800 }
1801 if (bs->drv && bs->drv->protocol_name) {
1802 printf("format name: %s\n", bs->drv->protocol_name);
1803 }
1804
1805 ret = bdrv_get_info(bs, &bdi);
1806 if (ret) {
b32d7a39 1807 return ret;
797ac58c
KW
1808 }
1809
1810 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1811 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1812
1813 printf("cluster size: %s\n", s1);
1814 printf("vm state offset: %s\n", s2);
1815
1bf6e9ca
AS
1816 spec_info = bdrv_get_specific_info(bs, &local_err);
1817 if (local_err) {
1818 error_report_err(local_err);
1819 return -EIO;
1820 }
a8d8ecb7
HR
1821 if (spec_info) {
1822 printf("Format specific information:\n");
e1ce7d74 1823 bdrv_image_info_specific_dump(spec_info);
a8d8ecb7
HR
1824 qapi_free_ImageInfoSpecific(spec_info);
1825 }
b32d7a39
HR
1826
1827 return 0;
797ac58c
KW
1828}
1829
1830
1831
1832static const cmdinfo_t info_cmd = {
1833 .name = "info",
1834 .altname = "i",
1835 .cfunc = info_f,
1836 .oneline = "prints information about the current file",
1837};
1838
1839static void discard_help(void)
1840{
1841 printf(
1842"\n"
1843" discards a range of bytes from the given offset\n"
1844"\n"
1845" Example:\n"
1846" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1847"\n"
1848" Discards a segment of the currently open file.\n"
1849" -C, -- report statistics in a machine parsable format\n"
1850" -q, -- quiet mode, do not show I/O statistics\n"
1851"\n");
1852}
1853
b32d7a39 1854static int discard_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1855
1856static const cmdinfo_t discard_cmd = {
1857 .name = "discard",
1858 .altname = "d",
1859 .cfunc = discard_f,
887354bd 1860 .perm = BLK_PERM_WRITE,
797ac58c
KW
1861 .argmin = 2,
1862 .argmax = -1,
1863 .args = "[-Cq] off len",
1864 .oneline = "discards a number of bytes at a specified offset",
1865 .help = discard_help,
1866};
1867
b32d7a39 1868static int discard_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1869{
50290c00 1870 struct timespec t1, t2;
dc38852a 1871 bool Cflag = false, qflag = false;
797ac58c 1872 int c, ret;
f5a5ca79 1873 int64_t offset, bytes;
797ac58c 1874
b062ad86 1875 while ((c = getopt(argc, argv, "Cq")) != -1) {
797ac58c
KW
1876 switch (c) {
1877 case 'C':
dc38852a 1878 Cflag = true;
797ac58c
KW
1879 break;
1880 case 'q':
dc38852a 1881 qflag = true;
797ac58c
KW
1882 break;
1883 default:
b444d0e9 1884 qemuio_command_usage(&discard_cmd);
b32d7a39 1885 return -EINVAL;
797ac58c
KW
1886 }
1887 }
1888
1889 if (optind != argc - 2) {
b444d0e9 1890 qemuio_command_usage(&discard_cmd);
b32d7a39 1891 return -EINVAL;
797ac58c
KW
1892 }
1893
1894 offset = cvtnum(argv[optind]);
1895 if (offset < 0) {
a9ecfa00 1896 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1897 return offset;
797ac58c
KW
1898 }
1899
1900 optind++;
f5a5ca79
MP
1901 bytes = cvtnum(argv[optind]);
1902 if (bytes < 0) {
1903 print_cvtnum_err(bytes, argv[optind]);
b32d7a39 1904 return bytes;
41ae31e3 1905 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 1906 printf("length cannot exceed %"PRIu64", given %s\n",
41ae31e3 1907 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 1908 return -EINVAL;
797ac58c
KW
1909 }
1910
50290c00 1911 clock_gettime(CLOCK_MONOTONIC, &t1);
f5a5ca79 1912 ret = blk_pdiscard(blk, offset, bytes);
50290c00 1913 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c
KW
1914
1915 if (ret < 0) {
1916 printf("discard failed: %s\n", strerror(-ret));
b32d7a39 1917 return ret;
797ac58c
KW
1918 }
1919
1920 /* Finally, report back -- -C gives a parsable format */
1921 if (!qflag) {
1922 t2 = tsub(t2, t1);
f5a5ca79 1923 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
797ac58c 1924 }
b32d7a39
HR
1925
1926 return 0;
797ac58c
KW
1927}
1928
b32d7a39 1929static int alloc_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1930{
4c7b7e9b 1931 BlockDriverState *bs = blk_bs(blk);
d6a644bb 1932 int64_t offset, start, remaining, count;
797ac58c 1933 char s1[64];
d6a644bb
EB
1934 int ret;
1935 int64_t num, sum_alloc;
797ac58c 1936
d6a644bb 1937 start = offset = cvtnum(argv[1]);
797ac58c 1938 if (offset < 0) {
a9ecfa00 1939 print_cvtnum_err(offset, argv[1]);
b32d7a39 1940 return offset;
797ac58c
KW
1941 }
1942
1943 if (argc == 3) {
4401fdc7
EB
1944 count = cvtnum(argv[2]);
1945 if (count < 0) {
1946 print_cvtnum_err(count, argv[2]);
b32d7a39 1947 return count;
797ac58c
KW
1948 }
1949 } else {
4401fdc7
EB
1950 count = BDRV_SECTOR_SIZE;
1951 }
797ac58c 1952
d6a644bb 1953 remaining = count;
797ac58c 1954 sum_alloc = 0;
797ac58c 1955 while (remaining) {
d6a644bb 1956 ret = bdrv_is_allocated(bs, offset, remaining, &num);
d663640c
PB
1957 if (ret < 0) {
1958 printf("is_allocated failed: %s\n", strerror(-ret));
b32d7a39 1959 return ret;
d663640c 1960 }
d6a644bb 1961 offset += num;
797ac58c
KW
1962 remaining -= num;
1963 if (ret) {
1964 sum_alloc += num;
1965 }
1966 if (num == 0) {
d6a644bb 1967 count -= remaining;
797ac58c
KW
1968 remaining = 0;
1969 }
1970 }
1971
d6a644bb 1972 cvtstr(start, s1, sizeof(s1));
797ac58c 1973
4401fdc7 1974 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
d6a644bb 1975 sum_alloc, count, s1);
b32d7a39 1976 return 0;
797ac58c
KW
1977}
1978
1979static const cmdinfo_t alloc_cmd = {
1980 .name = "alloc",
1981 .altname = "a",
1982 .argmin = 1,
1983 .argmax = 2,
1984 .cfunc = alloc_f,
4401fdc7
EB
1985 .args = "offset [count]",
1986 .oneline = "checks if offset is allocated in the file",
797ac58c
KW
1987};
1988
1989
d6a644bb
EB
1990static int map_is_allocated(BlockDriverState *bs, int64_t offset,
1991 int64_t bytes, int64_t *pnum)
797ac58c 1992{
d6a644bb 1993 int64_t num;
797ac58c
KW
1994 int ret, firstret;
1995
087f2fb3 1996 ret = bdrv_is_allocated(bs, offset, bytes, &num);
797ac58c
KW
1997 if (ret < 0) {
1998 return ret;
1999 }
2000
2001 firstret = ret;
2002 *pnum = num;
2003
d6a644bb
EB
2004 while (bytes > 0 && ret == firstret) {
2005 offset += num;
2006 bytes -= num;
797ac58c 2007
087f2fb3 2008 ret = bdrv_is_allocated(bs, offset, bytes, &num);
4b25bbc4 2009 if (ret == firstret && num) {
797ac58c
KW
2010 *pnum += num;
2011 } else {
2012 break;
2013 }
2014 }
2015
2016 return firstret;
2017}
2018
b32d7a39 2019static int map_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2020{
d6a644bb 2021 int64_t offset, bytes;
6f3c90af 2022 char s1[64], s2[64];
797ac58c
KW
2023 int64_t num;
2024 int ret;
2025 const char *retstr;
2026
2027 offset = 0;
d6a644bb
EB
2028 bytes = blk_getlength(blk);
2029 if (bytes < 0) {
2030 error_report("Failed to query image length: %s", strerror(-bytes));
b32d7a39 2031 return bytes;
4c7b7e9b
HR
2032 }
2033
d6a644bb
EB
2034 while (bytes) {
2035 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
797ac58c
KW
2036 if (ret < 0) {
2037 error_report("Failed to get allocation status: %s", strerror(-ret));
b32d7a39 2038 return ret;
4b25bbc4
HR
2039 } else if (!num) {
2040 error_report("Unexpected end of image");
b32d7a39 2041 return -EIO;
797ac58c
KW
2042 }
2043
2044 retstr = ret ? " allocated" : "not allocated";
d6a644bb
EB
2045 cvtstr(num, s1, sizeof(s1));
2046 cvtstr(offset, s2, sizeof(s2));
6f3c90af 2047 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
d6a644bb 2048 s1, num, retstr, s2, offset);
797ac58c
KW
2049
2050 offset += num;
d6a644bb
EB
2051 bytes -= num;
2052 }
b32d7a39
HR
2053
2054 return 0;
797ac58c
KW
2055}
2056
2057static const cmdinfo_t map_cmd = {
2058 .name = "map",
2059 .argmin = 0,
2060 .argmax = 0,
2061 .cfunc = map_f,
2062 .args = "",
2063 .oneline = "prints the allocated areas of a file",
2064};
2065
5bbd2e59
KW
2066static void reopen_help(void)
2067{
2068 printf(
2069"\n"
2070" Changes the open options of an already opened image\n"
2071"\n"
2072" Example:\n"
2073" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2074"\n"
2075" -r, -- Reopen the image read-only\n"
ea92203c 2076" -w, -- Reopen the image read-write\n"
5bbd2e59
KW
2077" -c, -- Change the cache mode to the given value\n"
2078" -o, -- Changes block driver options (cf. 'open' command)\n"
2079"\n");
2080}
2081
b32d7a39 2082static int reopen_f(BlockBackend *blk, int argc, char **argv);
5bbd2e59
KW
2083
2084static QemuOptsList reopen_opts = {
2085 .name = "reopen",
2086 .merge_lists = true,
2087 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2088 .desc = {
2089 /* no elements => accept any params */
2090 { /* end of list */ }
2091 },
2092};
2093
2094static const cmdinfo_t reopen_cmd = {
2095 .name = "reopen",
2096 .argmin = 0,
2097 .argmax = -1,
2098 .cfunc = reopen_f,
ea92203c 2099 .args = "[(-r|-w)] [-c cache] [-o options]",
5bbd2e59
KW
2100 .oneline = "reopens an image with new options",
2101 .help = reopen_help,
2102};
2103
b32d7a39 2104static int reopen_f(BlockBackend *blk, int argc, char **argv)
5bbd2e59
KW
2105{
2106 BlockDriverState *bs = blk_bs(blk);
2107 QemuOpts *qopts;
2108 QDict *opts;
2109 int c;
2110 int flags = bs->open_flags;
19dbecdc 2111 bool writethrough = !blk_enable_write_cache(blk);
ea92203c 2112 bool has_rw_option = false;
dc900c35 2113 bool has_cache_option = false;
5bbd2e59
KW
2114 Error *local_err = NULL;
2115
ea92203c 2116 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
5bbd2e59
KW
2117 switch (c) {
2118 case 'c':
19dbecdc 2119 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
5bbd2e59 2120 error_report("Invalid cache option: %s", optarg);
b32d7a39 2121 return -EINVAL;
5bbd2e59 2122 }
dc900c35 2123 has_cache_option = true;
5bbd2e59
KW
2124 break;
2125 case 'o':
2126 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2127 qemu_opts_reset(&reopen_opts);
b32d7a39 2128 return -EINVAL;
5bbd2e59
KW
2129 }
2130 break;
2131 case 'r':
ea92203c
KW
2132 if (has_rw_option) {
2133 error_report("Only one -r/-w option may be given");
b32d7a39 2134 return -EINVAL;
ea92203c 2135 }
5bbd2e59 2136 flags &= ~BDRV_O_RDWR;
ea92203c
KW
2137 has_rw_option = true;
2138 break;
2139 case 'w':
2140 if (has_rw_option) {
2141 error_report("Only one -r/-w option may be given");
b32d7a39 2142 return -EINVAL;
ea92203c
KW
2143 }
2144 flags |= BDRV_O_RDWR;
2145 has_rw_option = true;
5bbd2e59
KW
2146 break;
2147 default:
2148 qemu_opts_reset(&reopen_opts);
b444d0e9 2149 qemuio_command_usage(&reopen_cmd);
b32d7a39 2150 return -EINVAL;
5bbd2e59
KW
2151 }
2152 }
2153
2154 if (optind != argc) {
2155 qemu_opts_reset(&reopen_opts);
b444d0e9 2156 qemuio_command_usage(&reopen_cmd);
b32d7a39 2157 return -EINVAL;
5bbd2e59
KW
2158 }
2159
a8003ec4 2160 if (!writethrough != blk_enable_write_cache(blk) &&
19dbecdc
KW
2161 blk_get_attached_dev(blk))
2162 {
2163 error_report("Cannot change cache.writeback: Device attached");
2164 qemu_opts_reset(&reopen_opts);
b32d7a39 2165 return -EBUSY;
19dbecdc
KW
2166 }
2167
f3adefb2
KW
2168 if (!(flags & BDRV_O_RDWR)) {
2169 uint64_t orig_perm, orig_shared_perm;
2170
2171 bdrv_drain(bs);
2172
2173 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2174 blk_set_perm(blk,
2175 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2176 orig_shared_perm,
2177 &error_abort);
2178 }
2179
5bbd2e59 2180 qopts = qemu_opts_find(&reopen_opts, NULL);
dc900c35 2181 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
5bbd2e59
KW
2182 qemu_opts_reset(&reopen_opts);
2183
dc900c35
AG
2184 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2185 if (has_rw_option) {
2186 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2187 qobject_unref(opts);
2188 return -EINVAL;
2189 }
2190 } else {
2191 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2192 }
2193
2194 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2195 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2196 if (has_cache_option) {
2197 error_report("Cannot set both -c and the cache options");
2198 qobject_unref(opts);
2199 return -EINVAL;
2200 }
2201 } else {
2202 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2203 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2204 }
2205
6cf42ca2 2206 bdrv_reopen(bs, opts, true, &local_err);
1a63a907 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
78632a3d
VSO
2460/*
2461 * Called with aio context of blk acquired. Or with qemu_get_aio_context()
2462 * context acquired if blk is NULL.
2463 */
b32d7a39 2464int qemuio_command(BlockBackend *blk, const char *cmd)
dd583296
KW
2465{
2466 char *input;
2467 const cmdinfo_t *ct;
2468 char **v;
2469 int c;
b32d7a39 2470 int ret = 0;
dd583296
KW
2471
2472 input = g_strdup(cmd);
2473 v = breakline(input, &c);
2474 if (c) {
2475 ct = find_command(v[0]);
2476 if (ct) {
b32d7a39 2477 ret = command(blk, ct, c, v);
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}