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