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