]> Git Repo - qemu.git/blob - qemu-io.c
lsi: move current_dev into lsi_request
[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("%08llx:  ", (unsigned long long)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 %lld\n",
112                         op, total, count, (long long)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                 long long 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 %lld is not sector aligned\n",
154                                 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
271 static void
272 read_help(void)
273 {
274         printf(
275 "\n"
276 " reads a range of bytes from the given offset\n"
277 "\n"
278 " Example:\n"
279 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
280 "\n"
281 " Reads a segment of the currently open file, optionally dumping it to the\n"
282 " standard output stream (with -v option) for subsequent inspection.\n"
283 " -b, -- read from the VM state rather than the virtual disk\n"
284 " -C, -- report statistics in a machine parsable format\n"
285 " -l, -- length for pattern verification (only with -P)\n"
286 " -p, -- use bdrv_pread to read the file\n"
287 " -P, -- use a pattern to verify read data\n"
288 " -q, -- quite mode, do not show I/O statistics\n"
289 " -s, -- start offset for pattern verification (only with -P)\n"
290 " -v, -- dump buffer to standard output\n"
291 "\n");
292 }
293
294 static int read_f(int argc, char **argv);
295
296 static const cmdinfo_t read_cmd = {
297         .name           = "read",
298         .altname        = "r",
299         .cfunc          = read_f,
300         .argmin         = 2,
301         .argmax         = -1,
302         .args           = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
303         .oneline        = "reads a number of bytes at a specified offset",
304         .help           = read_help,
305 };
306
307 static int
308 read_f(int argc, char **argv)
309 {
310         struct timeval t1, t2;
311         int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
312         int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
313         int c, cnt;
314         char *buf;
315         int64_t offset;
316         int count;
317         /* Some compilers get confused and warn if this is not initialized.  */
318         int total = 0;
319         int pattern = 0, pattern_offset = 0, pattern_count = 0;
320
321         while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
322                 switch (c) {
323                 case 'b':
324                         bflag = 1;
325                         break;
326                 case 'C':
327                         Cflag = 1;
328                         break;
329                 case 'l':
330                         lflag = 1;
331                         pattern_count = cvtnum(optarg);
332                         if (pattern_count < 0) {
333                                 printf("non-numeric length argument -- %s\n", optarg);
334                                 return 0;
335                         }
336                         break;
337                 case 'p':
338                         pflag = 1;
339                         break;
340                 case 'P':
341                         Pflag = 1;
342                         pattern = parse_pattern(optarg);
343                         if (pattern < 0)
344                                 return 0;
345                         break;
346                 case 'q':
347                         qflag = 1;
348                         break;
349                 case 's':
350                         sflag = 1;
351                         pattern_offset = cvtnum(optarg);
352                         if (pattern_offset < 0) {
353                                 printf("non-numeric length argument -- %s\n", optarg);
354                                 return 0;
355                         }
356                         break;
357                 case 'v':
358                         vflag = 1;
359                         break;
360                 default:
361                         return command_usage(&read_cmd);
362                 }
363         }
364
365         if (optind != argc - 2)
366                 return command_usage(&read_cmd);
367
368         if (bflag && pflag) {
369                 printf("-b and -p cannot be specified at the same time\n");
370                 return 0;
371         }
372
373         offset = cvtnum(argv[optind]);
374         if (offset < 0) {
375                 printf("non-numeric length argument -- %s\n", argv[optind]);
376                 return 0;
377         }
378
379         optind++;
380         count = cvtnum(argv[optind]);
381         if (count < 0) {
382                 printf("non-numeric length argument -- %s\n", argv[optind]);
383                 return 0;
384         }
385
386     if (!Pflag && (lflag || sflag)) {
387         return command_usage(&read_cmd);
388     }
389
390     if (!lflag) {
391         pattern_count = count - pattern_offset;
392     }
393
394     if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
395         printf("pattern verfication range exceeds end of read data\n");
396         return 0;
397     }
398
399         if (!pflag)
400                 if (offset & 0x1ff) {
401                         printf("offset %lld is not sector aligned\n",
402                                 (long long)offset);
403                         return 0;
404
405                 if (count & 0x1ff) {
406                         printf("count %d is not sector aligned\n",
407                                 count);
408                         return 0;
409                 }
410         }
411
412         buf = qemu_io_alloc(count, 0xab);
413
414         gettimeofday(&t1, NULL);
415         if (pflag)
416                 cnt = do_pread(buf, offset, count, &total);
417         else if (bflag)
418                 cnt = do_load_vmstate(buf, offset, count, &total);
419         else
420                 cnt = do_read(buf, offset, count, &total);
421         gettimeofday(&t2, NULL);
422
423         if (cnt < 0) {
424                 printf("read failed: %s\n", strerror(-cnt));
425                 goto out;
426         }
427
428         if (Pflag) {
429                 void* cmp_buf = malloc(pattern_count);
430                 memset(cmp_buf, pattern, pattern_count);
431                 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
432                         printf("Pattern verification failed at offset %lld, "
433                                 "%d bytes\n",
434                                 (long long) offset + pattern_offset, pattern_count);
435                 }
436                 free(cmp_buf);
437         }
438
439         if (qflag)
440                 goto out;
441
442         if (vflag)
443                 dump_buffer(buf, offset, count);
444
445         /* Finally, report back -- -C gives a parsable format */
446         t2 = tsub(t2, t1);
447         print_report("read", &t2, offset, count, total, cnt, Cflag);
448
449 out:
450         qemu_io_free(buf);
451
452         return 0;
453 }
454
455 static void
456 readv_help(void)
457 {
458         printf(
459 "\n"
460 " reads a range of bytes from the given offset into multiple buffers\n"
461 "\n"
462 " Example:\n"
463 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
464 "\n"
465 " Reads a segment of the currently open file, optionally dumping it to the\n"
466 " standard output stream (with -v option) for subsequent inspection.\n"
467 " Uses multiple iovec buffers if more than one byte range is specified.\n"
468 " -C, -- report statistics in a machine parsable format\n"
469 " -P, -- use a pattern to verify read data\n"
470 " -v, -- dump buffer to standard output\n"
471 " -q, -- quite mode, do not show I/O statistics\n"
472 "\n");
473 }
474
475 static int readv_f(int argc, char **argv);
476
477 static const cmdinfo_t readv_cmd = {
478         .name           = "readv",
479         .cfunc          = readv_f,
480         .argmin         = 2,
481         .argmax         = -1,
482         .args           = "[-Cqv] [-P pattern ] off len [len..]",
483         .oneline        = "reads a number of bytes at a specified offset",
484         .help           = readv_help,
485 };
486
487 static int
488 readv_f(int argc, char **argv)
489 {
490         struct timeval t1, t2;
491         int Cflag = 0, qflag = 0, vflag = 0;
492         int c, cnt;
493         char *buf;
494         int64_t offset;
495         /* Some compilers get confused and warn if this is not initialized.  */
496         int total = 0;
497         int nr_iov;
498         QEMUIOVector qiov;
499         int pattern = 0;
500         int Pflag = 0;
501
502         while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
503                 switch (c) {
504                 case 'C':
505                         Cflag = 1;
506                         break;
507                 case 'P':
508                         Pflag = 1;
509                         pattern = parse_pattern(optarg);
510                         if (pattern < 0)
511                                 return 0;
512                         break;
513                 case 'q':
514                         qflag = 1;
515                         break;
516                 case 'v':
517                         vflag = 1;
518                         break;
519                 default:
520                         return command_usage(&readv_cmd);
521                 }
522         }
523
524         if (optind > argc - 2)
525                 return command_usage(&readv_cmd);
526
527
528         offset = cvtnum(argv[optind]);
529         if (offset < 0) {
530                 printf("non-numeric length argument -- %s\n", argv[optind]);
531                 return 0;
532         }
533         optind++;
534
535         if (offset & 0x1ff) {
536                 printf("offset %lld is not sector aligned\n",
537                         (long long)offset);
538                 return 0;
539         }
540
541         nr_iov = argc - optind;
542         buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
543
544         gettimeofday(&t1, NULL);
545         cnt = do_aio_readv(&qiov, offset, &total);
546         gettimeofday(&t2, NULL);
547
548         if (cnt < 0) {
549                 printf("readv failed: %s\n", strerror(-cnt));
550                 goto out;
551         }
552
553         if (Pflag) {
554                 void* cmp_buf = malloc(qiov.size);
555                 memset(cmp_buf, pattern, qiov.size);
556                 if (memcmp(buf, cmp_buf, qiov.size)) {
557                         printf("Pattern verification failed at offset %lld, "
558                                 "%zd bytes\n",
559                                 (long long) offset, qiov.size);
560                 }
561                 free(cmp_buf);
562         }
563
564         if (qflag)
565                 goto out;
566
567         if (vflag)
568                 dump_buffer(buf, offset, qiov.size);
569
570         /* Finally, report back -- -C gives a parsable format */
571         t2 = tsub(t2, t1);
572         print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
573
574 out:
575         qemu_io_free(buf);
576         return 0;
577 }
578
579 static void
580 write_help(void)
581 {
582         printf(
583 "\n"
584 " writes a range of bytes from the given offset\n"
585 "\n"
586 " Example:\n"
587 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
588 "\n"
589 " Writes into a segment of the currently open file, using a buffer\n"
590 " filled with a set pattern (0xcdcdcdcd).\n"
591 " -b, -- write to the VM state rather than the virtual disk\n"
592 " -p, -- use bdrv_pwrite to write the file\n"
593 " -P, -- use different pattern to fill file\n"
594 " -C, -- report statistics in a machine parsable format\n"
595 " -q, -- quite mode, do not show I/O statistics\n"
596 "\n");
597 }
598
599 static int write_f(int argc, char **argv);
600
601 static const cmdinfo_t write_cmd = {
602         .name           = "write",
603         .altname        = "w",
604         .cfunc          = write_f,
605         .argmin         = 2,
606         .argmax         = -1,
607         .args           = "[-abCpq] [-P pattern ] off len",
608         .oneline        = "writes a number of bytes at a specified offset",
609         .help           = write_help,
610 };
611
612 static int
613 write_f(int argc, char **argv)
614 {
615         struct timeval t1, t2;
616         int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
617         int c, cnt;
618         char *buf;
619         int64_t offset;
620         int count;
621         /* Some compilers get confused and warn if this is not initialized.  */
622         int total = 0;
623         int pattern = 0xcd;
624
625         while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
626                 switch (c) {
627                 case 'b':
628                         bflag = 1;
629                         break;
630                 case 'C':
631                         Cflag = 1;
632                         break;
633                 case 'p':
634                         pflag = 1;
635                         break;
636                 case 'P':
637                         pattern = parse_pattern(optarg);
638                         if (pattern < 0)
639                                 return 0;
640                         break;
641                 case 'q':
642                         qflag = 1;
643                         break;
644                 default:
645                         return command_usage(&write_cmd);
646                 }
647         }
648
649         if (optind != argc - 2)
650                 return command_usage(&write_cmd);
651
652         if (bflag && pflag) {
653                 printf("-b and -p cannot be specified at the same time\n");
654                 return 0;
655         }
656
657         offset = cvtnum(argv[optind]);
658         if (offset < 0) {
659                 printf("non-numeric length argument -- %s\n", argv[optind]);
660                 return 0;
661         }
662
663         optind++;
664         count = cvtnum(argv[optind]);
665         if (count < 0) {
666                 printf("non-numeric length argument -- %s\n", argv[optind]);
667                 return 0;
668         }
669
670         if (!pflag) {
671                 if (offset & 0x1ff) {
672                         printf("offset %lld is not sector aligned\n",
673                                 (long long)offset);
674                         return 0;
675                 }
676
677                 if (count & 0x1ff) {
678                         printf("count %d is not sector aligned\n",
679                                 count);
680                         return 0;
681                 }
682         }
683
684         buf = qemu_io_alloc(count, pattern);
685
686         gettimeofday(&t1, NULL);
687         if (pflag)
688                 cnt = do_pwrite(buf, offset, count, &total);
689         else if (bflag)
690                 cnt = do_save_vmstate(buf, offset, count, &total);
691         else
692                 cnt = do_write(buf, offset, count, &total);
693         gettimeofday(&t2, NULL);
694
695         if (cnt < 0) {
696                 printf("write failed: %s\n", strerror(-cnt));
697                 goto out;
698         }
699
700         if (qflag)
701                 goto out;
702
703         /* Finally, report back -- -C gives a parsable format */
704         t2 = tsub(t2, t1);
705         print_report("wrote", &t2, offset, count, total, cnt, Cflag);
706
707 out:
708         qemu_io_free(buf);
709
710         return 0;
711 }
712
713 static void
714 writev_help(void)
715 {
716         printf(
717 "\n"
718 " writes a range of bytes from the given offset source from multiple buffers\n"
719 "\n"
720 " Example:\n"
721 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
722 "\n"
723 " Writes into a segment of the currently open file, using a buffer\n"
724 " filled with a set pattern (0xcdcdcdcd).\n"
725 " -P, -- use different pattern to fill file\n"
726 " -C, -- report statistics in a machine parsable format\n"
727 " -q, -- quite mode, do not show I/O statistics\n"
728 "\n");
729 }
730
731 static int writev_f(int argc, char **argv);
732
733 static const cmdinfo_t writev_cmd = {
734         .name           = "writev",
735         .cfunc          = writev_f,
736         .argmin         = 2,
737         .argmax         = -1,
738         .args           = "[-Cq] [-P pattern ] off len [len..]",
739         .oneline        = "writes a number of bytes at a specified offset",
740         .help           = writev_help,
741 };
742
743 static int
744 writev_f(int argc, char **argv)
745 {
746         struct timeval t1, t2;
747         int Cflag = 0, qflag = 0;
748         int c, cnt;
749         char *buf;
750         int64_t offset;
751         /* Some compilers get confused and warn if this is not initialized.  */
752         int total = 0;
753         int nr_iov;
754         int pattern = 0xcd;
755         QEMUIOVector qiov;
756
757         while ((c = getopt(argc, argv, "CqP:")) != EOF) {
758                 switch (c) {
759                 case 'C':
760                         Cflag = 1;
761                         break;
762                 case 'q':
763                         qflag = 1;
764                         break;
765                 case 'P':
766                         pattern = parse_pattern(optarg);
767                         if (pattern < 0)
768                                 return 0;
769                         break;
770                 default:
771                         return command_usage(&writev_cmd);
772                 }
773         }
774
775         if (optind > argc - 2)
776                 return command_usage(&writev_cmd);
777
778         offset = cvtnum(argv[optind]);
779         if (offset < 0) {
780                 printf("non-numeric length argument -- %s\n", argv[optind]);
781                 return 0;
782         }
783         optind++;
784
785         if (offset & 0x1ff) {
786                 printf("offset %lld is not sector aligned\n",
787                         (long long)offset);
788                 return 0;
789         }
790
791         nr_iov = argc - optind;
792         buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
793
794         gettimeofday(&t1, NULL);
795         cnt = do_aio_writev(&qiov, offset, &total);
796         gettimeofday(&t2, NULL);
797
798         if (cnt < 0) {
799                 printf("writev failed: %s\n", strerror(-cnt));
800                 goto out;
801         }
802
803         if (qflag)
804                 goto out;
805
806         /* Finally, report back -- -C gives a parsable format */
807         t2 = tsub(t2, t1);
808         print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
809 out:
810         qemu_io_free(buf);
811         return 0;
812 }
813
814 struct aio_ctx {
815         QEMUIOVector qiov;
816         int64_t offset;
817         char *buf;
818         int qflag;
819         int vflag;
820         int Cflag;
821         int Pflag;
822         int pattern;
823         struct timeval t1;
824 };
825
826 static void
827 aio_write_done(void *opaque, int ret)
828 {
829         struct aio_ctx *ctx = opaque;
830         struct timeval t2;
831
832         gettimeofday(&t2, NULL);
833
834
835         if (ret < 0) {
836                 printf("aio_write failed: %s\n", strerror(-ret));
837                 goto out;
838         }
839
840         if (ctx->qflag) {
841                 goto out;
842         }
843
844         /* Finally, report back -- -C gives a parsable format */
845         t2 = tsub(t2, ctx->t1);
846         print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
847                      ctx->qiov.size, 1, ctx->Cflag);
848 out:
849         qemu_io_free(ctx->buf);
850         free(ctx);
851 }
852
853 static void
854 aio_read_done(void *opaque, int ret)
855 {
856         struct aio_ctx *ctx = opaque;
857         struct timeval t2;
858
859         gettimeofday(&t2, NULL);
860
861         if (ret < 0) {
862                 printf("readv failed: %s\n", strerror(-ret));
863                 goto out;
864         }
865
866         if (ctx->Pflag) {
867                 void *cmp_buf = malloc(ctx->qiov.size);
868
869                 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
870                 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
871                         printf("Pattern verification failed at offset %lld, "
872                                 "%zd bytes\n",
873                                 (long long) ctx->offset, ctx->qiov.size);
874                 }
875                 free(cmp_buf);
876         }
877
878         if (ctx->qflag) {
879                 goto out;
880         }
881
882         if (ctx->vflag) {
883                 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
884         }
885
886         /* Finally, report back -- -C gives a parsable format */
887         t2 = tsub(t2, ctx->t1);
888         print_report("read", &t2, ctx->offset, ctx->qiov.size,
889                      ctx->qiov.size, 1, ctx->Cflag);
890 out:
891         qemu_io_free(ctx->buf);
892         free(ctx);
893 }
894
895 static void
896 aio_read_help(void)
897 {
898         printf(
899 "\n"
900 " asynchronously reads a range of bytes from the given offset\n"
901 "\n"
902 " Example:\n"
903 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
904 "\n"
905 " Reads a segment of the currently open file, optionally dumping it to the\n"
906 " standard output stream (with -v option) for subsequent inspection.\n"
907 " The read is performed asynchronously and should the aio_flush command \n"
908 " should be used to ensure all outstanding aio requests have been completed\n"
909 " -C, -- report statistics in a machine parsable format\n"
910 " -P, -- use a pattern to verify read data\n"
911 " -v, -- dump buffer to standard output\n"
912 " -q, -- quite mode, do not show I/O statistics\n"
913 "\n");
914 }
915
916 static int aio_read_f(int argc, char **argv);
917
918 static const cmdinfo_t aio_read_cmd = {
919         .name           = "aio_read",
920         .cfunc          = aio_read_f,
921         .argmin         = 2,
922         .argmax         = -1,
923         .args           = "[-Cqv] [-P pattern ] off len [len..]",
924         .oneline        = "asynchronously reads a number of bytes",
925         .help           = aio_read_help,
926 };
927
928 static int
929 aio_read_f(int argc, char **argv)
930 {
931         int nr_iov, c;
932         struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
933         BlockDriverAIOCB *acb;
934
935         while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
936                 switch (c) {
937                 case 'C':
938                         ctx->Cflag = 1;
939                         break;
940                 case 'P':
941                         ctx->Pflag = 1;
942                         ctx->pattern = parse_pattern(optarg);
943                         if (ctx->pattern < 0)
944                                 return 0;
945                         break;
946                 case 'q':
947                         ctx->qflag = 1;
948                         break;
949                 case 'v':
950                         ctx->vflag = 1;
951                         break;
952                 default:
953                         free(ctx);
954                         return command_usage(&aio_read_cmd);
955                 }
956         }
957
958         if (optind > argc - 2) {
959                 free(ctx);
960                 return command_usage(&aio_read_cmd);
961         }
962
963         ctx->offset = cvtnum(argv[optind]);
964         if (ctx->offset < 0) {
965                 printf("non-numeric length argument -- %s\n", argv[optind]);
966                 free(ctx);
967                 return 0;
968         }
969         optind++;
970
971         if (ctx->offset & 0x1ff) {
972                 printf("offset %lld is not sector aligned\n",
973                         (long long)ctx->offset);
974                 free(ctx);
975                 return 0;
976         }
977
978         nr_iov = argc - optind;
979         ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
980
981         gettimeofday(&ctx->t1, NULL);
982         acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
983                               ctx->qiov.size >> 9, aio_read_done, ctx);
984         if (!acb) {
985                 free(ctx->buf);
986                 free(ctx);
987                 return -EIO;
988         }
989
990         return 0;
991 }
992
993 static void
994 aio_write_help(void)
995 {
996         printf(
997 "\n"
998 " asynchronously writes a range of bytes from the given offset source \n"
999 " from multiple buffers\n"
1000 "\n"
1001 " Example:\n"
1002 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1003 "\n"
1004 " Writes into a segment of the currently open file, using a buffer\n"
1005 " filled with a set pattern (0xcdcdcdcd).\n"
1006 " The write is performed asynchronously and should the aio_flush command \n"
1007 " should be used to ensure all outstanding aio requests have been completed\n"
1008 " -P, -- use different pattern to fill file\n"
1009 " -C, -- report statistics in a machine parsable format\n"
1010 " -q, -- quite mode, do not show I/O statistics\n"
1011 "\n");
1012 }
1013
1014 static int aio_write_f(int argc, char **argv);
1015
1016 static const cmdinfo_t aio_write_cmd = {
1017         .name           = "aio_write",
1018         .cfunc          = aio_write_f,
1019         .argmin         = 2,
1020         .argmax         = -1,
1021         .args           = "[-Cq] [-P pattern ] off len [len..]",
1022         .oneline        = "asynchronously writes a number of bytes",
1023         .help           = aio_write_help,
1024 };
1025
1026 static int
1027 aio_write_f(int argc, char **argv)
1028 {
1029         int nr_iov, c;
1030         int pattern = 0xcd;
1031         struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
1032         BlockDriverAIOCB *acb;
1033
1034         while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1035                 switch (c) {
1036                 case 'C':
1037                         ctx->Cflag = 1;
1038                         break;
1039                 case 'q':
1040                         ctx->qflag = 1;
1041                         break;
1042                 case 'P':
1043                         pattern = parse_pattern(optarg);
1044                         if (pattern < 0)
1045                                 return 0;
1046                         break;
1047                 default:
1048                         free(ctx);
1049                         return command_usage(&aio_write_cmd);
1050                 }
1051         }
1052
1053         if (optind > argc - 2) {
1054                 free(ctx);
1055                 return command_usage(&aio_write_cmd);
1056         }
1057
1058         ctx->offset = cvtnum(argv[optind]);
1059         if (ctx->offset < 0) {
1060                 printf("non-numeric length argument -- %s\n", argv[optind]);
1061                 free(ctx);
1062                 return 0;
1063         }
1064         optind++;
1065
1066         if (ctx->offset & 0x1ff) {
1067                 printf("offset %lld is not sector aligned\n",
1068                         (long long)ctx->offset);
1069                 free(ctx);
1070                 return 0;
1071         }
1072
1073         nr_iov = argc - optind;
1074         ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
1075
1076         gettimeofday(&ctx->t1, NULL);
1077         acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1078                               ctx->qiov.size >> 9, aio_write_done, ctx);
1079         if (!acb) {
1080                 free(ctx->buf);
1081                 free(ctx);
1082                 return -EIO;
1083         }
1084
1085         return 0;
1086 }
1087
1088 static int
1089 aio_flush_f(int argc, char **argv)
1090 {
1091         qemu_aio_flush();
1092         return 0;
1093 }
1094
1095 static const cmdinfo_t aio_flush_cmd = {
1096         .name           = "aio_flush",
1097         .cfunc          = aio_flush_f,
1098         .oneline        = "completes all outstanding aio requets"
1099 };
1100
1101 static int
1102 flush_f(int argc, char **argv)
1103 {
1104         bdrv_flush(bs);
1105         return 0;
1106 }
1107
1108 static const cmdinfo_t flush_cmd = {
1109         .name           = "flush",
1110         .altname        = "f",
1111         .cfunc          = flush_f,
1112         .oneline        = "flush all in-core file state to disk",
1113 };
1114
1115 static int
1116 truncate_f(int argc, char **argv)
1117 {
1118         int64_t offset;
1119         int ret;
1120
1121         offset = cvtnum(argv[1]);
1122         if (offset < 0) {
1123                 printf("non-numeric truncate argument -- %s\n", argv[1]);
1124                 return 0;
1125         }
1126
1127         ret = bdrv_truncate(bs, offset);
1128         if (ret < 0) {
1129                 printf("truncate: %s", strerror(ret));
1130                 return 0;
1131         }
1132
1133         return 0;
1134 }
1135
1136 static const cmdinfo_t truncate_cmd = {
1137         .name           = "truncate",
1138         .altname        = "t",
1139         .cfunc          = truncate_f,
1140         .argmin         = 1,
1141         .argmax         = 1,
1142         .args           = "off",
1143         .oneline        = "truncates the current file at the given offset",
1144 };
1145
1146 static int
1147 length_f(int argc, char **argv)
1148 {
1149         int64_t size;
1150         char s1[64];
1151
1152         size = bdrv_getlength(bs);
1153         if (size < 0) {
1154                 printf("getlength: %s", strerror(size));
1155                 return 0;
1156         }
1157
1158         cvtstr(size, s1, sizeof(s1));
1159         printf("%s\n", s1);
1160         return 0;
1161 }
1162
1163
1164 static const cmdinfo_t length_cmd = {
1165         .name           = "length",
1166         .altname        = "l",
1167         .cfunc          = length_f,
1168         .oneline        = "gets the length of the current file",
1169 };
1170
1171
1172 static int
1173 info_f(int argc, char **argv)
1174 {
1175         BlockDriverInfo bdi;
1176         char s1[64], s2[64];
1177         int ret;
1178
1179         if (bs->drv && bs->drv->format_name)
1180                 printf("format name: %s\n", bs->drv->format_name);
1181         if (bs->drv && bs->drv->protocol_name)
1182                 printf("format name: %s\n", bs->drv->protocol_name);
1183
1184         ret = bdrv_get_info(bs, &bdi);
1185         if (ret)
1186                 return 0;
1187
1188         cvtstr(bdi.cluster_size, s1, sizeof(s1));
1189         cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1190
1191         printf("cluster size: %s\n", s1);
1192         printf("vm state offset: %s\n", s2);
1193
1194         return 0;
1195 }
1196
1197
1198
1199 static const cmdinfo_t info_cmd = {
1200         .name           = "info",
1201         .altname        = "i",
1202         .cfunc          = info_f,
1203         .oneline        = "prints information about the current file",
1204 };
1205
1206 static int
1207 alloc_f(int argc, char **argv)
1208 {
1209         int64_t offset;
1210         int nb_sectors, remaining;
1211         char s1[64];
1212         int num, sum_alloc;
1213         int ret;
1214
1215         offset = cvtnum(argv[1]);
1216         if (offset & 0x1ff) {
1217                 printf("offset %lld is not sector aligned\n",
1218                         (long long)offset);
1219                 return 0;
1220         }
1221
1222         if (argc == 3)
1223                 nb_sectors = cvtnum(argv[2]);
1224         else
1225                 nb_sectors = 1;
1226
1227         remaining = nb_sectors;
1228         sum_alloc = 0;
1229         while (remaining) {
1230                 ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
1231                 remaining -= num;
1232                 if (ret) {
1233                         sum_alloc += num;
1234                 }
1235         }
1236
1237         cvtstr(offset, s1, sizeof(s1));
1238
1239         if (nb_sectors == 1)
1240                 printf("sector allocated at offset %s\n", s1);
1241         else
1242                 printf("%d/%d sectors allocated at offset %s\n",
1243                         sum_alloc, nb_sectors, s1);
1244         return 0;
1245 }
1246
1247 static const cmdinfo_t alloc_cmd = {
1248         .name           = "alloc",
1249         .altname        = "a",
1250         .argmin         = 1,
1251         .argmax         = 2,
1252         .cfunc          = alloc_f,
1253         .args           = "off [sectors]",
1254         .oneline        = "checks if a sector is present in the file",
1255 };
1256
1257 static int
1258 close_f(int argc, char **argv)
1259 {
1260         bdrv_close(bs);
1261         bs = NULL;
1262         return 0;
1263 }
1264
1265 static const cmdinfo_t close_cmd = {
1266         .name           = "close",
1267         .altname        = "c",
1268         .cfunc          = close_f,
1269         .oneline        = "close the current open file",
1270 };
1271
1272 static int openfile(char *name, int flags, int growable)
1273 {
1274         if (bs) {
1275                 fprintf(stderr, "file open already, try 'help close'\n");
1276                 return 1;
1277         }
1278
1279         bs = bdrv_new("hda");
1280         if (!bs)
1281                 return 1;
1282
1283         if (growable) {
1284                 flags |= BDRV_O_FILE;
1285         }
1286
1287         if (bdrv_open(bs, name, flags) == -1) {
1288                 fprintf(stderr, "%s: can't open device %s\n", progname, name);
1289                 bs = NULL;
1290                 return 1;
1291         }
1292
1293         if (growable) {
1294                 bs->growable = 1;
1295         }
1296         return 0;
1297 }
1298
1299 static void
1300 open_help(void)
1301 {
1302         printf(
1303 "\n"
1304 " opens a new file in the requested mode\n"
1305 "\n"
1306 " Example:\n"
1307 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
1308 "\n"
1309 " Opens a file for subsequent use by all of the other qemu-io commands.\n"
1310 " -C, -- create new file if it doesn't exist\n"
1311 " -r, -- open file read-only\n"
1312 " -s, -- use snapshot file\n"
1313 " -n, -- disable host cache\n"
1314 " -g, -- allow file to grow (only applies to protocols)"
1315 "\n");
1316 }
1317
1318 static int open_f(int argc, char **argv);
1319
1320 static const cmdinfo_t open_cmd = {
1321         .name           = "open",
1322         .altname        = "o",
1323         .cfunc          = open_f,
1324         .argmin         = 1,
1325         .argmax         = -1,
1326         .flags          = CMD_NOFILE_OK,
1327         .args           = "[-Crsn] [path]",
1328         .oneline        = "open the file specified by path",
1329         .help           = open_help,
1330 };
1331
1332 static int
1333 open_f(int argc, char **argv)
1334 {
1335         int flags = 0;
1336         int readonly = 0;
1337         int growable = 0;
1338         int c;
1339
1340         while ((c = getopt(argc, argv, "snCrg")) != EOF) {
1341                 switch (c) {
1342                 case 's':
1343                         flags |= BDRV_O_SNAPSHOT;
1344                         break;
1345                 case 'n':
1346                         flags |= BDRV_O_NOCACHE;
1347                         break;
1348                 case 'C':
1349                         flags |= BDRV_O_CREAT;
1350                         break;
1351                 case 'r':
1352                         readonly = 1;
1353                         break;
1354                 case 'g':
1355                         growable = 1;
1356                         break;
1357                 default:
1358                         return command_usage(&open_cmd);
1359                 }
1360         }
1361
1362         if (readonly)
1363                 flags |= BDRV_O_RDONLY;
1364         else
1365                 flags |= BDRV_O_RDWR;
1366
1367         if (optind != argc - 1)
1368                 return command_usage(&open_cmd);
1369
1370         return openfile(argv[optind], flags, growable);
1371 }
1372
1373 static int
1374 init_args_command(
1375         int     index)
1376 {
1377         /* only one device allowed so far */
1378         if (index >= 1)
1379                 return 0;
1380         return ++index;
1381 }
1382
1383 static int
1384 init_check_command(
1385         const cmdinfo_t *ct)
1386 {
1387         if (ct->flags & CMD_FLAG_GLOBAL)
1388                 return 1;
1389         if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1390                 fprintf(stderr, "no file open, try 'help open'\n");
1391                 return 0;
1392         }
1393         return 1;
1394 }
1395
1396 static void usage(const char *name)
1397 {
1398         printf(
1399 "Usage: %s [-h] [-V] [-Crsnm] [-c cmd] ... [file]\n"
1400 "QEMU Disk exerciser\n"
1401 "\n"
1402 "  -C, --create         create new file if it doesn't exist\n"
1403 "  -c, --cmd            command to execute\n"
1404 "  -r, --read-only      export read-only\n"
1405 "  -s, --snapshot       use snapshot file\n"
1406 "  -n, --nocache        disable host cache\n"
1407 "  -g, --growable       allow file to grow (only applies to protocols)\n"
1408 "  -m, --misalign       misalign allocations for O_DIRECT\n"
1409 "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
1410 "  -h, --help           display this help and exit\n"
1411 "  -V, --version        output version information and exit\n"
1412 "\n",
1413         name);
1414 }
1415
1416
1417 int main(int argc, char **argv)
1418 {
1419         int readonly = 0;
1420         int growable = 0;
1421         const char *sopt = "hVc:Crsnmgk";
1422         const struct option lopt[] = {
1423                 { "help", 0, NULL, 'h' },
1424                 { "version", 0, NULL, 'V' },
1425                 { "offset", 1, NULL, 'o' },
1426                 { "cmd", 1, NULL, 'c' },
1427                 { "create", 0, NULL, 'C' },
1428                 { "read-only", 0, NULL, 'r' },
1429                 { "snapshot", 0, NULL, 's' },
1430                 { "nocache", 0, NULL, 'n' },
1431                 { "misalign", 0, NULL, 'm' },
1432                 { "growable", 0, NULL, 'g' },
1433                 { "native-aio", 0, NULL, 'k' },
1434                 { NULL, 0, NULL, 0 }
1435         };
1436         int c;
1437         int opt_index = 0;
1438         int flags = 0;
1439
1440         progname = basename(argv[0]);
1441
1442         while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
1443                 switch (c) {
1444                 case 's':
1445                         flags |= BDRV_O_SNAPSHOT;
1446                         break;
1447                 case 'n':
1448                         flags |= BDRV_O_NOCACHE;
1449                         break;
1450                 case 'c':
1451                         add_user_command(optarg);
1452                         break;
1453                 case 'C':
1454                         flags |= BDRV_O_CREAT;
1455                         break;
1456                 case 'r':
1457                         readonly = 1;
1458                         break;
1459                 case 'm':
1460                         misalign = 1;
1461                         break;
1462                 case 'g':
1463                         growable = 1;
1464                         break;
1465                 case 'k':
1466                         flags |= BDRV_O_NATIVE_AIO;
1467                         break;
1468                 case 'V':
1469                         printf("%s version %s\n", progname, VERSION);
1470                         exit(0);
1471                 case 'h':
1472                         usage(progname);
1473                         exit(0);
1474                 default:
1475                         usage(progname);
1476                         exit(1);
1477                 }
1478         }
1479
1480         if ((argc - optind) > 1) {
1481                 usage(progname);
1482                 exit(1);
1483         }
1484
1485         bdrv_init();
1486
1487         /* initialize commands */
1488         quit_init();
1489         help_init();
1490         add_command(&open_cmd);
1491         add_command(&close_cmd);
1492         add_command(&read_cmd);
1493         add_command(&readv_cmd);
1494         add_command(&write_cmd);
1495         add_command(&writev_cmd);
1496         add_command(&aio_read_cmd);
1497         add_command(&aio_write_cmd);
1498         add_command(&aio_flush_cmd);
1499         add_command(&flush_cmd);
1500         add_command(&truncate_cmd);
1501         add_command(&length_cmd);
1502         add_command(&info_cmd);
1503         add_command(&alloc_cmd);
1504
1505         add_args_command(init_args_command);
1506         add_check_command(init_check_command);
1507
1508         /* open the device */
1509         if (readonly)
1510                 flags |= BDRV_O_RDONLY;
1511         else
1512                 flags |= BDRV_O_RDWR;
1513
1514         if ((argc - optind) == 1)
1515                 openfile(argv[optind], flags, growable);
1516         command_loop();
1517
1518         /*
1519          * Make sure all outstanding requests get flushed the program exits.
1520          */
1521         qemu_aio_flush();
1522
1523         if (bs)
1524                 bdrv_close(bs);
1525         return 0;
1526 }
This page took 0.119859 seconds and 4 git commands to generate.