import source from 0.14.1
[adaptation/panda/qemu-arm-static.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_blockalign(bs, 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                 int64_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 > INT_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, -- quiet 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, -- quiet 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, -- quiet 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, -- quiet 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, -- quiet 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                                 free(ctx);
1136                                 return 0;
1137                         }
1138                         break;
1139                 case 'q':
1140                         ctx->qflag = 1;
1141                         break;
1142                 case 'v':
1143                         ctx->vflag = 1;
1144                         break;
1145                 default:
1146                         free(ctx);
1147                         return command_usage(&aio_read_cmd);
1148                 }
1149         }
1150
1151         if (optind > argc - 2) {
1152                 free(ctx);
1153                 return command_usage(&aio_read_cmd);
1154         }
1155
1156         ctx->offset = cvtnum(argv[optind]);
1157         if (ctx->offset < 0) {
1158                 printf("non-numeric length argument -- %s\n", argv[optind]);
1159                 free(ctx);
1160                 return 0;
1161         }
1162         optind++;
1163
1164         if (ctx->offset & 0x1ff) {
1165                 printf("offset %" PRId64 " is not sector aligned\n",
1166                        ctx->offset);
1167                 free(ctx);
1168                 return 0;
1169         }
1170
1171         nr_iov = argc - optind;
1172         ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
1173
1174         gettimeofday(&ctx->t1, NULL);
1175         acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1176                               ctx->qiov.size >> 9, aio_read_done, ctx);
1177         if (!acb) {
1178                 free(ctx->buf);
1179                 free(ctx);
1180                 return -EIO;
1181         }
1182
1183         return 0;
1184 }
1185
1186 static void
1187 aio_write_help(void)
1188 {
1189         printf(
1190 "\n"
1191 " asynchronously writes a range of bytes from the given offset source \n"
1192 " from multiple buffers\n"
1193 "\n"
1194 " Example:\n"
1195 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1196 "\n"
1197 " Writes into a segment of the currently open file, using a buffer\n"
1198 " filled with a set pattern (0xcdcdcdcd).\n"
1199 " The write is performed asynchronously and the aio_flush command must be\n"
1200 " used to ensure all outstanding aio requests have been completed\n"
1201 " -P, -- use different pattern to fill file\n"
1202 " -C, -- report statistics in a machine parsable format\n"
1203 " -q, -- quiet mode, do not show I/O statistics\n"
1204 "\n");
1205 }
1206
1207 static int aio_write_f(int argc, char **argv);
1208
1209 static const cmdinfo_t aio_write_cmd = {
1210         .name           = "aio_write",
1211         .cfunc          = aio_write_f,
1212         .argmin         = 2,
1213         .argmax         = -1,
1214         .args           = "[-Cq] [-P pattern ] off len [len..]",
1215         .oneline        = "asynchronously writes a number of bytes",
1216         .help           = aio_write_help,
1217 };
1218
1219 static int
1220 aio_write_f(int argc, char **argv)
1221 {
1222         int nr_iov, c;
1223         int pattern = 0xcd;
1224         struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
1225         BlockDriverAIOCB *acb;
1226
1227         while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1228                 switch (c) {
1229                 case 'C':
1230                         ctx->Cflag = 1;
1231                         break;
1232                 case 'q':
1233                         ctx->qflag = 1;
1234                         break;
1235                 case 'P':
1236                         pattern = parse_pattern(optarg);
1237                         if (pattern < 0)
1238                                 return 0;
1239                         break;
1240                 default:
1241                         free(ctx);
1242                         return command_usage(&aio_write_cmd);
1243                 }
1244         }
1245
1246         if (optind > argc - 2) {
1247                 free(ctx);
1248                 return command_usage(&aio_write_cmd);
1249         }
1250
1251         ctx->offset = cvtnum(argv[optind]);
1252         if (ctx->offset < 0) {
1253                 printf("non-numeric length argument -- %s\n", argv[optind]);
1254                 free(ctx);
1255                 return 0;
1256         }
1257         optind++;
1258
1259         if (ctx->offset & 0x1ff) {
1260                 printf("offset %" PRId64 " is not sector aligned\n",
1261                        ctx->offset);
1262                 free(ctx);
1263                 return 0;
1264         }
1265
1266         nr_iov = argc - optind;
1267         ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
1268
1269         gettimeofday(&ctx->t1, NULL);
1270         acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1271                               ctx->qiov.size >> 9, aio_write_done, ctx);
1272         if (!acb) {
1273                 free(ctx->buf);
1274                 free(ctx);
1275                 return -EIO;
1276         }
1277
1278         return 0;
1279 }
1280
1281 static int
1282 aio_flush_f(int argc, char **argv)
1283 {
1284         qemu_aio_flush();
1285         return 0;
1286 }
1287
1288 static const cmdinfo_t aio_flush_cmd = {
1289         .name           = "aio_flush",
1290         .cfunc          = aio_flush_f,
1291         .oneline        = "completes all outstanding aio requests"
1292 };
1293
1294 static int
1295 flush_f(int argc, char **argv)
1296 {
1297         bdrv_flush(bs);
1298         return 0;
1299 }
1300
1301 static const cmdinfo_t flush_cmd = {
1302         .name           = "flush",
1303         .altname        = "f",
1304         .cfunc          = flush_f,
1305         .oneline        = "flush all in-core file state to disk",
1306 };
1307
1308 static int
1309 truncate_f(int argc, char **argv)
1310 {
1311         int64_t offset;
1312         int ret;
1313
1314         offset = cvtnum(argv[1]);
1315         if (offset < 0) {
1316                 printf("non-numeric truncate argument -- %s\n", argv[1]);
1317                 return 0;
1318         }
1319
1320         ret = bdrv_truncate(bs, offset);
1321         if (ret < 0) {
1322                 printf("truncate: %s\n", strerror(-ret));
1323                 return 0;
1324         }
1325
1326         return 0;
1327 }
1328
1329 static const cmdinfo_t truncate_cmd = {
1330         .name           = "truncate",
1331         .altname        = "t",
1332         .cfunc          = truncate_f,
1333         .argmin         = 1,
1334         .argmax         = 1,
1335         .args           = "off",
1336         .oneline        = "truncates the current file at the given offset",
1337 };
1338
1339 static int
1340 length_f(int argc, char **argv)
1341 {
1342         int64_t size;
1343         char s1[64];
1344
1345         size = bdrv_getlength(bs);
1346         if (size < 0) {
1347                 printf("getlength: %s\n", strerror(-size));
1348                 return 0;
1349         }
1350
1351         cvtstr(size, s1, sizeof(s1));
1352         printf("%s\n", s1);
1353         return 0;
1354 }
1355
1356
1357 static const cmdinfo_t length_cmd = {
1358         .name           = "length",
1359         .altname        = "l",
1360         .cfunc          = length_f,
1361         .oneline        = "gets the length of the current file",
1362 };
1363
1364
1365 static int
1366 info_f(int argc, char **argv)
1367 {
1368         BlockDriverInfo bdi;
1369         char s1[64], s2[64];
1370         int ret;
1371
1372         if (bs->drv && bs->drv->format_name)
1373                 printf("format name: %s\n", bs->drv->format_name);
1374         if (bs->drv && bs->drv->protocol_name)
1375                 printf("format name: %s\n", bs->drv->protocol_name);
1376
1377         ret = bdrv_get_info(bs, &bdi);
1378         if (ret)
1379                 return 0;
1380
1381         cvtstr(bdi.cluster_size, s1, sizeof(s1));
1382         cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1383
1384         printf("cluster size: %s\n", s1);
1385         printf("vm state offset: %s\n", s2);
1386
1387         return 0;
1388 }
1389
1390
1391
1392 static const cmdinfo_t info_cmd = {
1393         .name           = "info",
1394         .altname        = "i",
1395         .cfunc          = info_f,
1396         .oneline        = "prints information about the current file",
1397 };
1398
1399 static void
1400 discard_help(void)
1401 {
1402         printf(
1403 "\n"
1404 " discards a range of bytes from the given offset\n"
1405 "\n"
1406 " Example:\n"
1407 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1408 "\n"
1409 " Discards a segment of the currently open file.\n"
1410 " -C, -- report statistics in a machine parsable format\n"
1411 " -q, -- quiet mode, do not show I/O statistics\n"
1412 "\n");
1413 }
1414
1415 static int discard_f(int argc, char **argv);
1416
1417 static const cmdinfo_t discard_cmd = {
1418         .name           = "discard",
1419         .altname        = "d",
1420         .cfunc          = discard_f,
1421         .argmin         = 2,
1422         .argmax         = -1,
1423         .args           = "[-Cq] off len",
1424         .oneline        = "discards a number of bytes at a specified offset",
1425         .help           = discard_help,
1426 };
1427
1428 static int
1429 discard_f(int argc, char **argv)
1430 {
1431         struct timeval t1, t2;
1432         int Cflag = 0, qflag = 0;
1433         int c, ret;
1434         int64_t offset;
1435         int count;
1436
1437         while ((c = getopt(argc, argv, "Cq")) != EOF) {
1438                 switch (c) {
1439                 case 'C':
1440                         Cflag = 1;
1441                         break;
1442                 case 'q':
1443                         qflag = 1;
1444                         break;
1445                 default:
1446                         return command_usage(&discard_cmd);
1447                 }
1448         }
1449
1450         if (optind != argc - 2) {
1451                 return command_usage(&discard_cmd);
1452         }
1453
1454         offset = cvtnum(argv[optind]);
1455         if (offset < 0) {
1456                 printf("non-numeric length argument -- %s\n", argv[optind]);
1457                 return 0;
1458         }
1459
1460         optind++;
1461         count = cvtnum(argv[optind]);
1462         if (count < 0) {
1463                 printf("non-numeric length argument -- %s\n", argv[optind]);
1464                 return 0;
1465         }
1466
1467         gettimeofday(&t1, NULL);
1468         ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, count >> BDRV_SECTOR_BITS);
1469         gettimeofday(&t2, NULL);
1470
1471         if (ret < 0) {
1472                 printf("discard failed: %s\n", strerror(-ret));
1473                 goto out;
1474         }
1475
1476         /* Finally, report back -- -C gives a parsable format */
1477         if (!qflag) {
1478                 t2 = tsub(t2, t1);
1479                 print_report("discard", &t2, offset, count, count, 1, Cflag);
1480         }
1481
1482 out:
1483         return 0;
1484 }
1485
1486 static int
1487 alloc_f(int argc, char **argv)
1488 {
1489         int64_t offset;
1490         int nb_sectors, remaining;
1491         char s1[64];
1492         int num, sum_alloc;
1493         int ret;
1494
1495         offset = cvtnum(argv[1]);
1496         if (offset & 0x1ff) {
1497                 printf("offset %" PRId64 " is not sector aligned\n",
1498                        offset);
1499                 return 0;
1500         }
1501
1502         if (argc == 3)
1503                 nb_sectors = cvtnum(argv[2]);
1504         else
1505                 nb_sectors = 1;
1506
1507         remaining = nb_sectors;
1508         sum_alloc = 0;
1509         while (remaining) {
1510                 ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
1511                 remaining -= num;
1512                 if (ret) {
1513                         sum_alloc += num;
1514                 }
1515         }
1516
1517         cvtstr(offset, s1, sizeof(s1));
1518
1519         printf("%d/%d sectors allocated at offset %s\n",
1520                sum_alloc, nb_sectors, s1);
1521         return 0;
1522 }
1523
1524 static const cmdinfo_t alloc_cmd = {
1525         .name           = "alloc",
1526         .altname        = "a",
1527         .argmin         = 1,
1528         .argmax         = 2,
1529         .cfunc          = alloc_f,
1530         .args           = "off [sectors]",
1531         .oneline        = "checks if a sector is present in the file",
1532 };
1533
1534 static int
1535 map_f(int argc, char **argv)
1536 {
1537         int64_t offset;
1538         int64_t nb_sectors;
1539         char s1[64];
1540         int num, num_checked;
1541         int ret;
1542         const char *retstr;
1543
1544         offset = 0;
1545         nb_sectors = bs->total_sectors;
1546
1547         do {
1548                 num_checked = MIN(nb_sectors, INT_MAX);
1549                 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
1550                 retstr = ret ? "    allocated" : "not allocated";
1551                 cvtstr(offset << 9ULL, s1, sizeof(s1));
1552                 printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
1553                                 offset << 9ULL, num, num_checked, retstr, s1, ret);
1554
1555                 offset += num;
1556                 nb_sectors -= num;
1557         } while(offset < bs->total_sectors);
1558
1559         return 0;
1560 }
1561
1562 static const cmdinfo_t map_cmd = {
1563        .name           = "map",
1564        .argmin         = 0,
1565        .argmax         = 0,
1566        .cfunc          = map_f,
1567        .args           = "",
1568        .oneline        = "prints the allocated areas of a file",
1569 };
1570
1571
1572 static int
1573 close_f(int argc, char **argv)
1574 {
1575         bdrv_close(bs);
1576         bs = NULL;
1577         return 0;
1578 }
1579
1580 static const cmdinfo_t close_cmd = {
1581         .name           = "close",
1582         .altname        = "c",
1583         .cfunc          = close_f,
1584         .oneline        = "close the current open file",
1585 };
1586
1587 static int openfile(char *name, int flags, int growable)
1588 {
1589         if (bs) {
1590                 fprintf(stderr, "file open already, try 'help close'\n");
1591                 return 1;
1592         }
1593
1594         if (growable) {
1595                 if (bdrv_file_open(&bs, name, flags)) {
1596                         fprintf(stderr, "%s: can't open device %s\n", progname, name);
1597                         return 1;
1598                 }
1599         } else {
1600                 bs = bdrv_new("hda");
1601
1602                 if (bdrv_open(bs, name, flags, NULL) < 0) {
1603                         fprintf(stderr, "%s: can't open device %s\n", progname, name);
1604                         bs = NULL;
1605                         return 1;
1606                 }
1607         }
1608
1609         return 0;
1610 }
1611
1612 static void
1613 open_help(void)
1614 {
1615         printf(
1616 "\n"
1617 " opens a new file in the requested mode\n"
1618 "\n"
1619 " Example:\n"
1620 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
1621 "\n"
1622 " Opens a file for subsequent use by all of the other qemu-io commands.\n"
1623 " -r, -- open file read-only\n"
1624 " -s, -- use snapshot file\n"
1625 " -n, -- disable host cache\n"
1626 " -g, -- allow file to grow (only applies to protocols)"
1627 "\n");
1628 }
1629
1630 static int open_f(int argc, char **argv);
1631
1632 static const cmdinfo_t open_cmd = {
1633         .name           = "open",
1634         .altname        = "o",
1635         .cfunc          = open_f,
1636         .argmin         = 1,
1637         .argmax         = -1,
1638         .flags          = CMD_NOFILE_OK,
1639         .args           = "[-Crsn] [path]",
1640         .oneline        = "open the file specified by path",
1641         .help           = open_help,
1642 };
1643
1644 static int
1645 open_f(int argc, char **argv)
1646 {
1647         int flags = 0;
1648         int readonly = 0;
1649         int growable = 0;
1650         int c;
1651
1652         while ((c = getopt(argc, argv, "snrg")) != EOF) {
1653                 switch (c) {
1654                 case 's':
1655                         flags |= BDRV_O_SNAPSHOT;
1656                         break;
1657                 case 'n':
1658                         flags |= BDRV_O_NOCACHE;
1659                         break;
1660                 case 'r':
1661                         readonly = 1;
1662                         break;
1663                 case 'g':
1664                         growable = 1;
1665                         break;
1666                 default:
1667                         return command_usage(&open_cmd);
1668                 }
1669         }
1670
1671         if (!readonly) {
1672             flags |= BDRV_O_RDWR;
1673         }
1674
1675         if (optind != argc - 1)
1676                 return command_usage(&open_cmd);
1677
1678         return openfile(argv[optind], flags, growable);
1679 }
1680
1681 static int
1682 init_args_command(
1683         int     index)
1684 {
1685         /* only one device allowed so far */
1686         if (index >= 1)
1687                 return 0;
1688         return ++index;
1689 }
1690
1691 static int
1692 init_check_command(
1693         const cmdinfo_t *ct)
1694 {
1695         if (ct->flags & CMD_FLAG_GLOBAL)
1696                 return 1;
1697         if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1698                 fprintf(stderr, "no file open, try 'help open'\n");
1699                 return 0;
1700         }
1701         return 1;
1702 }
1703
1704 static void usage(const char *name)
1705 {
1706         printf(
1707 "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
1708 "QEMU Disk exerciser\n"
1709 "\n"
1710 "  -c, --cmd            command to execute\n"
1711 "  -r, --read-only      export read-only\n"
1712 "  -s, --snapshot       use snapshot file\n"
1713 "  -n, --nocache        disable host cache\n"
1714 "  -g, --growable       allow file to grow (only applies to protocols)\n"
1715 "  -m, --misalign       misalign allocations for O_DIRECT\n"
1716 "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
1717 "  -h, --help           display this help and exit\n"
1718 "  -V, --version        output version information and exit\n"
1719 "\n",
1720         name);
1721 }
1722
1723
1724 int main(int argc, char **argv)
1725 {
1726         int readonly = 0;
1727         int growable = 0;
1728         const char *sopt = "hVc:rsnmgk";
1729         const struct option lopt[] = {
1730                 { "help", 0, NULL, 'h' },
1731                 { "version", 0, NULL, 'V' },
1732                 { "offset", 1, NULL, 'o' },
1733                 { "cmd", 1, NULL, 'c' },
1734                 { "read-only", 0, NULL, 'r' },
1735                 { "snapshot", 0, NULL, 's' },
1736                 { "nocache", 0, NULL, 'n' },
1737                 { "misalign", 0, NULL, 'm' },
1738                 { "growable", 0, NULL, 'g' },
1739                 { "native-aio", 0, NULL, 'k' },
1740                 { NULL, 0, NULL, 0 }
1741         };
1742         int c;
1743         int opt_index = 0;
1744         int flags = 0;
1745
1746         progname = basename(argv[0]);
1747
1748         while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
1749                 switch (c) {
1750                 case 's':
1751                         flags |= BDRV_O_SNAPSHOT;
1752                         break;
1753                 case 'n':
1754                         flags |= BDRV_O_NOCACHE;
1755                         break;
1756                 case 'c':
1757                         add_user_command(optarg);
1758                         break;
1759                 case 'r':
1760                         readonly = 1;
1761                         break;
1762                 case 'm':
1763                         misalign = 1;
1764                         break;
1765                 case 'g':
1766                         growable = 1;
1767                         break;
1768                 case 'k':
1769                         flags |= BDRV_O_NATIVE_AIO;
1770                         break;
1771                 case 'V':
1772                         printf("%s version %s\n", progname, VERSION);
1773                         exit(0);
1774                 case 'h':
1775                         usage(progname);
1776                         exit(0);
1777                 default:
1778                         usage(progname);
1779                         exit(1);
1780                 }
1781         }
1782
1783         if ((argc - optind) > 1) {
1784                 usage(progname);
1785                 exit(1);
1786         }
1787
1788         bdrv_init();
1789
1790         /* initialize commands */
1791         quit_init();
1792         help_init();
1793         add_command(&open_cmd);
1794         add_command(&close_cmd);
1795         add_command(&read_cmd);
1796         add_command(&readv_cmd);
1797         add_command(&write_cmd);
1798         add_command(&writev_cmd);
1799         add_command(&multiwrite_cmd);
1800         add_command(&aio_read_cmd);
1801         add_command(&aio_write_cmd);
1802         add_command(&aio_flush_cmd);
1803         add_command(&flush_cmd);
1804         add_command(&truncate_cmd);
1805         add_command(&length_cmd);
1806         add_command(&info_cmd);
1807         add_command(&discard_cmd);
1808         add_command(&alloc_cmd);
1809         add_command(&map_cmd);
1810
1811         add_args_command(init_args_command);
1812         add_check_command(init_check_command);
1813
1814         /* open the device */
1815         if (!readonly) {
1816             flags |= BDRV_O_RDWR;
1817         }
1818
1819         if ((argc - optind) == 1)
1820                 openfile(argv[optind], flags, growable);
1821         command_loop();
1822
1823         /*
1824          * Make sure all outstanding requests get flushed the program exits.
1825          */
1826         qemu_aio_flush();
1827
1828         if (bs)
1829                 bdrv_close(bs);
1830         return 0;
1831 }