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