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