2 * Command line utility to exercise the QEMU I/O path.
4 * Copyright (C) 2009 Red Hat, Inc.
5 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
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.
12 #include "block/block_int.h"
13 #include "block/qapi.h"
14 #include "qemu/main-loop.h"
16 #define CMD_NOFILE_OK 0x01
20 static cmdinfo_t *cmdtab;
23 static int compare_cmdname(const void *a, const void *b)
25 return strcmp(((const cmdinfo_t *)a)->name,
26 ((const cmdinfo_t *)b)->name);
29 void qemuio_add_command(const cmdinfo_t *ci)
31 cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
32 cmdtab[ncmds - 1] = *ci;
33 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
36 int qemuio_command_usage(const cmdinfo_t *ci)
38 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
42 static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
44 if (ct->flags & CMD_FLAG_GLOBAL) {
47 if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
48 fprintf(stderr, "no file open, try 'help open'\n");
54 static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
59 if (!init_check_command(bs, ct)) {
63 if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
64 if (ct->argmax == -1) {
66 "bad argument count %d to %s, expected at least %d arguments\n",
67 argc-1, cmd, ct->argmin);
68 } else if (ct->argmin == ct->argmax) {
70 "bad argument count %d to %s, expected %d arguments\n",
71 argc-1, cmd, ct->argmin);
74 "bad argument count %d to %s, expected between %d and %d arguments\n",
75 argc-1, cmd, ct->argmin, ct->argmax);
80 return ct->cfunc(bs, argc, argv);
83 static const cmdinfo_t *find_command(const char *cmd)
87 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
88 if (strcmp(ct->name, cmd) == 0 ||
89 (ct->altname && strcmp(ct->altname, cmd) == 0))
91 return (const cmdinfo_t *)ct;
97 static char **breakline(char *input, int *count)
101 char **rval = g_malloc0(sizeof(char *));
104 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
109 tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
125 static int64_t cvtnum(const char *s)
128 return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
131 #define EXABYTES(x) ((long long)(x) << 60)
132 #define PETABYTES(x) ((long long)(x) << 50)
133 #define TERABYTES(x) ((long long)(x) << 40)
134 #define GIGABYTES(x) ((long long)(x) << 30)
135 #define MEGABYTES(x) ((long long)(x) << 20)
136 #define KILOBYTES(x) ((long long)(x) << 10)
138 #define TO_EXABYTES(x) ((x) / EXABYTES(1))
139 #define TO_PETABYTES(x) ((x) / PETABYTES(1))
140 #define TO_TERABYTES(x) ((x) / TERABYTES(1))
141 #define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
142 #define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
143 #define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
145 static void cvtstr(double value, char *str, size_t size)
150 if (value >= EXABYTES(1)) {
152 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
153 } else if (value >= PETABYTES(1)) {
155 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
156 } else if (value >= TERABYTES(1)) {
158 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
159 } else if (value >= GIGABYTES(1)) {
161 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
162 } else if (value >= MEGABYTES(1)) {
164 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
165 } else if (value >= KILOBYTES(1)) {
167 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
170 snprintf(str, size - 6, "%f", value);
173 trim = strstr(str, ".000");
175 strcpy(trim, suffix);
183 static struct timeval tsub(struct timeval t1, struct timeval t2)
185 t1.tv_usec -= t2.tv_usec;
186 if (t1.tv_usec < 0) {
187 t1.tv_usec += 1000000;
190 t1.tv_sec -= t2.tv_sec;
194 static double tdiv(double value, struct timeval tv)
196 return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
199 #define HOURS(sec) ((sec) / (60 * 60))
200 #define MINUTES(sec) (((sec) % (60 * 60)) / 60)
201 #define SECONDS(sec) ((sec) % 60)
205 TERSE_FIXED_TIME = 0x1,
206 VERBOSE_FIXED_TIME = 0x2,
209 static void timestr(struct timeval *tv, char *ts, size_t size, int format)
211 double usec = (double)tv->tv_usec / 1000000.0;
213 if (format & TERSE_FIXED_TIME) {
214 if (!HOURS(tv->tv_sec)) {
215 snprintf(ts, size, "%u:%02u.%02u",
216 (unsigned int) MINUTES(tv->tv_sec),
217 (unsigned int) SECONDS(tv->tv_sec),
218 (unsigned int) (usec * 100));
221 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
224 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
225 snprintf(ts, size, "%u:%02u:%02u.%02u",
226 (unsigned int) HOURS(tv->tv_sec),
227 (unsigned int) MINUTES(tv->tv_sec),
228 (unsigned int) SECONDS(tv->tv_sec),
229 (unsigned int) (usec * 100));
231 snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
236 * Parse the pattern argument to various sub-commands.
238 * Because the pattern is used as an argument to memset it must evaluate
239 * to an unsigned integer that fits into a single byte.
241 static int parse_pattern(const char *arg)
246 pattern = strtol(arg, &endptr, 0);
247 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
248 printf("%s is not a valid pattern byte\n", arg);
256 * Memory allocation helpers.
258 * Make sure memory is aligned by default, or purposefully misaligned if
259 * that is specified on the command line.
262 #define MISALIGN_OFFSET 16
263 static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
267 if (qemuio_misalign) {
268 len += MISALIGN_OFFSET;
270 buf = qemu_blockalign(bs, len);
271 memset(buf, pattern, len);
272 if (qemuio_misalign) {
273 buf += MISALIGN_OFFSET;
278 static void qemu_io_free(void *p)
280 if (qemuio_misalign) {
281 p -= MISALIGN_OFFSET;
286 static void dump_buffer(const void *buffer, int64_t offset, int len)
291 for (i = 0, p = buffer; i < len; i += 16) {
292 const uint8_t *s = p;
294 printf("%08" PRIx64 ": ", offset + i);
295 for (j = 0; j < 16 && i + j < len; j++, p++) {
299 for (j = 0; j < 16 && i + j < len; j++, s++) {
310 static void print_report(const char *op, struct timeval *t, int64_t offset,
311 int count, int total, int cnt, int Cflag)
313 char s1[64], s2[64], ts[64];
315 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
317 cvtstr((double)total, s1, sizeof(s1));
318 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
319 printf("%s %d/%d bytes at offset %" PRId64 "\n",
320 op, total, count, offset);
321 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
322 s1, cnt, ts, s2, tdiv((double)cnt, *t));
323 } else {/* bytes,ops,time,bytes/sec,ops/sec */
324 printf("%d,%d,%s,%.3f,%.3f\n",
326 tdiv((double)total, *t),
327 tdiv((double)cnt, *t));
332 * Parse multiple length statements for vectored I/O, and construct an I/O
333 * vector matching it.
336 create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
339 size_t *sizes = g_new0(size_t, nr_iov);
345 for (i = 0; i < nr_iov; i++) {
351 printf("non-numeric length argument -- %s\n", arg);
355 /* should be SIZE_T_MAX, but that doesn't exist */
357 printf("too large length argument -- %s\n", arg);
362 printf("length argument %" PRId64
363 " is not sector aligned\n", len);
371 qemu_iovec_init(qiov, nr_iov);
373 buf = p = qemu_io_alloc(bs, count, pattern);
375 for (i = 0; i < nr_iov; i++) {
376 qemu_iovec_add(qiov, p, sizes[i]);
385 static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
390 ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
398 static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
403 ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
411 static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
414 *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
421 static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
424 *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
432 BlockDriverState *bs;
440 static void coroutine_fn co_write_zeroes_entry(void *opaque)
442 CoWriteZeroes *data = opaque;
444 data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
445 data->count / BDRV_SECTOR_SIZE, 0);
448 *data->total = data->ret;
452 *data->total = data->count;
455 static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
459 CoWriteZeroes data = {
467 co = qemu_coroutine_create(co_write_zeroes_entry);
468 qemu_coroutine_enter(co, &data);
479 static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
480 int count, int *total)
484 ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
492 static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
493 int count, int *total)
495 *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
502 static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
503 int count, int *total)
505 *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
512 #define NOT_DONE 0x7fffffff
513 static void aio_rw_done(void *opaque, int ret)
515 *(int *)opaque = ret;
518 static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
519 int64_t offset, int *total)
521 int async_ret = NOT_DONE;
523 bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
524 aio_rw_done, &async_ret);
525 while (async_ret == NOT_DONE) {
526 main_loop_wait(false);
530 return async_ret < 0 ? async_ret : 1;
533 static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
534 int64_t offset, int *total)
536 int async_ret = NOT_DONE;
538 bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
539 aio_rw_done, &async_ret);
540 while (async_ret == NOT_DONE) {
541 main_loop_wait(false);
545 return async_ret < 0 ? async_ret : 1;
548 struct multiwrite_async_ret {
553 static void multiwrite_cb(void *opaque, int ret)
555 struct multiwrite_async_ret *async_ret = opaque;
557 async_ret->num_done++;
559 async_ret->error = ret;
563 static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
564 int num_reqs, int *total)
567 struct multiwrite_async_ret async_ret = {
573 for (i = 0; i < num_reqs; i++) {
574 reqs[i].cb = multiwrite_cb;
575 reqs[i].opaque = &async_ret;
576 *total += reqs[i].qiov->size;
579 ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
584 while (async_ret.num_done < num_reqs) {
585 main_loop_wait(false);
588 return async_ret.error < 0 ? async_ret.error : 1;
591 static void read_help(void)
595 " reads a range of bytes from the given offset\n"
598 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
600 " Reads a segment of the currently open file, optionally dumping it to the\n"
601 " standard output stream (with -v option) for subsequent inspection.\n"
602 " -b, -- read from the VM state rather than the virtual disk\n"
603 " -C, -- report statistics in a machine parsable format\n"
604 " -l, -- length for pattern verification (only with -P)\n"
605 " -p, -- use bdrv_pread to read the file\n"
606 " -P, -- use a pattern to verify read data\n"
607 " -q, -- quiet mode, do not show I/O statistics\n"
608 " -s, -- start offset for pattern verification (only with -P)\n"
609 " -v, -- dump buffer to standard output\n"
613 static int read_f(BlockDriverState *bs, int argc, char **argv);
615 static const cmdinfo_t read_cmd = {
621 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
622 .oneline = "reads a number of bytes at a specified offset",
626 static int read_f(BlockDriverState *bs, int argc, char **argv)
628 struct timeval t1, t2;
629 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
630 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
635 /* Some compilers get confused and warn if this is not initialized. */
637 int pattern = 0, pattern_offset = 0, pattern_count = 0;
639 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
649 pattern_count = cvtnum(optarg);
650 if (pattern_count < 0) {
651 printf("non-numeric length argument -- %s\n", optarg);
660 pattern = parse_pattern(optarg);
670 pattern_offset = cvtnum(optarg);
671 if (pattern_offset < 0) {
672 printf("non-numeric length argument -- %s\n", optarg);
680 return qemuio_command_usage(&read_cmd);
684 if (optind != argc - 2) {
685 return qemuio_command_usage(&read_cmd);
688 if (bflag && pflag) {
689 printf("-b and -p cannot be specified at the same time\n");
693 offset = cvtnum(argv[optind]);
695 printf("non-numeric length argument -- %s\n", argv[optind]);
700 count = cvtnum(argv[optind]);
702 printf("non-numeric length argument -- %s\n", argv[optind]);
706 if (!Pflag && (lflag || sflag)) {
707 return qemuio_command_usage(&read_cmd);
711 pattern_count = count - pattern_offset;
714 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
715 printf("pattern verification range exceeds end of read data\n");
720 if (offset & 0x1ff) {
721 printf("offset %" PRId64 " is not sector aligned\n",
726 printf("count %d is not sector aligned\n",
732 buf = qemu_io_alloc(bs, count, 0xab);
734 gettimeofday(&t1, NULL);
736 cnt = do_pread(bs, buf, offset, count, &total);
738 cnt = do_load_vmstate(bs, buf, offset, count, &total);
740 cnt = do_read(bs, buf, offset, count, &total);
742 gettimeofday(&t2, NULL);
745 printf("read failed: %s\n", strerror(-cnt));
750 void *cmp_buf = g_malloc(pattern_count);
751 memset(cmp_buf, pattern, pattern_count);
752 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
753 printf("Pattern verification failed at offset %"
754 PRId64 ", %d bytes\n",
755 offset + pattern_offset, pattern_count);
765 dump_buffer(buf, offset, count);
768 /* Finally, report back -- -C gives a parsable format */
770 print_report("read", &t2, offset, count, total, cnt, Cflag);
778 static void readv_help(void)
782 " reads a range of bytes from the given offset into multiple buffers\n"
785 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
787 " Reads a segment of the currently open file, optionally dumping it to the\n"
788 " standard output stream (with -v option) for subsequent inspection.\n"
789 " Uses multiple iovec buffers if more than one byte range is specified.\n"
790 " -C, -- report statistics in a machine parsable format\n"
791 " -P, -- use a pattern to verify read data\n"
792 " -v, -- dump buffer to standard output\n"
793 " -q, -- quiet mode, do not show I/O statistics\n"
797 static int readv_f(BlockDriverState *bs, int argc, char **argv);
799 static const cmdinfo_t readv_cmd = {
804 .args = "[-Cqv] [-P pattern ] off len [len..]",
805 .oneline = "reads a number of bytes at a specified offset",
809 static int readv_f(BlockDriverState *bs, int argc, char **argv)
811 struct timeval t1, t2;
812 int Cflag = 0, qflag = 0, vflag = 0;
816 /* Some compilers get confused and warn if this is not initialized. */
823 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
830 pattern = parse_pattern(optarg);
842 return qemuio_command_usage(&readv_cmd);
846 if (optind > argc - 2) {
847 return qemuio_command_usage(&readv_cmd);
851 offset = cvtnum(argv[optind]);
853 printf("non-numeric length argument -- %s\n", argv[optind]);
858 if (offset & 0x1ff) {
859 printf("offset %" PRId64 " is not sector aligned\n",
864 nr_iov = argc - optind;
865 buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
870 gettimeofday(&t1, NULL);
871 cnt = do_aio_readv(bs, &qiov, offset, &total);
872 gettimeofday(&t2, NULL);
875 printf("readv failed: %s\n", strerror(-cnt));
880 void *cmp_buf = g_malloc(qiov.size);
881 memset(cmp_buf, pattern, qiov.size);
882 if (memcmp(buf, cmp_buf, qiov.size)) {
883 printf("Pattern verification failed at offset %"
884 PRId64 ", %zd bytes\n", offset, qiov.size);
894 dump_buffer(buf, offset, qiov.size);
897 /* Finally, report back -- -C gives a parsable format */
899 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
902 qemu_iovec_destroy(&qiov);
907 static void write_help(void)
911 " writes a range of bytes from the given offset\n"
914 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
916 " Writes into a segment of the currently open file, using a buffer\n"
917 " filled with a set pattern (0xcdcdcdcd).\n"
918 " -b, -- write to the VM state rather than the virtual disk\n"
919 " -c, -- write compressed data with bdrv_write_compressed\n"
920 " -p, -- use bdrv_pwrite to write the file\n"
921 " -P, -- use different pattern to fill file\n"
922 " -C, -- report statistics in a machine parsable format\n"
923 " -q, -- quiet mode, do not show I/O statistics\n"
924 " -z, -- write zeroes using bdrv_co_write_zeroes\n"
928 static int write_f(BlockDriverState *bs, int argc, char **argv);
930 static const cmdinfo_t write_cmd = {
936 .args = "[-bcCpqz] [-P pattern ] off len",
937 .oneline = "writes a number of bytes at a specified offset",
941 static int write_f(BlockDriverState *bs, int argc, char **argv)
943 struct timeval t1, t2;
944 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
950 /* Some compilers get confused and warn if this is not initialized. */
954 while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
970 pattern = parse_pattern(optarg);
982 return qemuio_command_usage(&write_cmd);
986 if (optind != argc - 2) {
987 return qemuio_command_usage(&write_cmd);
990 if (bflag + pflag + zflag > 1) {
991 printf("-b, -p, or -z cannot be specified at the same time\n");
995 if (zflag && Pflag) {
996 printf("-z and -P cannot be specified at the same time\n");
1000 offset = cvtnum(argv[optind]);
1002 printf("non-numeric length argument -- %s\n", argv[optind]);
1007 count = cvtnum(argv[optind]);
1009 printf("non-numeric length argument -- %s\n", argv[optind]);
1014 if (offset & 0x1ff) {
1015 printf("offset %" PRId64 " is not sector aligned\n",
1020 if (count & 0x1ff) {
1021 printf("count %d is not sector aligned\n",
1028 buf = qemu_io_alloc(bs, count, pattern);
1031 gettimeofday(&t1, NULL);
1033 cnt = do_pwrite(bs, buf, offset, count, &total);
1035 cnt = do_save_vmstate(bs, buf, offset, count, &total);
1037 cnt = do_co_write_zeroes(bs, offset, count, &total);
1039 cnt = do_write_compressed(bs, buf, offset, count, &total);
1041 cnt = do_write(bs, buf, offset, count, &total);
1043 gettimeofday(&t2, NULL);
1046 printf("write failed: %s\n", strerror(-cnt));
1054 /* Finally, report back -- -C gives a parsable format */
1056 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1071 " writes a range of bytes from the given offset source from multiple buffers\n"
1074 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1076 " Writes into a segment of the currently open file, using a buffer\n"
1077 " filled with a set pattern (0xcdcdcdcd).\n"
1078 " -P, -- use different pattern to fill file\n"
1079 " -C, -- report statistics in a machine parsable format\n"
1080 " -q, -- quiet mode, do not show I/O statistics\n"
1084 static int writev_f(BlockDriverState *bs, int argc, char **argv);
1086 static const cmdinfo_t writev_cmd = {
1091 .args = "[-Cq] [-P pattern ] off len [len..]",
1092 .oneline = "writes a number of bytes at a specified offset",
1093 .help = writev_help,
1096 static int writev_f(BlockDriverState *bs, int argc, char **argv)
1098 struct timeval t1, t2;
1099 int Cflag = 0, qflag = 0;
1103 /* Some compilers get confused and warn if this is not initialized. */
1109 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1118 pattern = parse_pattern(optarg);
1124 return qemuio_command_usage(&writev_cmd);
1128 if (optind > argc - 2) {
1129 return qemuio_command_usage(&writev_cmd);
1132 offset = cvtnum(argv[optind]);
1134 printf("non-numeric length argument -- %s\n", argv[optind]);
1139 if (offset & 0x1ff) {
1140 printf("offset %" PRId64 " is not sector aligned\n",
1145 nr_iov = argc - optind;
1146 buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
1151 gettimeofday(&t1, NULL);
1152 cnt = do_aio_writev(bs, &qiov, offset, &total);
1153 gettimeofday(&t2, NULL);
1156 printf("writev failed: %s\n", strerror(-cnt));
1164 /* Finally, report back -- -C gives a parsable format */
1166 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1168 qemu_iovec_destroy(&qiov);
1173 static void multiwrite_help(void)
1177 " writes a range of bytes from the given offset source from multiple buffers,\n"
1178 " in a batch of requests that may be merged by qemu\n"
1181 " 'multiwrite 512 1k 1k ; 4k 1k'\n"
1182 " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
1184 " Writes into a segment of the currently open file, using a buffer\n"
1185 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
1186 " by one for each request contained in the multiwrite command.\n"
1187 " -P, -- use different pattern to fill file\n"
1188 " -C, -- report statistics in a machine parsable format\n"
1189 " -q, -- quiet mode, do not show I/O statistics\n"
1193 static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
1195 static const cmdinfo_t multiwrite_cmd = {
1196 .name = "multiwrite",
1197 .cfunc = multiwrite_f,
1200 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
1201 .oneline = "issues multiple write requests at once",
1202 .help = multiwrite_help,
1205 static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
1207 struct timeval t1, t2;
1208 int Cflag = 0, qflag = 0;
1211 int64_t offset, first_offset = 0;
1212 /* Some compilers get confused and warn if this is not initialized. */
1217 QEMUIOVector *qiovs;
1221 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1230 pattern = parse_pattern(optarg);
1236 return qemuio_command_usage(&writev_cmd);
1240 if (optind > argc - 2) {
1241 return qemuio_command_usage(&writev_cmd);
1245 for (i = optind; i < argc; i++) {
1246 if (!strcmp(argv[i], ";")) {
1251 reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1252 buf = g_malloc0(nr_reqs * sizeof(*buf));
1253 qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1255 for (i = 0; i < nr_reqs && optind < argc; i++) {
1258 /* Read the offset of the request */
1259 offset = cvtnum(argv[optind]);
1261 printf("non-numeric offset argument -- %s\n", argv[optind]);
1266 if (offset & 0x1ff) {
1267 printf("offset %lld is not sector aligned\n",
1273 first_offset = offset;
1276 /* Read lengths for qiov entries */
1277 for (j = optind; j < argc; j++) {
1278 if (!strcmp(argv[j], ";")) {
1283 nr_iov = j - optind;
1286 buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
1287 if (buf[i] == NULL) {
1291 reqs[i].qiov = &qiovs[i];
1292 reqs[i].sector = offset >> 9;
1293 reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1300 /* If there were empty requests at the end, ignore them */
1303 gettimeofday(&t1, NULL);
1304 cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
1305 gettimeofday(&t2, NULL);
1308 printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1316 /* Finally, report back -- -C gives a parsable format */
1318 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1320 for (i = 0; i < nr_reqs; i++) {
1321 qemu_io_free(buf[i]);
1322 if (reqs[i].qiov != NULL) {
1323 qemu_iovec_destroy(&qiovs[i]);
1344 static void aio_write_done(void *opaque, int ret)
1346 struct aio_ctx *ctx = opaque;
1349 gettimeofday(&t2, NULL);
1353 printf("aio_write failed: %s\n", strerror(-ret));
1361 /* Finally, report back -- -C gives a parsable format */
1362 t2 = tsub(t2, ctx->t1);
1363 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1364 ctx->qiov.size, 1, ctx->Cflag);
1366 qemu_io_free(ctx->buf);
1367 qemu_iovec_destroy(&ctx->qiov);
1371 static void aio_read_done(void *opaque, int ret)
1373 struct aio_ctx *ctx = opaque;
1376 gettimeofday(&t2, NULL);
1379 printf("readv failed: %s\n", strerror(-ret));
1384 void *cmp_buf = g_malloc(ctx->qiov.size);
1386 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1387 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1388 printf("Pattern verification failed at offset %"
1389 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1399 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1402 /* Finally, report back -- -C gives a parsable format */
1403 t2 = tsub(t2, ctx->t1);
1404 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1405 ctx->qiov.size, 1, ctx->Cflag);
1407 qemu_io_free(ctx->buf);
1408 qemu_iovec_destroy(&ctx->qiov);
1412 static void aio_read_help(void)
1416 " asynchronously reads a range of bytes from the given offset\n"
1419 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1421 " Reads a segment of the currently open file, optionally dumping it to the\n"
1422 " standard output stream (with -v option) for subsequent inspection.\n"
1423 " The read is performed asynchronously and the aio_flush command must be\n"
1424 " used to ensure all outstanding aio requests have been completed.\n"
1425 " -C, -- report statistics in a machine parsable format\n"
1426 " -P, -- use a pattern to verify read data\n"
1427 " -v, -- dump buffer to standard output\n"
1428 " -q, -- quiet mode, do not show I/O statistics\n"
1432 static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1434 static const cmdinfo_t aio_read_cmd = {
1436 .cfunc = aio_read_f,
1439 .args = "[-Cqv] [-P pattern ] off len [len..]",
1440 .oneline = "asynchronously reads a number of bytes",
1441 .help = aio_read_help,
1444 static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
1447 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1449 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1456 ctx->pattern = parse_pattern(optarg);
1457 if (ctx->pattern < 0) {
1470 return qemuio_command_usage(&aio_read_cmd);
1474 if (optind > argc - 2) {
1476 return qemuio_command_usage(&aio_read_cmd);
1479 ctx->offset = cvtnum(argv[optind]);
1480 if (ctx->offset < 0) {
1481 printf("non-numeric length argument -- %s\n", argv[optind]);
1487 if (ctx->offset & 0x1ff) {
1488 printf("offset %" PRId64 " is not sector aligned\n",
1494 nr_iov = argc - optind;
1495 ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1496 if (ctx->buf == NULL) {
1501 gettimeofday(&ctx->t1, NULL);
1502 bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1503 ctx->qiov.size >> 9, aio_read_done, ctx);
1507 static void aio_write_help(void)
1511 " asynchronously writes a range of bytes from the given offset source\n"
1512 " from multiple buffers\n"
1515 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1517 " Writes into a segment of the currently open file, using a buffer\n"
1518 " filled with a set pattern (0xcdcdcdcd).\n"
1519 " The write is performed asynchronously and the aio_flush command must be\n"
1520 " used to ensure all outstanding aio requests have been completed.\n"
1521 " -P, -- use different pattern to fill file\n"
1522 " -C, -- report statistics in a machine parsable format\n"
1523 " -q, -- quiet mode, do not show I/O statistics\n"
1527 static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1529 static const cmdinfo_t aio_write_cmd = {
1530 .name = "aio_write",
1531 .cfunc = aio_write_f,
1534 .args = "[-Cq] [-P pattern ] off len [len..]",
1535 .oneline = "asynchronously writes a number of bytes",
1536 .help = aio_write_help,
1539 static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
1543 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1545 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1554 pattern = parse_pattern(optarg);
1562 return qemuio_command_usage(&aio_write_cmd);
1566 if (optind > argc - 2) {
1568 return qemuio_command_usage(&aio_write_cmd);
1571 ctx->offset = cvtnum(argv[optind]);
1572 if (ctx->offset < 0) {
1573 printf("non-numeric length argument -- %s\n", argv[optind]);
1579 if (ctx->offset & 0x1ff) {
1580 printf("offset %" PRId64 " is not sector aligned\n",
1586 nr_iov = argc - optind;
1587 ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
1588 if (ctx->buf == NULL) {
1593 gettimeofday(&ctx->t1, NULL);
1594 bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1595 ctx->qiov.size >> 9, aio_write_done, ctx);
1599 static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1605 static const cmdinfo_t aio_flush_cmd = {
1606 .name = "aio_flush",
1607 .cfunc = aio_flush_f,
1608 .oneline = "completes all outstanding aio requests"
1611 static int flush_f(BlockDriverState *bs, int argc, char **argv)
1617 static const cmdinfo_t flush_cmd = {
1621 .oneline = "flush all in-core file state to disk",
1624 static int truncate_f(BlockDriverState *bs, int argc, char **argv)
1629 offset = cvtnum(argv[1]);
1631 printf("non-numeric truncate argument -- %s\n", argv[1]);
1635 ret = bdrv_truncate(bs, offset);
1637 printf("truncate: %s\n", strerror(-ret));
1644 static const cmdinfo_t truncate_cmd = {
1647 .cfunc = truncate_f,
1651 .oneline = "truncates the current file at the given offset",
1654 static int length_f(BlockDriverState *bs, int argc, char **argv)
1659 size = bdrv_getlength(bs);
1661 printf("getlength: %s\n", strerror(-size));
1665 cvtstr(size, s1, sizeof(s1));
1671 static const cmdinfo_t length_cmd = {
1675 .oneline = "gets the length of the current file",
1679 static int info_f(BlockDriverState *bs, int argc, char **argv)
1681 BlockDriverInfo bdi;
1682 ImageInfoSpecific *spec_info;
1683 char s1[64], s2[64];
1686 if (bs->drv && bs->drv->format_name) {
1687 printf("format name: %s\n", bs->drv->format_name);
1689 if (bs->drv && bs->drv->protocol_name) {
1690 printf("format name: %s\n", bs->drv->protocol_name);
1693 ret = bdrv_get_info(bs, &bdi);
1698 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1699 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1701 printf("cluster size: %s\n", s1);
1702 printf("vm state offset: %s\n", s2);
1704 spec_info = bdrv_get_specific_info(bs);
1706 printf("Format specific information:\n");
1707 bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
1708 qapi_free_ImageInfoSpecific(spec_info);
1716 static const cmdinfo_t info_cmd = {
1720 .oneline = "prints information about the current file",
1723 static void discard_help(void)
1727 " discards a range of bytes from the given offset\n"
1730 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1732 " Discards a segment of the currently open file.\n"
1733 " -C, -- report statistics in a machine parsable format\n"
1734 " -q, -- quiet mode, do not show I/O statistics\n"
1738 static int discard_f(BlockDriverState *bs, int argc, char **argv);
1740 static const cmdinfo_t discard_cmd = {
1746 .args = "[-Cq] off len",
1747 .oneline = "discards a number of bytes at a specified offset",
1748 .help = discard_help,
1751 static int discard_f(BlockDriverState *bs, int argc, char **argv)
1753 struct timeval t1, t2;
1754 int Cflag = 0, qflag = 0;
1759 while ((c = getopt(argc, argv, "Cq")) != EOF) {
1768 return qemuio_command_usage(&discard_cmd);
1772 if (optind != argc - 2) {
1773 return qemuio_command_usage(&discard_cmd);
1776 offset = cvtnum(argv[optind]);
1778 printf("non-numeric length argument -- %s\n", argv[optind]);
1783 count = cvtnum(argv[optind]);
1785 printf("non-numeric length argument -- %s\n", argv[optind]);
1789 gettimeofday(&t1, NULL);
1790 ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1791 count >> BDRV_SECTOR_BITS);
1792 gettimeofday(&t2, NULL);
1795 printf("discard failed: %s\n", strerror(-ret));
1799 /* Finally, report back -- -C gives a parsable format */
1802 print_report("discard", &t2, offset, count, count, 1, Cflag);
1809 static int alloc_f(BlockDriverState *bs, int argc, char **argv)
1811 int64_t offset, sector_num;
1812 int nb_sectors, remaining;
1817 offset = cvtnum(argv[1]);
1819 printf("non-numeric offset argument -- %s\n", argv[1]);
1821 } else if (offset & 0x1ff) {
1822 printf("offset %" PRId64 " is not sector aligned\n",
1828 nb_sectors = cvtnum(argv[2]);
1829 if (nb_sectors < 0) {
1830 printf("non-numeric length argument -- %s\n", argv[2]);
1837 remaining = nb_sectors;
1839 sector_num = offset >> 9;
1841 ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1843 printf("is_allocated failed: %s\n", strerror(-ret));
1852 nb_sectors -= remaining;
1857 cvtstr(offset, s1, sizeof(s1));
1859 printf("%d/%d sectors allocated at offset %s\n",
1860 sum_alloc, nb_sectors, s1);
1864 static const cmdinfo_t alloc_cmd = {
1870 .args = "off [sectors]",
1871 .oneline = "checks if a sector is present in the file",
1875 static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
1876 int64_t nb_sectors, int64_t *pnum)
1878 int num, num_checked;
1881 num_checked = MIN(nb_sectors, INT_MAX);
1882 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1890 while (nb_sectors > 0 && ret == firstret) {
1894 num_checked = MIN(nb_sectors, INT_MAX);
1895 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1896 if (ret == firstret) {
1906 static int map_f(BlockDriverState *bs, int argc, char **argv)
1916 nb_sectors = bs->total_sectors;
1919 ret = map_is_allocated(bs, offset, nb_sectors, &num);
1921 error_report("Failed to get allocation status: %s", strerror(-ret));
1925 retstr = ret ? " allocated" : "not allocated";
1926 cvtstr(offset << 9ULL, s1, sizeof(s1));
1927 printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
1928 "at offset %s (%d)\n",
1929 offset << 9ULL, num, nb_sectors, retstr, s1, ret);
1933 } while (offset < bs->total_sectors);
1938 static const cmdinfo_t map_cmd = {
1944 .oneline = "prints the allocated areas of a file",
1947 static int break_f(BlockDriverState *bs, int argc, char **argv)
1951 ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1953 printf("Could not set breakpoint: %s\n", strerror(-ret));
1959 static int remove_break_f(BlockDriverState *bs, int argc, char **argv)
1963 ret = bdrv_debug_remove_breakpoint(bs, argv[1]);
1965 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
1971 static const cmdinfo_t break_cmd = {
1976 .args = "event tag",
1977 .oneline = "sets a breakpoint on event and tags the stopped "
1981 static const cmdinfo_t remove_break_cmd = {
1982 .name = "remove_break",
1985 .cfunc = remove_break_f,
1987 .oneline = "remove a breakpoint by tag",
1990 static int resume_f(BlockDriverState *bs, int argc, char **argv)
1994 ret = bdrv_debug_resume(bs, argv[1]);
1996 printf("Could not resume request: %s\n", strerror(-ret));
2002 static const cmdinfo_t resume_cmd = {
2008 .oneline = "resumes the request tagged as tag",
2011 static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
2013 while (!bdrv_debug_is_suspended(bs, argv[1])) {
2020 static const cmdinfo_t wait_break_cmd = {
2021 .name = "wait_break",
2024 .cfunc = wait_break_f,
2026 .oneline = "waits for the suspension of a request",
2029 static int abort_f(BlockDriverState *bs, int argc, char **argv)
2034 static const cmdinfo_t abort_cmd = {
2037 .flags = CMD_NOFILE_OK,
2038 .oneline = "simulate a program crash using abort(3)",
2041 static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2046 printf("%s ", ct->name);
2048 printf("(or %s) ", ct->altname);
2053 printf("%s ", ct->args);
2055 printf("-- %s\n", ct->oneline);
2058 static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2060 help_oneline(cmd, ct);
2066 static void help_all(void)
2068 const cmdinfo_t *ct;
2070 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2071 help_oneline(ct->name, ct);
2073 printf("\nUse 'help commandname' for extended help.\n");
2076 static int help_f(BlockDriverState *bs, int argc, char **argv)
2078 const cmdinfo_t *ct;
2085 ct = find_command(argv[1]);
2087 printf("command %s not found\n", argv[1]);
2091 help_onecmd(argv[1], ct);
2095 static const cmdinfo_t help_cmd = {
2101 .flags = CMD_FLAG_GLOBAL,
2102 .args = "[command]",
2103 .oneline = "help for one or all commands",
2106 bool qemuio_command(BlockDriverState *bs, const char *cmd)
2109 const cmdinfo_t *ct;
2114 input = g_strdup(cmd);
2115 v = breakline(input, &c);
2117 ct = find_command(v[0]);
2119 done = command(bs, ct, c, v);
2121 fprintf(stderr, "command \"%s\" not found\n", v[0]);
2130 static void __attribute((constructor)) init_qemuio_commands(void)
2132 /* initialize commands */
2133 qemuio_add_command(&help_cmd);
2134 qemuio_add_command(&read_cmd);
2135 qemuio_add_command(&readv_cmd);
2136 qemuio_add_command(&write_cmd);
2137 qemuio_add_command(&writev_cmd);
2138 qemuio_add_command(&multiwrite_cmd);
2139 qemuio_add_command(&aio_read_cmd);
2140 qemuio_add_command(&aio_write_cmd);
2141 qemuio_add_command(&aio_flush_cmd);
2142 qemuio_add_command(&flush_cmd);
2143 qemuio_add_command(&truncate_cmd);
2144 qemuio_add_command(&length_cmd);
2145 qemuio_add_command(&info_cmd);
2146 qemuio_add_command(&discard_cmd);
2147 qemuio_add_command(&alloc_cmd);
2148 qemuio_add_command(&map_cmd);
2149 qemuio_add_command(&break_cmd);
2150 qemuio_add_command(&remove_break_cmd);
2151 qemuio_add_command(&resume_cmd);
2152 qemuio_add_command(&wait_break_cmd);
2153 qemuio_add_command(&abort_cmd);