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