]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-io-cmds.c
qemu-io: Move qemu_strsep() to cutils.c
[mirror_qemu.git] / qemu-io-cmds.c
CommitLineData
797ac58c
KW
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
17int qemuio_misalign;
18
19static 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 */
31static 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
53static 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
68static void qemu_io_free(void *p)
69{
70 if (qemuio_misalign) {
71 p -= MISALIGN_OFFSET;
72 }
73 qemu_vfree(p);
74}
75
76static 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
100static 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 */
125static void *
126create_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
170fail:
171 g_free(sizes);
172 return buf;
173}
174
175static 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
188static 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
201static 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
211static 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
221typedef struct {
222 BlockDriverState *bs;
223 int64_t offset;
224 int count;
225 int *total;
226 int ret;
227 bool done;
228} CoWriteZeroes;
229
230static 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
245static 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
269static 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
282static 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
292static 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
303static void aio_rw_done(void *opaque, int ret)
304{
305 *(int *)opaque = ret;
306}
307
308static 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
323static 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
338struct multiwrite_async_ret {
339 int num_done;
340 int error;
341};
342
343static 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
353static 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
381static 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
403static int read_f(BlockDriverState *bs, int argc, char **argv);
404
405static 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
416static 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
562out:
563 qemu_io_free(buf);
564
565 return 0;
566}
567
568static 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
587static int readv_f(BlockDriverState *bs, int argc, char **argv);
588
589static 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
599static 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
691out:
692 qemu_iovec_destroy(&qiov);
693 qemu_io_free(buf);
694 return 0;
695}
696
697static 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
718static int write_f(BlockDriverState *bs, int argc, char **argv);
719
720static 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
731static 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
848out:
849 if (!zflag) {
850 qemu_io_free(buf);
851 }
852
853 return 0;
854}
855
856static void
857writev_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
874static int writev_f(BlockDriverState *bs, int argc, char **argv);
875
876static 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
886static 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);
957out:
958 qemu_iovec_destroy(&qiov);
959 qemu_io_free(buf);
960 return 0;
961}
962
963static 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
983static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
984
985static 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
995static 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);
1109out:
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
1122struct 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
1134static 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);
1155out:
1156 qemu_io_free(ctx->buf);
1157 qemu_iovec_destroy(&ctx->qiov);
1158 g_free(ctx);
1159}
1160
1161static 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);
1196out:
1197 qemu_io_free(ctx->buf);
1198 qemu_iovec_destroy(&ctx->qiov);
1199 g_free(ctx);
1200}
1201
1202static 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
1222static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1223
1224static 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
1234static 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
1297static 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
1317static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1318
1319static 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
1329static 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
1389static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1390{
1391 bdrv_drain_all();
1392 return 0;
1393}
1394
1395static const cmdinfo_t aio_flush_cmd = {
1396 .name = "aio_flush",
1397 .cfunc = aio_flush_f,
1398 .oneline = "completes all outstanding aio requests"
1399};
1400
1401static int flush_f(BlockDriverState *bs, int argc, char **argv)
1402{
1403 bdrv_flush(bs);
1404 return 0;
1405}
1406
1407static 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
1414static 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
1434static 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
1444static 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
1461static 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
1469static 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
1498static 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
1505static 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
1520static int discard_f(BlockDriverState *bs, int argc, char **argv);
1521
1522static 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
1533static 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
1587out:
1588 return 0;
1589}
1590
1591static 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
1642static 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
1653static 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
1684static 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
1716static 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
1725static 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
1737static 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
1747static 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
1759static 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
1768static 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
1777static 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
1786static int abort_f(BlockDriverState *bs, int argc, char **argv)
1787{
1788 abort();
1789}
1790
1791static 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
f18a834a
KW
1798static void help_oneline(const char *cmd, const cmdinfo_t *ct)
1799{
1800 if (cmd) {
1801 printf("%s ", cmd);
1802 } else {
1803 printf("%s ", ct->name);
1804 if (ct->altname) {
1805 printf("(or %s) ", ct->altname);
1806 }
1807 }
1808
1809 if (ct->args) {
1810 printf("%s ", ct->args);
1811 }
1812 printf("-- %s\n", ct->oneline);
1813}
1814
1815static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
1816{
1817 help_oneline(cmd, ct);
1818 if (ct->help) {
1819 ct->help();
1820 }
1821}
1822
1823static void help_all(void)
1824{
1825 const cmdinfo_t *ct;
1826
1827 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
1828 help_oneline(ct->name, ct);
1829 }
1830 printf("\nUse 'help commandname' for extended help.\n");
1831}
1832
1833static int help_f(BlockDriverState *bs, int argc, char **argv)
1834{
1835 const cmdinfo_t *ct;
1836
1837 if (argc == 1) {
1838 help_all();
1839 return 0;
1840 }
1841
1842 ct = find_command(argv[1]);
1843 if (ct == NULL) {
1844 printf("command %s not found\n", argv[1]);
1845 return 0;
1846 }
1847
1848 help_onecmd(argv[1], ct);
1849 return 0;
1850}
1851
1852static const cmdinfo_t help_cmd = {
1853 .name = "help",
1854 .altname = "?",
1855 .cfunc = help_f,
1856 .argmin = 0,
1857 .argmax = 1,
1858 .flags = CMD_FLAG_GLOBAL,
1859 .args = "[command]",
1860 .oneline = "help for one or all commands",
1861};
1862
797ac58c
KW
1863static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
1864{
1865 if (ct->flags & CMD_FLAG_GLOBAL) {
1866 return 1;
1867 }
1868 if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1869 fprintf(stderr, "no file open, try 'help open'\n");
1870 return 0;
1871 }
1872 return 1;
1873}
1874
dd583296
KW
1875bool qemuio_command(const char *cmd)
1876{
1877 char *input;
1878 const cmdinfo_t *ct;
1879 char **v;
1880 int c;
1881 bool done = false;
1882
1883 input = g_strdup(cmd);
1884 v = breakline(input, &c);
1885 if (c) {
1886 ct = find_command(v[0]);
1887 if (ct) {
1888 done = command(ct, c, v);
1889 } else {
1890 fprintf(stderr, "command \"%s\" not found\n", v[0]);
1891 }
1892 }
1893 g_free(input);
1894 g_free(v);
1895
1896 return done;
1897}
1898
797ac58c
KW
1899static void __attribute((constructor)) init_qemuio_commands(void)
1900{
1901 /* initialize commands */
f18a834a 1902 add_command(&help_cmd);
797ac58c
KW
1903 add_command(&read_cmd);
1904 add_command(&readv_cmd);
1905 add_command(&write_cmd);
1906 add_command(&writev_cmd);
1907 add_command(&multiwrite_cmd);
1908 add_command(&aio_read_cmd);
1909 add_command(&aio_write_cmd);
1910 add_command(&aio_flush_cmd);
1911 add_command(&flush_cmd);
1912 add_command(&truncate_cmd);
1913 add_command(&length_cmd);
1914 add_command(&info_cmd);
1915 add_command(&discard_cmd);
1916 add_command(&alloc_cmd);
1917 add_command(&map_cmd);
1918 add_command(&break_cmd);
1919 add_command(&resume_cmd);
1920 add_command(&wait_break_cmd);
1921 add_command(&abort_cmd);
1922
1923 add_check_command(init_check_command);
1924}