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