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"
15 #include "qemu/timer.h"
17 #define CMD_NOFILE_OK 0x01
21 static cmdinfo_t *cmdtab;
24 static int compare_cmdname(const void *a, const void *b)
26 return strcmp(((const cmdinfo_t *)a)->name,
27 ((const cmdinfo_t *)b)->name);
30 void qemuio_add_command(const cmdinfo_t *ci)
32 cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
33 cmdtab[ncmds - 1] = *ci;
34 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
37 int qemuio_command_usage(const cmdinfo_t *ci)
39 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
43 static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
45 if (ct->flags & CMD_FLAG_GLOBAL) {
48 if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
49 fprintf(stderr, "no file open, try 'help open'\n");
55 static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
60 if (!init_check_command(bs, ct)) {
64 if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
65 if (ct->argmax == -1) {
67 "bad argument count %d to %s, expected at least %d arguments\n",
68 argc-1, cmd, ct->argmin);
69 } else if (ct->argmin == ct->argmax) {
71 "bad argument count %d to %s, expected %d arguments\n",
72 argc-1, cmd, ct->argmin);
75 "bad argument count %d to %s, expected between %d and %d arguments\n",
76 argc-1, cmd, ct->argmin, ct->argmax);
81 return ct->cfunc(bs, argc, argv);
84 static const cmdinfo_t *find_command(const char *cmd)
88 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
89 if (strcmp(ct->name, cmd) == 0 ||
90 (ct->altname && strcmp(ct->altname, cmd) == 0))
92 return (const cmdinfo_t *)ct;
98 /* Invoke fn() for commands with a matching prefix */
99 void qemuio_complete_command(const char *input,
100 void (*fn)(const char *cmd, void *opaque),
104 size_t input_len = strlen(input);
106 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
107 if (strncmp(input, ct->name, input_len) == 0) {
108 fn(ct->name, opaque);
113 static char **breakline(char *input, int *count)
117 char **rval = g_malloc0(sizeof(char *));
120 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
125 tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
141 static int64_t cvtnum(const char *s)
144 return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
147 #define EXABYTES(x) ((long long)(x) << 60)
148 #define PETABYTES(x) ((long long)(x) << 50)
149 #define TERABYTES(x) ((long long)(x) << 40)
150 #define GIGABYTES(x) ((long long)(x) << 30)
151 #define MEGABYTES(x) ((long long)(x) << 20)
152 #define KILOBYTES(x) ((long long)(x) << 10)
154 #define TO_EXABYTES(x) ((x) / EXABYTES(1))
155 #define TO_PETABYTES(x) ((x) / PETABYTES(1))
156 #define TO_TERABYTES(x) ((x) / TERABYTES(1))
157 #define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
158 #define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
159 #define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
161 static void cvtstr(double value, char *str, size_t size)
166 if (value >= EXABYTES(1)) {
168 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
169 } else if (value >= PETABYTES(1)) {
171 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
172 } else if (value >= TERABYTES(1)) {
174 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
175 } else if (value >= GIGABYTES(1)) {
177 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
178 } else if (value >= MEGABYTES(1)) {
180 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
181 } else if (value >= KILOBYTES(1)) {
183 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
186 snprintf(str, size - 6, "%f", value);
189 trim = strstr(str, ".000");
191 strcpy(trim, suffix);
199 static struct timeval tsub(struct timeval t1, struct timeval t2)
201 t1.tv_usec -= t2.tv_usec;
202 if (t1.tv_usec < 0) {
203 t1.tv_usec += 1000000;
206 t1.tv_sec -= t2.tv_sec;
210 static double tdiv(double value, struct timeval tv)
212 return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
215 #define HOURS(sec) ((sec) / (60 * 60))
216 #define MINUTES(sec) (((sec) % (60 * 60)) / 60)
217 #define SECONDS(sec) ((sec) % 60)
221 TERSE_FIXED_TIME = 0x1,
222 VERBOSE_FIXED_TIME = 0x2,
225 static void timestr(struct timeval *tv, char *ts, size_t size, int format)
227 double usec = (double)tv->tv_usec / 1000000.0;
229 if (format & TERSE_FIXED_TIME) {
230 if (!HOURS(tv->tv_sec)) {
231 snprintf(ts, size, "%u:%02u.%02u",
232 (unsigned int) MINUTES(tv->tv_sec),
233 (unsigned int) SECONDS(tv->tv_sec),
234 (unsigned int) (usec * 100));
237 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
240 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
241 snprintf(ts, size, "%u:%02u:%02u.%02u",
242 (unsigned int) HOURS(tv->tv_sec),
243 (unsigned int) MINUTES(tv->tv_sec),
244 (unsigned int) SECONDS(tv->tv_sec),
245 (unsigned int) (usec * 100));
247 snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
252 * Parse the pattern argument to various sub-commands.
254 * Because the pattern is used as an argument to memset it must evaluate
255 * to an unsigned integer that fits into a single byte.
257 static int parse_pattern(const char *arg)
262 pattern = strtol(arg, &endptr, 0);
263 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
264 printf("%s is not a valid pattern byte\n", arg);
272 * Memory allocation helpers.
274 * Make sure memory is aligned by default, or purposefully misaligned if
275 * that is specified on the command line.
278 #define MISALIGN_OFFSET 16
279 static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
283 if (qemuio_misalign) {
284 len += MISALIGN_OFFSET;
286 buf = qemu_blockalign(bs, len);
287 memset(buf, pattern, len);
288 if (qemuio_misalign) {
289 buf += MISALIGN_OFFSET;
294 static void qemu_io_free(void *p)
296 if (qemuio_misalign) {
297 p -= MISALIGN_OFFSET;
302 static void dump_buffer(const void *buffer, int64_t offset, int len)
307 for (i = 0, p = buffer; i < len; i += 16) {
308 const uint8_t *s = p;
310 printf("%08" PRIx64 ": ", offset + i);
311 for (j = 0; j < 16 && i + j < len; j++, p++) {
315 for (j = 0; j < 16 && i + j < len; j++, s++) {
326 static void print_report(const char *op, struct timeval *t, int64_t offset,
327 int count, int total, int cnt, int Cflag)
329 char s1[64], s2[64], ts[64];
331 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
333 cvtstr((double)total, s1, sizeof(s1));
334 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
335 printf("%s %d/%d bytes at offset %" PRId64 "\n",
336 op, total, count, offset);
337 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
338 s1, cnt, ts, s2, tdiv((double)cnt, *t));
339 } else {/* bytes,ops,time,bytes/sec,ops/sec */
340 printf("%d,%d,%s,%.3f,%.3f\n",
342 tdiv((double)total, *t),
343 tdiv((double)cnt, *t));
348 * Parse multiple length statements for vectored I/O, and construct an I/O
349 * vector matching it.
352 create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
355 size_t *sizes = g_new0(size_t, nr_iov);
361 for (i = 0; i < nr_iov; i++) {
367 printf("non-numeric length argument -- %s\n", arg);
371 /* should be SIZE_T_MAX, but that doesn't exist */
373 printf("too large length argument -- %s\n", arg);
378 printf("length argument %" PRId64
379 " is not sector aligned\n", len);
387 qemu_iovec_init(qiov, nr_iov);
389 buf = p = qemu_io_alloc(bs, count, pattern);
391 for (i = 0; i < nr_iov; i++) {
392 qemu_iovec_add(qiov, p, sizes[i]);
401 static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
406 ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
414 static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
419 ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
427 static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
430 *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
437 static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
440 *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
448 BlockDriverState *bs;
456 static void coroutine_fn co_write_zeroes_entry(void *opaque)
458 CoWriteZeroes *data = opaque;
460 data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
461 data->count / BDRV_SECTOR_SIZE, 0);
464 *data->total = data->ret;
468 *data->total = data->count;
471 static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
475 CoWriteZeroes data = {
483 co = qemu_coroutine_create(co_write_zeroes_entry);
484 qemu_coroutine_enter(co, &data);
486 aio_poll(bdrv_get_aio_context(bs), true);
495 static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
496 int count, int *total)
500 ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
508 static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
509 int count, int *total)
511 *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
518 static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
519 int count, int *total)
521 *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
528 #define NOT_DONE 0x7fffffff
529 static void aio_rw_done(void *opaque, int ret)
531 *(int *)opaque = ret;
534 static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
535 int64_t offset, int *total)
537 int async_ret = NOT_DONE;
539 bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
540 aio_rw_done, &async_ret);
541 while (async_ret == NOT_DONE) {
542 main_loop_wait(false);
546 return async_ret < 0 ? async_ret : 1;
549 static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
550 int64_t offset, int *total)
552 int async_ret = NOT_DONE;
554 bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
555 aio_rw_done, &async_ret);
556 while (async_ret == NOT_DONE) {
557 main_loop_wait(false);
561 return async_ret < 0 ? async_ret : 1;
564 struct multiwrite_async_ret {
569 static void multiwrite_cb(void *opaque, int ret)
571 struct multiwrite_async_ret *async_ret = opaque;
573 async_ret->num_done++;
575 async_ret->error = ret;
579 static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
580 int num_reqs, int *total)
583 struct multiwrite_async_ret async_ret = {
589 for (i = 0; i < num_reqs; i++) {
590 reqs[i].cb = multiwrite_cb;
591 reqs[i].opaque = &async_ret;
592 *total += reqs[i].qiov->size;
595 ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
600 while (async_ret.num_done < num_reqs) {
601 main_loop_wait(false);
604 return async_ret.error < 0 ? async_ret.error : 1;
607 static void read_help(void)
611 " reads a range of bytes from the given offset\n"
614 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
616 " Reads a segment of the currently open file, optionally dumping it to the\n"
617 " standard output stream (with -v option) for subsequent inspection.\n"
618 " -b, -- read from the VM state rather than the virtual disk\n"
619 " -C, -- report statistics in a machine parsable format\n"
620 " -l, -- length for pattern verification (only with -P)\n"
621 " -p, -- use bdrv_pread to read the file\n"
622 " -P, -- use a pattern to verify read data\n"
623 " -q, -- quiet mode, do not show I/O statistics\n"
624 " -s, -- start offset for pattern verification (only with -P)\n"
625 " -v, -- dump buffer to standard output\n"
629 static int read_f(BlockDriverState *bs, int argc, char **argv);
631 static const cmdinfo_t read_cmd = {
637 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
638 .oneline = "reads a number of bytes at a specified offset",
642 static int read_f(BlockDriverState *bs, int argc, char **argv)
644 struct timeval t1, t2;
645 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
646 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
651 /* Some compilers get confused and warn if this is not initialized. */
653 int pattern = 0, pattern_offset = 0, pattern_count = 0;
655 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
665 pattern_count = cvtnum(optarg);
666 if (pattern_count < 0) {
667 printf("non-numeric length argument -- %s\n", optarg);
676 pattern = parse_pattern(optarg);
686 pattern_offset = cvtnum(optarg);
687 if (pattern_offset < 0) {
688 printf("non-numeric length argument -- %s\n", optarg);
696 return qemuio_command_usage(&read_cmd);
700 if (optind != argc - 2) {
701 return qemuio_command_usage(&read_cmd);
704 if (bflag && pflag) {
705 printf("-b and -p cannot be specified at the same time\n");
709 offset = cvtnum(argv[optind]);
711 printf("non-numeric length argument -- %s\n", argv[optind]);
716 count = cvtnum(argv[optind]);
718 printf("non-numeric length argument -- %s\n", argv[optind]);
722 if (!Pflag && (lflag || sflag)) {
723 return qemuio_command_usage(&read_cmd);
727 pattern_count = count - pattern_offset;
730 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
731 printf("pattern verification range exceeds end of read data\n");
736 if (offset & 0x1ff) {
737 printf("offset %" PRId64 " is not sector aligned\n",
742 printf("count %d is not sector aligned\n",
748 buf = qemu_io_alloc(bs, count, 0xab);
750 gettimeofday(&t1, NULL);
752 cnt = do_pread(bs, buf, offset, count, &total);
754 cnt = do_load_vmstate(bs, buf, offset, count, &total);
756 cnt = do_read(bs, buf, offset, count, &total);
758 gettimeofday(&t2, NULL);
761 printf("read failed: %s\n", strerror(-cnt));
766 void *cmp_buf = g_malloc(pattern_count);
767 memset(cmp_buf, pattern, pattern_count);
768 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
769 printf("Pattern verification failed at offset %"
770 PRId64 ", %d bytes\n",
771 offset + pattern_offset, pattern_count);
781 dump_buffer(buf, offset, count);
784 /* Finally, report back -- -C gives a parsable format */
786 print_report("read", &t2, offset, count, total, cnt, Cflag);
794 static void readv_help(void)
798 " reads a range of bytes from the given offset into multiple buffers\n"
801 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
803 " Reads a segment of the currently open file, optionally dumping it to the\n"
804 " standard output stream (with -v option) for subsequent inspection.\n"
805 " Uses multiple iovec buffers if more than one byte range is specified.\n"
806 " -C, -- report statistics in a machine parsable format\n"
807 " -P, -- use a pattern to verify read data\n"
808 " -v, -- dump buffer to standard output\n"
809 " -q, -- quiet mode, do not show I/O statistics\n"
813 static int readv_f(BlockDriverState *bs, int argc, char **argv);
815 static const cmdinfo_t readv_cmd = {
820 .args = "[-Cqv] [-P pattern ] off len [len..]",
821 .oneline = "reads a number of bytes at a specified offset",
825 static int readv_f(BlockDriverState *bs, int argc, char **argv)
827 struct timeval t1, t2;
828 int Cflag = 0, qflag = 0, vflag = 0;
832 /* Some compilers get confused and warn if this is not initialized. */
839 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
846 pattern = parse_pattern(optarg);
858 return qemuio_command_usage(&readv_cmd);
862 if (optind > argc - 2) {
863 return qemuio_command_usage(&readv_cmd);
867 offset = cvtnum(argv[optind]);
869 printf("non-numeric length argument -- %s\n", argv[optind]);
874 if (offset & 0x1ff) {
875 printf("offset %" PRId64 " is not sector aligned\n",
880 nr_iov = argc - optind;
881 buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
886 gettimeofday(&t1, NULL);
887 cnt = do_aio_readv(bs, &qiov, offset, &total);
888 gettimeofday(&t2, NULL);
891 printf("readv failed: %s\n", strerror(-cnt));
896 void *cmp_buf = g_malloc(qiov.size);
897 memset(cmp_buf, pattern, qiov.size);
898 if (memcmp(buf, cmp_buf, qiov.size)) {
899 printf("Pattern verification failed at offset %"
900 PRId64 ", %zd bytes\n", offset, qiov.size);
910 dump_buffer(buf, offset, qiov.size);
913 /* Finally, report back -- -C gives a parsable format */
915 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
918 qemu_iovec_destroy(&qiov);
923 static void write_help(void)
927 " writes a range of bytes from the given offset\n"
930 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
932 " Writes into a segment of the currently open file, using a buffer\n"
933 " filled with a set pattern (0xcdcdcdcd).\n"
934 " -b, -- write to the VM state rather than the virtual disk\n"
935 " -c, -- write compressed data with bdrv_write_compressed\n"
936 " -p, -- use bdrv_pwrite to write the file\n"
937 " -P, -- use different pattern to fill file\n"
938 " -C, -- report statistics in a machine parsable format\n"
939 " -q, -- quiet mode, do not show I/O statistics\n"
940 " -z, -- write zeroes using bdrv_co_write_zeroes\n"
944 static int write_f(BlockDriverState *bs, int argc, char **argv);
946 static const cmdinfo_t write_cmd = {
952 .args = "[-bcCpqz] [-P pattern ] off len",
953 .oneline = "writes a number of bytes at a specified offset",
957 static int write_f(BlockDriverState *bs, int argc, char **argv)
959 struct timeval t1, t2;
960 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
966 /* Some compilers get confused and warn if this is not initialized. */
970 while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
986 pattern = parse_pattern(optarg);
998 return qemuio_command_usage(&write_cmd);
1002 if (optind != argc - 2) {
1003 return qemuio_command_usage(&write_cmd);
1006 if (bflag + pflag + zflag > 1) {
1007 printf("-b, -p, or -z cannot be specified at the same time\n");
1011 if (zflag && Pflag) {
1012 printf("-z and -P cannot be specified at the same time\n");
1016 offset = cvtnum(argv[optind]);
1018 printf("non-numeric length argument -- %s\n", argv[optind]);
1023 count = cvtnum(argv[optind]);
1025 printf("non-numeric length argument -- %s\n", argv[optind]);
1030 if (offset & 0x1ff) {
1031 printf("offset %" PRId64 " is not sector aligned\n",
1036 if (count & 0x1ff) {
1037 printf("count %d is not sector aligned\n",
1044 buf = qemu_io_alloc(bs, count, pattern);
1047 gettimeofday(&t1, NULL);
1049 cnt = do_pwrite(bs, buf, offset, count, &total);
1051 cnt = do_save_vmstate(bs, buf, offset, count, &total);
1053 cnt = do_co_write_zeroes(bs, offset, count, &total);
1055 cnt = do_write_compressed(bs, buf, offset, count, &total);
1057 cnt = do_write(bs, buf, offset, count, &total);
1059 gettimeofday(&t2, NULL);
1062 printf("write failed: %s\n", strerror(-cnt));
1070 /* Finally, report back -- -C gives a parsable format */
1072 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1087 " writes a range of bytes from the given offset source from multiple buffers\n"
1090 " 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1092 " Writes into a segment of the currently open file, using a buffer\n"
1093 " filled with a set pattern (0xcdcdcdcd).\n"
1094 " -P, -- use different pattern to fill file\n"
1095 " -C, -- report statistics in a machine parsable format\n"
1096 " -q, -- quiet mode, do not show I/O statistics\n"
1100 static int writev_f(BlockDriverState *bs, int argc, char **argv);
1102 static const cmdinfo_t writev_cmd = {
1107 .args = "[-Cq] [-P pattern ] off len [len..]",
1108 .oneline = "writes a number of bytes at a specified offset",
1109 .help = writev_help,
1112 static int writev_f(BlockDriverState *bs, int argc, char **argv)
1114 struct timeval t1, t2;
1115 int Cflag = 0, qflag = 0;
1119 /* Some compilers get confused and warn if this is not initialized. */
1125 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1134 pattern = parse_pattern(optarg);
1140 return qemuio_command_usage(&writev_cmd);
1144 if (optind > argc - 2) {
1145 return qemuio_command_usage(&writev_cmd);
1148 offset = cvtnum(argv[optind]);
1150 printf("non-numeric length argument -- %s\n", argv[optind]);
1155 if (offset & 0x1ff) {
1156 printf("offset %" PRId64 " is not sector aligned\n",
1161 nr_iov = argc - optind;
1162 buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
1167 gettimeofday(&t1, NULL);
1168 cnt = do_aio_writev(bs, &qiov, offset, &total);
1169 gettimeofday(&t2, NULL);
1172 printf("writev failed: %s\n", strerror(-cnt));
1180 /* Finally, report back -- -C gives a parsable format */
1182 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1184 qemu_iovec_destroy(&qiov);
1189 static void multiwrite_help(void)
1193 " writes a range of bytes from the given offset source from multiple buffers,\n"
1194 " in a batch of requests that may be merged by qemu\n"
1197 " 'multiwrite 512 1k 1k ; 4k 1k'\n"
1198 " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
1200 " Writes into a segment of the currently open file, using a buffer\n"
1201 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
1202 " by one for each request contained in the multiwrite command.\n"
1203 " -P, -- use different pattern to fill file\n"
1204 " -C, -- report statistics in a machine parsable format\n"
1205 " -q, -- quiet mode, do not show I/O statistics\n"
1209 static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
1211 static const cmdinfo_t multiwrite_cmd = {
1212 .name = "multiwrite",
1213 .cfunc = multiwrite_f,
1216 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
1217 .oneline = "issues multiple write requests at once",
1218 .help = multiwrite_help,
1221 static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
1223 struct timeval t1, t2;
1224 int Cflag = 0, qflag = 0;
1227 int64_t offset, first_offset = 0;
1228 /* Some compilers get confused and warn if this is not initialized. */
1233 QEMUIOVector *qiovs;
1237 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1246 pattern = parse_pattern(optarg);
1252 return qemuio_command_usage(&writev_cmd);
1256 if (optind > argc - 2) {
1257 return qemuio_command_usage(&writev_cmd);
1261 for (i = optind; i < argc; i++) {
1262 if (!strcmp(argv[i], ";")) {
1267 reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1268 buf = g_malloc0(nr_reqs * sizeof(*buf));
1269 qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1271 for (i = 0; i < nr_reqs && optind < argc; i++) {
1274 /* Read the offset of the request */
1275 offset = cvtnum(argv[optind]);
1277 printf("non-numeric offset argument -- %s\n", argv[optind]);
1282 if (offset & 0x1ff) {
1283 printf("offset %lld is not sector aligned\n",
1289 first_offset = offset;
1292 /* Read lengths for qiov entries */
1293 for (j = optind; j < argc; j++) {
1294 if (!strcmp(argv[j], ";")) {
1299 nr_iov = j - optind;
1302 buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
1303 if (buf[i] == NULL) {
1307 reqs[i].qiov = &qiovs[i];
1308 reqs[i].sector = offset >> 9;
1309 reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1316 /* If there were empty requests at the end, ignore them */
1319 gettimeofday(&t1, NULL);
1320 cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
1321 gettimeofday(&t2, NULL);
1324 printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1332 /* Finally, report back -- -C gives a parsable format */
1334 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1336 for (i = 0; i < nr_reqs; i++) {
1337 qemu_io_free(buf[i]);
1338 if (reqs[i].qiov != NULL) {
1339 qemu_iovec_destroy(&qiovs[i]);
1360 static void aio_write_done(void *opaque, int ret)
1362 struct aio_ctx *ctx = opaque;
1365 gettimeofday(&t2, NULL);
1369 printf("aio_write failed: %s\n", strerror(-ret));
1377 /* Finally, report back -- -C gives a parsable format */
1378 t2 = tsub(t2, ctx->t1);
1379 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1380 ctx->qiov.size, 1, ctx->Cflag);
1382 qemu_io_free(ctx->buf);
1383 qemu_iovec_destroy(&ctx->qiov);
1387 static void aio_read_done(void *opaque, int ret)
1389 struct aio_ctx *ctx = opaque;
1392 gettimeofday(&t2, NULL);
1395 printf("readv failed: %s\n", strerror(-ret));
1400 void *cmp_buf = g_malloc(ctx->qiov.size);
1402 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1403 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1404 printf("Pattern verification failed at offset %"
1405 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1415 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1418 /* Finally, report back -- -C gives a parsable format */
1419 t2 = tsub(t2, ctx->t1);
1420 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1421 ctx->qiov.size, 1, ctx->Cflag);
1423 qemu_io_free(ctx->buf);
1424 qemu_iovec_destroy(&ctx->qiov);
1428 static void aio_read_help(void)
1432 " asynchronously reads a range of bytes from the given offset\n"
1435 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1437 " Reads a segment of the currently open file, optionally dumping it to the\n"
1438 " standard output stream (with -v option) for subsequent inspection.\n"
1439 " The read is performed asynchronously and the aio_flush command must be\n"
1440 " used to ensure all outstanding aio requests have been completed.\n"
1441 " -C, -- report statistics in a machine parsable format\n"
1442 " -P, -- use a pattern to verify read data\n"
1443 " -v, -- dump buffer to standard output\n"
1444 " -q, -- quiet mode, do not show I/O statistics\n"
1448 static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1450 static const cmdinfo_t aio_read_cmd = {
1452 .cfunc = aio_read_f,
1455 .args = "[-Cqv] [-P pattern ] off len [len..]",
1456 .oneline = "asynchronously reads a number of bytes",
1457 .help = aio_read_help,
1460 static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
1463 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1465 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1472 ctx->pattern = parse_pattern(optarg);
1473 if (ctx->pattern < 0) {
1486 return qemuio_command_usage(&aio_read_cmd);
1490 if (optind > argc - 2) {
1492 return qemuio_command_usage(&aio_read_cmd);
1495 ctx->offset = cvtnum(argv[optind]);
1496 if (ctx->offset < 0) {
1497 printf("non-numeric length argument -- %s\n", argv[optind]);
1503 if (ctx->offset & 0x1ff) {
1504 printf("offset %" PRId64 " is not sector aligned\n",
1510 nr_iov = argc - optind;
1511 ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1512 if (ctx->buf == NULL) {
1517 gettimeofday(&ctx->t1, NULL);
1518 bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1519 ctx->qiov.size >> 9, aio_read_done, ctx);
1523 static void aio_write_help(void)
1527 " asynchronously writes a range of bytes from the given offset source\n"
1528 " from multiple buffers\n"
1531 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1533 " Writes into a segment of the currently open file, using a buffer\n"
1534 " filled with a set pattern (0xcdcdcdcd).\n"
1535 " The write is performed asynchronously and the aio_flush command must be\n"
1536 " used to ensure all outstanding aio requests have been completed.\n"
1537 " -P, -- use different pattern to fill file\n"
1538 " -C, -- report statistics in a machine parsable format\n"
1539 " -q, -- quiet mode, do not show I/O statistics\n"
1543 static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1545 static const cmdinfo_t aio_write_cmd = {
1546 .name = "aio_write",
1547 .cfunc = aio_write_f,
1550 .args = "[-Cq] [-P pattern ] off len [len..]",
1551 .oneline = "asynchronously writes a number of bytes",
1552 .help = aio_write_help,
1555 static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
1559 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1561 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1570 pattern = parse_pattern(optarg);
1578 return qemuio_command_usage(&aio_write_cmd);
1582 if (optind > argc - 2) {
1584 return qemuio_command_usage(&aio_write_cmd);
1587 ctx->offset = cvtnum(argv[optind]);
1588 if (ctx->offset < 0) {
1589 printf("non-numeric length argument -- %s\n", argv[optind]);
1595 if (ctx->offset & 0x1ff) {
1596 printf("offset %" PRId64 " is not sector aligned\n",
1602 nr_iov = argc - optind;
1603 ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
1604 if (ctx->buf == NULL) {
1609 gettimeofday(&ctx->t1, NULL);
1610 bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1611 ctx->qiov.size >> 9, aio_write_done, ctx);
1615 static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1621 static const cmdinfo_t aio_flush_cmd = {
1622 .name = "aio_flush",
1623 .cfunc = aio_flush_f,
1624 .oneline = "completes all outstanding aio requests"
1627 static int flush_f(BlockDriverState *bs, int argc, char **argv)
1633 static const cmdinfo_t flush_cmd = {
1637 .oneline = "flush all in-core file state to disk",
1640 static int truncate_f(BlockDriverState *bs, int argc, char **argv)
1645 offset = cvtnum(argv[1]);
1647 printf("non-numeric truncate argument -- %s\n", argv[1]);
1651 ret = bdrv_truncate(bs, offset);
1653 printf("truncate: %s\n", strerror(-ret));
1660 static const cmdinfo_t truncate_cmd = {
1663 .cfunc = truncate_f,
1667 .oneline = "truncates the current file at the given offset",
1670 static int length_f(BlockDriverState *bs, int argc, char **argv)
1675 size = bdrv_getlength(bs);
1677 printf("getlength: %s\n", strerror(-size));
1681 cvtstr(size, s1, sizeof(s1));
1687 static const cmdinfo_t length_cmd = {
1691 .oneline = "gets the length of the current file",
1695 static int info_f(BlockDriverState *bs, int argc, char **argv)
1697 BlockDriverInfo bdi;
1698 ImageInfoSpecific *spec_info;
1699 char s1[64], s2[64];
1702 if (bs->drv && bs->drv->format_name) {
1703 printf("format name: %s\n", bs->drv->format_name);
1705 if (bs->drv && bs->drv->protocol_name) {
1706 printf("format name: %s\n", bs->drv->protocol_name);
1709 ret = bdrv_get_info(bs, &bdi);
1714 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1715 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1717 printf("cluster size: %s\n", s1);
1718 printf("vm state offset: %s\n", s2);
1720 spec_info = bdrv_get_specific_info(bs);
1722 printf("Format specific information:\n");
1723 bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
1724 qapi_free_ImageInfoSpecific(spec_info);
1732 static const cmdinfo_t info_cmd = {
1736 .oneline = "prints information about the current file",
1739 static void discard_help(void)
1743 " discards a range of bytes from the given offset\n"
1746 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1748 " Discards a segment of the currently open file.\n"
1749 " -C, -- report statistics in a machine parsable format\n"
1750 " -q, -- quiet mode, do not show I/O statistics\n"
1754 static int discard_f(BlockDriverState *bs, int argc, char **argv);
1756 static const cmdinfo_t discard_cmd = {
1762 .args = "[-Cq] off len",
1763 .oneline = "discards a number of bytes at a specified offset",
1764 .help = discard_help,
1767 static int discard_f(BlockDriverState *bs, int argc, char **argv)
1769 struct timeval t1, t2;
1770 int Cflag = 0, qflag = 0;
1775 while ((c = getopt(argc, argv, "Cq")) != EOF) {
1784 return qemuio_command_usage(&discard_cmd);
1788 if (optind != argc - 2) {
1789 return qemuio_command_usage(&discard_cmd);
1792 offset = cvtnum(argv[optind]);
1794 printf("non-numeric length argument -- %s\n", argv[optind]);
1799 count = cvtnum(argv[optind]);
1801 printf("non-numeric length argument -- %s\n", argv[optind]);
1805 gettimeofday(&t1, NULL);
1806 ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1807 count >> BDRV_SECTOR_BITS);
1808 gettimeofday(&t2, NULL);
1811 printf("discard failed: %s\n", strerror(-ret));
1815 /* Finally, report back -- -C gives a parsable format */
1818 print_report("discard", &t2, offset, count, count, 1, Cflag);
1825 static int alloc_f(BlockDriverState *bs, int argc, char **argv)
1827 int64_t offset, sector_num;
1828 int nb_sectors, remaining;
1833 offset = cvtnum(argv[1]);
1835 printf("non-numeric offset argument -- %s\n", argv[1]);
1837 } else if (offset & 0x1ff) {
1838 printf("offset %" PRId64 " is not sector aligned\n",
1844 nb_sectors = cvtnum(argv[2]);
1845 if (nb_sectors < 0) {
1846 printf("non-numeric length argument -- %s\n", argv[2]);
1853 remaining = nb_sectors;
1855 sector_num = offset >> 9;
1857 ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1859 printf("is_allocated failed: %s\n", strerror(-ret));
1868 nb_sectors -= remaining;
1873 cvtstr(offset, s1, sizeof(s1));
1875 printf("%d/%d sectors allocated at offset %s\n",
1876 sum_alloc, nb_sectors, s1);
1880 static const cmdinfo_t alloc_cmd = {
1886 .args = "off [sectors]",
1887 .oneline = "checks if a sector is present in the file",
1891 static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
1892 int64_t nb_sectors, int64_t *pnum)
1894 int num, num_checked;
1897 num_checked = MIN(nb_sectors, INT_MAX);
1898 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1906 while (nb_sectors > 0 && ret == firstret) {
1910 num_checked = MIN(nb_sectors, INT_MAX);
1911 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1912 if (ret == firstret) {
1922 static int map_f(BlockDriverState *bs, int argc, char **argv)
1932 nb_sectors = bs->total_sectors;
1935 ret = map_is_allocated(bs, offset, nb_sectors, &num);
1937 error_report("Failed to get allocation status: %s", strerror(-ret));
1941 retstr = ret ? " allocated" : "not allocated";
1942 cvtstr(offset << 9ULL, s1, sizeof(s1));
1943 printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
1944 "at offset %s (%d)\n",
1945 offset << 9ULL, num, nb_sectors, retstr, s1, ret);
1949 } while (offset < bs->total_sectors);
1954 static const cmdinfo_t map_cmd = {
1960 .oneline = "prints the allocated areas of a file",
1963 static int break_f(BlockDriverState *bs, int argc, char **argv)
1967 ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1969 printf("Could not set breakpoint: %s\n", strerror(-ret));
1975 static int remove_break_f(BlockDriverState *bs, int argc, char **argv)
1979 ret = bdrv_debug_remove_breakpoint(bs, argv[1]);
1981 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
1987 static const cmdinfo_t break_cmd = {
1992 .args = "event tag",
1993 .oneline = "sets a breakpoint on event and tags the stopped "
1997 static const cmdinfo_t remove_break_cmd = {
1998 .name = "remove_break",
2001 .cfunc = remove_break_f,
2003 .oneline = "remove a breakpoint by tag",
2006 static int resume_f(BlockDriverState *bs, int argc, char **argv)
2010 ret = bdrv_debug_resume(bs, argv[1]);
2012 printf("Could not resume request: %s\n", strerror(-ret));
2018 static const cmdinfo_t resume_cmd = {
2024 .oneline = "resumes the request tagged as tag",
2027 static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
2029 while (!bdrv_debug_is_suspended(bs, argv[1])) {
2030 aio_poll(bdrv_get_aio_context(bs), true);
2036 static const cmdinfo_t wait_break_cmd = {
2037 .name = "wait_break",
2040 .cfunc = wait_break_f,
2042 .oneline = "waits for the suspension of a request",
2045 static int abort_f(BlockDriverState *bs, int argc, char **argv)
2050 static const cmdinfo_t abort_cmd = {
2053 .flags = CMD_NOFILE_OK,
2054 .oneline = "simulate a program crash using abort(3)",
2057 static void sleep_cb(void *opaque)
2059 bool *expired = opaque;
2063 static int sleep_f(BlockDriverState *bs, int argc, char **argv)
2067 struct QEMUTimer *timer;
2068 bool expired = false;
2070 ms = strtol(argv[1], &endptr, 0);
2071 if (ms < 0 || *endptr != '\0') {
2072 printf("%s is not a valid number\n", argv[1]);
2076 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2077 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2080 main_loop_wait(false);
2088 static const cmdinfo_t sleep_cmd = {
2093 .flags = CMD_NOFILE_OK,
2094 .oneline = "waits for the given value in milliseconds",
2097 static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2102 printf("%s ", ct->name);
2104 printf("(or %s) ", ct->altname);
2109 printf("%s ", ct->args);
2111 printf("-- %s\n", ct->oneline);
2114 static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2116 help_oneline(cmd, ct);
2122 static void help_all(void)
2124 const cmdinfo_t *ct;
2126 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2127 help_oneline(ct->name, ct);
2129 printf("\nUse 'help commandname' for extended help.\n");
2132 static int help_f(BlockDriverState *bs, int argc, char **argv)
2134 const cmdinfo_t *ct;
2141 ct = find_command(argv[1]);
2143 printf("command %s not found\n", argv[1]);
2147 help_onecmd(argv[1], ct);
2151 static const cmdinfo_t help_cmd = {
2157 .flags = CMD_FLAG_GLOBAL,
2158 .args = "[command]",
2159 .oneline = "help for one or all commands",
2162 bool qemuio_command(BlockDriverState *bs, const char *cmd)
2165 const cmdinfo_t *ct;
2170 input = g_strdup(cmd);
2171 v = breakline(input, &c);
2173 ct = find_command(v[0]);
2175 done = command(bs, ct, c, v);
2177 fprintf(stderr, "command \"%s\" not found\n", v[0]);
2186 static void __attribute((constructor)) init_qemuio_commands(void)
2188 /* initialize commands */
2189 qemuio_add_command(&help_cmd);
2190 qemuio_add_command(&read_cmd);
2191 qemuio_add_command(&readv_cmd);
2192 qemuio_add_command(&write_cmd);
2193 qemuio_add_command(&writev_cmd);
2194 qemuio_add_command(&multiwrite_cmd);
2195 qemuio_add_command(&aio_read_cmd);
2196 qemuio_add_command(&aio_write_cmd);
2197 qemuio_add_command(&aio_flush_cmd);
2198 qemuio_add_command(&flush_cmd);
2199 qemuio_add_command(&truncate_cmd);
2200 qemuio_add_command(&length_cmd);
2201 qemuio_add_command(&info_cmd);
2202 qemuio_add_command(&discard_cmd);
2203 qemuio_add_command(&alloc_cmd);
2204 qemuio_add_command(&map_cmd);
2205 qemuio_add_command(&break_cmd);
2206 qemuio_add_command(&remove_break_cmd);
2207 qemuio_add_command(&resume_cmd);
2208 qemuio_add_command(&wait_break_cmd);
2209 qemuio_add_command(&abort_cmd);
2210 qemuio_add_command(&sleep_cmd);