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