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