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