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