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