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