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