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