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.
11 #include <sys/types.h>
17 #include "qemu-common.h"
18 #include "qemu/main-loop.h"
19 #include "block/block_int.h"
21 #include "trace/control.h"
23 #define VERSION "0.0.1"
25 #define CMD_NOFILE_OK 0x01
28 static BlockDriverState *bs;
33 * Parse the pattern argument to various sub-commands.
35 * Because the pattern is used as an argument to memset it must evaluate
36 * to an unsigned integer that fits into a single byte.
38 static int parse_pattern(const char *arg)
43 pattern = strtol(arg, &endptr, 0);
44 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
45 printf("%s is not a valid pattern byte\n", arg);
53 * Memory allocation helpers.
55 * Make sure memory is aligned by default, or purposefully misaligned if
56 * that is specified on the command line.
59 #define MISALIGN_OFFSET 16
60 static void *qemu_io_alloc(size_t len, int pattern)
65 len += MISALIGN_OFFSET;
67 buf = qemu_blockalign(bs, len);
68 memset(buf, pattern, len);
70 buf += MISALIGN_OFFSET;
75 static void qemu_io_free(void *p)
83 static void dump_buffer(const void *buffer, int64_t offset, int len)
88 for (i = 0, p = buffer; i < len; i += 16) {
91 printf("%08" PRIx64 ": ", offset + i);
92 for (j = 0; j < 16 && i + j < len; j++, p++) {
96 for (j = 0; j < 16 && i + j < len; j++, s++) {
107 static void print_report(const char *op, struct timeval *t, int64_t offset,
108 int count, int total, int cnt, int Cflag)
110 char s1[64], s2[64], ts[64];
112 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
114 cvtstr((double)total, s1, sizeof(s1));
115 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
116 printf("%s %d/%d bytes at offset %" PRId64 "\n",
117 op, total, count, offset);
118 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
119 s1, cnt, ts, s2, tdiv((double)cnt, *t));
120 } else {/* bytes,ops,time,bytes/sec,ops/sec */
121 printf("%d,%d,%s,%.3f,%.3f\n",
123 tdiv((double)total, *t),
124 tdiv((double)cnt, *t));
129 * Parse multiple length statements for vectored I/O, and construct an I/O
130 * vector matching it.
133 create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
135 size_t *sizes = g_new0(size_t, nr_iov);
141 for (i = 0; i < nr_iov; i++) {
147 printf("non-numeric length argument -- %s\n", arg);
151 /* should be SIZE_T_MAX, but that doesn't exist */
153 printf("too large length argument -- %s\n", arg);
158 printf("length argument %" PRId64
159 " is not sector aligned\n", len);
167 qemu_iovec_init(qiov, nr_iov);
169 buf = p = qemu_io_alloc(count, pattern);
171 for (i = 0; i < nr_iov; i++) {
172 qemu_iovec_add(qiov, p, sizes[i]);
181 static int do_read(char *buf, int64_t offset, int count, int *total)
185 ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
193 static int do_write(char *buf, int64_t offset, int count, int *total)
197 ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
205 static int do_pread(char *buf, int64_t offset, int count, int *total)
207 *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
214 static int do_pwrite(char *buf, int64_t offset, int count, int *total)
216 *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
231 static void coroutine_fn co_write_zeroes_entry(void *opaque)
233 CoWriteZeroes *data = opaque;
235 data->ret = bdrv_co_write_zeroes(bs, data->offset / BDRV_SECTOR_SIZE,
236 data->count / BDRV_SECTOR_SIZE);
239 *data->total = data->ret;
243 *data->total = data->count;
246 static int do_co_write_zeroes(int64_t offset, int count, int *total)
249 CoWriteZeroes data = {
256 co = qemu_coroutine_create(co_write_zeroes_entry);
257 qemu_coroutine_enter(co, &data);
268 static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
272 ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
280 static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
282 *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
289 static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
291 *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
298 #define NOT_DONE 0x7fffffff
299 static void aio_rw_done(void *opaque, int ret)
301 *(int *)opaque = ret;
304 static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
306 int async_ret = NOT_DONE;
308 bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
309 aio_rw_done, &async_ret);
310 while (async_ret == NOT_DONE) {
311 main_loop_wait(false);
315 return async_ret < 0 ? async_ret : 1;
318 static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
320 int async_ret = NOT_DONE;
322 bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
323 aio_rw_done, &async_ret);
324 while (async_ret == NOT_DONE) {
325 main_loop_wait(false);
329 return async_ret < 0 ? async_ret : 1;
332 struct multiwrite_async_ret {
337 static void multiwrite_cb(void *opaque, int ret)
339 struct multiwrite_async_ret *async_ret = opaque;
341 async_ret->num_done++;
343 async_ret->error = ret;
347 static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
350 struct multiwrite_async_ret async_ret = {
356 for (i = 0; i < num_reqs; i++) {
357 reqs[i].cb = multiwrite_cb;
358 reqs[i].opaque = &async_ret;
359 *total += reqs[i].qiov->size;
362 ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
367 while (async_ret.num_done < num_reqs) {
368 main_loop_wait(false);
371 return async_ret.error < 0 ? async_ret.error : 1;
374 static void read_help(void)
378 " reads a range of bytes from the given offset\n"
381 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
383 " Reads a segment of the currently open file, optionally dumping it to the\n"
384 " standard output stream (with -v option) for subsequent inspection.\n"
385 " -b, -- read from the VM state rather than the virtual disk\n"
386 " -C, -- report statistics in a machine parsable format\n"
387 " -l, -- length for pattern verification (only with -P)\n"
388 " -p, -- use bdrv_pread to read the file\n"
389 " -P, -- use a pattern to verify read data\n"
390 " -q, -- quiet mode, do not show I/O statistics\n"
391 " -s, -- start offset for pattern verification (only with -P)\n"
392 " -v, -- dump buffer to standard output\n"
396 static int read_f(int argc, char **argv);
398 static const cmdinfo_t read_cmd = {
404 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
405 .oneline = "reads a number of bytes at a specified offset",
409 static int read_f(int argc, char **argv)
411 struct timeval t1, t2;
412 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
413 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
418 /* Some compilers get confused and warn if this is not initialized. */
420 int pattern = 0, pattern_offset = 0, pattern_count = 0;
422 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
432 pattern_count = cvtnum(optarg);
433 if (pattern_count < 0) {
434 printf("non-numeric length argument -- %s\n", optarg);
443 pattern = parse_pattern(optarg);
453 pattern_offset = cvtnum(optarg);
454 if (pattern_offset < 0) {
455 printf("non-numeric length argument -- %s\n", optarg);
463 return command_usage(&read_cmd);
467 if (optind != argc - 2) {
468 return command_usage(&read_cmd);
471 if (bflag && pflag) {
472 printf("-b and -p cannot be specified at the same time\n");
476 offset = cvtnum(argv[optind]);
478 printf("non-numeric length argument -- %s\n", argv[optind]);
483 count = cvtnum(argv[optind]);
485 printf("non-numeric length argument -- %s\n", argv[optind]);
489 if (!Pflag && (lflag || sflag)) {
490 return command_usage(&read_cmd);
494 pattern_count = count - pattern_offset;
497 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
498 printf("pattern verification range exceeds end of read data\n");
503 if (offset & 0x1ff) {
504 printf("offset %" PRId64 " is not sector aligned\n",
509 printf("count %d is not sector aligned\n",
515 buf = qemu_io_alloc(count, 0xab);
517 gettimeofday(&t1, NULL);
519 cnt = do_pread(buf, offset, count, &total);
521 cnt = do_load_vmstate(buf, offset, count, &total);
523 cnt = do_read(buf, offset, count, &total);
525 gettimeofday(&t2, NULL);
528 printf("read failed: %s\n", strerror(-cnt));
533 void *cmp_buf = g_malloc(pattern_count);
534 memset(cmp_buf, pattern, pattern_count);
535 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
536 printf("Pattern verification failed at offset %"
537 PRId64 ", %d bytes\n",
538 offset + pattern_offset, pattern_count);
548 dump_buffer(buf, offset, count);
551 /* Finally, report back -- -C gives a parsable format */
553 print_report("read", &t2, offset, count, total, cnt, Cflag);
561 static void readv_help(void)
565 " reads a range of bytes from the given offset into multiple buffers\n"
568 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
570 " Reads a segment of the currently open file, optionally dumping it to the\n"
571 " standard output stream (with -v option) for subsequent inspection.\n"
572 " Uses multiple iovec buffers if more than one byte range is specified.\n"
573 " -C, -- report statistics in a machine parsable format\n"
574 " -P, -- use a pattern to verify read data\n"
575 " -v, -- dump buffer to standard output\n"
576 " -q, -- quiet mode, do not show I/O statistics\n"
580 static int readv_f(int argc, char **argv);
582 static const cmdinfo_t readv_cmd = {
587 .args = "[-Cqv] [-P pattern ] off len [len..]",
588 .oneline = "reads a number of bytes at a specified offset",
592 static int readv_f(int argc, char **argv)
594 struct timeval t1, t2;
595 int Cflag = 0, qflag = 0, vflag = 0;
599 /* Some compilers get confused and warn if this is not initialized. */
606 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
613 pattern = parse_pattern(optarg);
625 return command_usage(&readv_cmd);
629 if (optind > argc - 2) {
630 return command_usage(&readv_cmd);
634 offset = cvtnum(argv[optind]);
636 printf("non-numeric length argument -- %s\n", argv[optind]);
641 if (offset & 0x1ff) {
642 printf("offset %" PRId64 " is not sector aligned\n",
647 nr_iov = argc - optind;
648 buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
653 gettimeofday(&t1, NULL);
654 cnt = do_aio_readv(&qiov, offset, &total);
655 gettimeofday(&t2, NULL);
658 printf("readv failed: %s\n", strerror(-cnt));
663 void *cmp_buf = g_malloc(qiov.size);
664 memset(cmp_buf, pattern, qiov.size);
665 if (memcmp(buf, cmp_buf, qiov.size)) {
666 printf("Pattern verification failed at offset %"
667 PRId64 ", %zd bytes\n", offset, qiov.size);
677 dump_buffer(buf, offset, qiov.size);
680 /* Finally, report back -- -C gives a parsable format */
682 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
685 qemu_iovec_destroy(&qiov);
690 static void write_help(void)
694 " writes a range of bytes from the given offset\n"
697 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
699 " Writes into a segment of the currently open file, using a buffer\n"
700 " filled with a set pattern (0xcdcdcdcd).\n"
701 " -b, -- write to the VM state rather than the virtual disk\n"
702 " -c, -- write compressed data with bdrv_write_compressed\n"
703 " -p, -- use bdrv_pwrite to write the file\n"
704 " -P, -- use different pattern to fill file\n"
705 " -C, -- report statistics in a machine parsable format\n"
706 " -q, -- quiet mode, do not show I/O statistics\n"
707 " -z, -- write zeroes using bdrv_co_write_zeroes\n"
711 static int write_f(int argc, char **argv);
713 static const cmdinfo_t write_cmd = {
719 .args = "[-bcCpqz] [-P pattern ] off len",
720 .oneline = "writes a number of bytes at a specified offset",
724 static int write_f(int argc, char **argv)
726 struct timeval t1, t2;
727 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
733 /* Some compilers get confused and warn if this is not initialized. */
737 while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
753 pattern = parse_pattern(optarg);
765 return command_usage(&write_cmd);
769 if (optind != argc - 2) {
770 return command_usage(&write_cmd);
773 if (bflag + pflag + zflag > 1) {
774 printf("-b, -p, or -z cannot be specified at the same time\n");
778 if (zflag && Pflag) {
779 printf("-z and -P cannot be specified at the same time\n");
783 offset = cvtnum(argv[optind]);
785 printf("non-numeric length argument -- %s\n", argv[optind]);
790 count = cvtnum(argv[optind]);
792 printf("non-numeric length argument -- %s\n", argv[optind]);
797 if (offset & 0x1ff) {
798 printf("offset %" PRId64 " is not sector aligned\n",
804 printf("count %d is not sector aligned\n",
811 buf = qemu_io_alloc(count, pattern);
814 gettimeofday(&t1, NULL);
816 cnt = do_pwrite(buf, offset, count, &total);
818 cnt = do_save_vmstate(buf, offset, count, &total);
820 cnt = do_co_write_zeroes(offset, count, &total);
822 cnt = do_write_compressed(buf, offset, count, &total);
824 cnt = do_write(buf, offset, count, &total);
826 gettimeofday(&t2, NULL);
829 printf("write failed: %s\n", strerror(-cnt));
837 /* Finally, report back -- -C gives a parsable format */
839 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
854 " writes a range of bytes from the given offset source from multiple buffers\n"
857 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
859 " Writes into a segment of the currently open file, using a buffer\n"
860 " filled with a set pattern (0xcdcdcdcd).\n"
861 " -P, -- use different pattern to fill file\n"
862 " -C, -- report statistics in a machine parsable format\n"
863 " -q, -- quiet mode, do not show I/O statistics\n"
867 static int writev_f(int argc, char **argv);
869 static const cmdinfo_t writev_cmd = {
874 .args = "[-Cq] [-P pattern ] off len [len..]",
875 .oneline = "writes a number of bytes at a specified offset",
879 static int writev_f(int argc, char **argv)
881 struct timeval t1, t2;
882 int Cflag = 0, qflag = 0;
886 /* Some compilers get confused and warn if this is not initialized. */
892 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
901 pattern = parse_pattern(optarg);
907 return command_usage(&writev_cmd);
911 if (optind > argc - 2) {
912 return command_usage(&writev_cmd);
915 offset = cvtnum(argv[optind]);
917 printf("non-numeric length argument -- %s\n", argv[optind]);
922 if (offset & 0x1ff) {
923 printf("offset %" PRId64 " is not sector aligned\n",
928 nr_iov = argc - optind;
929 buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
934 gettimeofday(&t1, NULL);
935 cnt = do_aio_writev(&qiov, offset, &total);
936 gettimeofday(&t2, NULL);
939 printf("writev failed: %s\n", strerror(-cnt));
947 /* Finally, report back -- -C gives a parsable format */
949 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
951 qemu_iovec_destroy(&qiov);
956 static void multiwrite_help(void)
960 " writes a range of bytes from the given offset source from multiple buffers,\n"
961 " in a batch of requests that may be merged by qemu\n"
964 " 'multiwrite 512 1k 1k ; 4k 1k'\n"
965 " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
967 " Writes into a segment of the currently open file, using a buffer\n"
968 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
969 " by one for each request contained in the multiwrite command.\n"
970 " -P, -- use different pattern to fill file\n"
971 " -C, -- report statistics in a machine parsable format\n"
972 " -q, -- quiet mode, do not show I/O statistics\n"
976 static int multiwrite_f(int argc, char **argv);
978 static const cmdinfo_t multiwrite_cmd = {
979 .name = "multiwrite",
980 .cfunc = multiwrite_f,
983 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
984 .oneline = "issues multiple write requests at once",
985 .help = multiwrite_help,
988 static int multiwrite_f(int argc, char **argv)
990 struct timeval t1, t2;
991 int Cflag = 0, qflag = 0;
994 int64_t offset, first_offset = 0;
995 /* Some compilers get confused and warn if this is not initialized. */
1000 QEMUIOVector *qiovs;
1004 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1013 pattern = parse_pattern(optarg);
1019 return command_usage(&writev_cmd);
1023 if (optind > argc - 2) {
1024 return command_usage(&writev_cmd);
1028 for (i = optind; i < argc; i++) {
1029 if (!strcmp(argv[i], ";")) {
1034 reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1035 buf = g_malloc0(nr_reqs * sizeof(*buf));
1036 qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1038 for (i = 0; i < nr_reqs && optind < argc; i++) {
1041 /* Read the offset of the request */
1042 offset = cvtnum(argv[optind]);
1044 printf("non-numeric offset argument -- %s\n", argv[optind]);
1049 if (offset & 0x1ff) {
1050 printf("offset %lld is not sector aligned\n",
1056 first_offset = offset;
1059 /* Read lengths for qiov entries */
1060 for (j = optind; j < argc; j++) {
1061 if (!strcmp(argv[j], ";")) {
1066 nr_iov = j - optind;
1069 buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern);
1070 if (buf[i] == NULL) {
1074 reqs[i].qiov = &qiovs[i];
1075 reqs[i].sector = offset >> 9;
1076 reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1083 /* If there were empty requests at the end, ignore them */
1086 gettimeofday(&t1, NULL);
1087 cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
1088 gettimeofday(&t2, NULL);
1091 printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1099 /* Finally, report back -- -C gives a parsable format */
1101 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1103 for (i = 0; i < nr_reqs; i++) {
1104 qemu_io_free(buf[i]);
1105 if (reqs[i].qiov != NULL) {
1106 qemu_iovec_destroy(&qiovs[i]);
1127 static void aio_write_done(void *opaque, int ret)
1129 struct aio_ctx *ctx = opaque;
1132 gettimeofday(&t2, NULL);
1136 printf("aio_write failed: %s\n", strerror(-ret));
1144 /* Finally, report back -- -C gives a parsable format */
1145 t2 = tsub(t2, ctx->t1);
1146 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1147 ctx->qiov.size, 1, ctx->Cflag);
1149 qemu_io_free(ctx->buf);
1150 qemu_iovec_destroy(&ctx->qiov);
1154 static void aio_read_done(void *opaque, int ret)
1156 struct aio_ctx *ctx = opaque;
1159 gettimeofday(&t2, NULL);
1162 printf("readv failed: %s\n", strerror(-ret));
1167 void *cmp_buf = g_malloc(ctx->qiov.size);
1169 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1170 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1171 printf("Pattern verification failed at offset %"
1172 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1182 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1185 /* Finally, report back -- -C gives a parsable format */
1186 t2 = tsub(t2, ctx->t1);
1187 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1188 ctx->qiov.size, 1, ctx->Cflag);
1190 qemu_io_free(ctx->buf);
1191 qemu_iovec_destroy(&ctx->qiov);
1195 static void aio_read_help(void)
1199 " asynchronously reads a range of bytes from the given offset\n"
1202 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1204 " Reads a segment of the currently open file, optionally dumping it to the\n"
1205 " standard output stream (with -v option) for subsequent inspection.\n"
1206 " The read is performed asynchronously and the aio_flush command must be\n"
1207 " used to ensure all outstanding aio requests have been completed.\n"
1208 " -C, -- report statistics in a machine parsable format\n"
1209 " -P, -- use a pattern to verify read data\n"
1210 " -v, -- dump buffer to standard output\n"
1211 " -q, -- quiet mode, do not show I/O statistics\n"
1215 static int aio_read_f(int argc, char **argv);
1217 static const cmdinfo_t aio_read_cmd = {
1219 .cfunc = aio_read_f,
1222 .args = "[-Cqv] [-P pattern ] off len [len..]",
1223 .oneline = "asynchronously reads a number of bytes",
1224 .help = aio_read_help,
1227 static int aio_read_f(int argc, char **argv)
1230 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1232 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1239 ctx->pattern = parse_pattern(optarg);
1240 if (ctx->pattern < 0) {
1253 return command_usage(&aio_read_cmd);
1257 if (optind > argc - 2) {
1259 return command_usage(&aio_read_cmd);
1262 ctx->offset = cvtnum(argv[optind]);
1263 if (ctx->offset < 0) {
1264 printf("non-numeric length argument -- %s\n", argv[optind]);
1270 if (ctx->offset & 0x1ff) {
1271 printf("offset %" PRId64 " is not sector aligned\n",
1277 nr_iov = argc - optind;
1278 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
1279 if (ctx->buf == NULL) {
1284 gettimeofday(&ctx->t1, NULL);
1285 bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1286 ctx->qiov.size >> 9, aio_read_done, ctx);
1290 static void aio_write_help(void)
1294 " asynchronously writes a range of bytes from the given offset source\n"
1295 " from multiple buffers\n"
1298 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1300 " Writes into a segment of the currently open file, using a buffer\n"
1301 " filled with a set pattern (0xcdcdcdcd).\n"
1302 " The write is performed asynchronously and the aio_flush command must be\n"
1303 " used to ensure all outstanding aio requests have been completed.\n"
1304 " -P, -- use different pattern to fill file\n"
1305 " -C, -- report statistics in a machine parsable format\n"
1306 " -q, -- quiet mode, do not show I/O statistics\n"
1310 static int aio_write_f(int argc, char **argv);
1312 static const cmdinfo_t aio_write_cmd = {
1313 .name = "aio_write",
1314 .cfunc = aio_write_f,
1317 .args = "[-Cq] [-P pattern ] off len [len..]",
1318 .oneline = "asynchronously writes a number of bytes",
1319 .help = aio_write_help,
1322 static int aio_write_f(int argc, char **argv)
1326 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1328 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1337 pattern = parse_pattern(optarg);
1345 return command_usage(&aio_write_cmd);
1349 if (optind > argc - 2) {
1351 return command_usage(&aio_write_cmd);
1354 ctx->offset = cvtnum(argv[optind]);
1355 if (ctx->offset < 0) {
1356 printf("non-numeric length argument -- %s\n", argv[optind]);
1362 if (ctx->offset & 0x1ff) {
1363 printf("offset %" PRId64 " is not sector aligned\n",
1369 nr_iov = argc - optind;
1370 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
1371 if (ctx->buf == NULL) {
1376 gettimeofday(&ctx->t1, NULL);
1377 bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1378 ctx->qiov.size >> 9, aio_write_done, ctx);
1382 static int aio_flush_f(int argc, char **argv)
1388 static const cmdinfo_t aio_flush_cmd = {
1389 .name = "aio_flush",
1390 .cfunc = aio_flush_f,
1391 .oneline = "completes all outstanding aio requests"
1394 static int flush_f(int argc, char **argv)
1400 static const cmdinfo_t flush_cmd = {
1404 .oneline = "flush all in-core file state to disk",
1407 static int truncate_f(int argc, char **argv)
1412 offset = cvtnum(argv[1]);
1414 printf("non-numeric truncate argument -- %s\n", argv[1]);
1418 ret = bdrv_truncate(bs, offset);
1420 printf("truncate: %s\n", strerror(-ret));
1427 static const cmdinfo_t truncate_cmd = {
1430 .cfunc = truncate_f,
1434 .oneline = "truncates the current file at the given offset",
1437 static int length_f(int argc, char **argv)
1442 size = bdrv_getlength(bs);
1444 printf("getlength: %s\n", strerror(-size));
1448 cvtstr(size, s1, sizeof(s1));
1454 static const cmdinfo_t length_cmd = {
1458 .oneline = "gets the length of the current file",
1462 static int info_f(int argc, char **argv)
1464 BlockDriverInfo bdi;
1465 char s1[64], s2[64];
1468 if (bs->drv && bs->drv->format_name) {
1469 printf("format name: %s\n", bs->drv->format_name);
1471 if (bs->drv && bs->drv->protocol_name) {
1472 printf("format name: %s\n", bs->drv->protocol_name);
1475 ret = bdrv_get_info(bs, &bdi);
1480 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1481 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1483 printf("cluster size: %s\n", s1);
1484 printf("vm state offset: %s\n", s2);
1491 static const cmdinfo_t info_cmd = {
1495 .oneline = "prints information about the current file",
1498 static void discard_help(void)
1502 " discards a range of bytes from the given offset\n"
1505 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1507 " Discards a segment of the currently open file.\n"
1508 " -C, -- report statistics in a machine parsable format\n"
1509 " -q, -- quiet mode, do not show I/O statistics\n"
1513 static int discard_f(int argc, char **argv);
1515 static const cmdinfo_t discard_cmd = {
1521 .args = "[-Cq] off len",
1522 .oneline = "discards a number of bytes at a specified offset",
1523 .help = discard_help,
1526 static int discard_f(int argc, char **argv)
1528 struct timeval t1, t2;
1529 int Cflag = 0, qflag = 0;
1534 while ((c = getopt(argc, argv, "Cq")) != EOF) {
1543 return command_usage(&discard_cmd);
1547 if (optind != argc - 2) {
1548 return command_usage(&discard_cmd);
1551 offset = cvtnum(argv[optind]);
1553 printf("non-numeric length argument -- %s\n", argv[optind]);
1558 count = cvtnum(argv[optind]);
1560 printf("non-numeric length argument -- %s\n", argv[optind]);
1564 gettimeofday(&t1, NULL);
1565 ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1566 count >> BDRV_SECTOR_BITS);
1567 gettimeofday(&t2, NULL);
1570 printf("discard failed: %s\n", strerror(-ret));
1574 /* Finally, report back -- -C gives a parsable format */
1577 print_report("discard", &t2, offset, count, count, 1, Cflag);
1584 static int alloc_f(int argc, char **argv)
1586 int64_t offset, sector_num;
1587 int nb_sectors, remaining;
1592 offset = cvtnum(argv[1]);
1593 if (offset & 0x1ff) {
1594 printf("offset %" PRId64 " is not sector aligned\n",
1600 nb_sectors = cvtnum(argv[2]);
1605 remaining = nb_sectors;
1607 sector_num = offset >> 9;
1609 ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1616 nb_sectors -= remaining;
1621 cvtstr(offset, s1, sizeof(s1));
1623 printf("%d/%d sectors allocated at offset %s\n",
1624 sum_alloc, nb_sectors, s1);
1628 static const cmdinfo_t alloc_cmd = {
1634 .args = "off [sectors]",
1635 .oneline = "checks if a sector is present in the file",
1638 static int map_f(int argc, char **argv)
1643 int num, num_checked;
1648 nb_sectors = bs->total_sectors;
1651 num_checked = MIN(nb_sectors, INT_MAX);
1652 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
1653 retstr = ret ? " allocated" : "not allocated";
1654 cvtstr(offset << 9ULL, s1, sizeof(s1));
1655 printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
1656 offset << 9ULL, num, num_checked, retstr, s1, ret);
1660 } while (offset < bs->total_sectors);
1665 static const cmdinfo_t map_cmd = {
1671 .oneline = "prints the allocated areas of a file",
1674 static int break_f(int argc, char **argv)
1678 ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1680 printf("Could not set breakpoint: %s\n", strerror(-ret));
1686 static const cmdinfo_t break_cmd = {
1691 .args = "event tag",
1692 .oneline = "sets a breakpoint on event and tags the stopped "
1696 static int resume_f(int argc, char **argv)
1700 ret = bdrv_debug_resume(bs, argv[1]);
1702 printf("Could not resume request: %s\n", strerror(-ret));
1708 static const cmdinfo_t resume_cmd = {
1714 .oneline = "resumes the request tagged as tag",
1717 static int wait_break_f(int argc, char **argv)
1719 while (!bdrv_debug_is_suspended(bs, argv[1])) {
1726 static const cmdinfo_t wait_break_cmd = {
1727 .name = "wait_break",
1730 .cfunc = wait_break_f,
1732 .oneline = "waits for the suspension of a request",
1735 static int abort_f(int argc, char **argv)
1740 static const cmdinfo_t abort_cmd = {
1743 .flags = CMD_NOFILE_OK,
1744 .oneline = "simulate a program crash using abort(3)",
1747 static int close_f(int argc, char **argv)
1754 static const cmdinfo_t close_cmd = {
1758 .oneline = "close the current open file",
1761 static int openfile(char *name, int flags, int growable)
1764 fprintf(stderr, "file open already, try 'help close'\n");
1769 if (bdrv_file_open(&bs, name, NULL, flags)) {
1770 fprintf(stderr, "%s: can't open device %s\n", progname, name);
1774 bs = bdrv_new("hda");
1776 if (bdrv_open(bs, name, NULL, flags, NULL) < 0) {
1777 fprintf(stderr, "%s: can't open device %s\n", progname, name);
1787 static void open_help(void)
1791 " opens a new file in the requested mode\n"
1794 " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
1796 " Opens a file for subsequent use by all of the other qemu-io commands.\n"
1797 " -r, -- open file read-only\n"
1798 " -s, -- use snapshot file\n"
1799 " -n, -- disable host cache\n"
1800 " -g, -- allow file to grow (only applies to protocols)"
1804 static int open_f(int argc, char **argv);
1806 static const cmdinfo_t open_cmd = {
1812 .flags = CMD_NOFILE_OK,
1813 .args = "[-Crsn] [path]",
1814 .oneline = "open the file specified by path",
1818 static int open_f(int argc, char **argv)
1825 while ((c = getopt(argc, argv, "snrg")) != EOF) {
1828 flags |= BDRV_O_SNAPSHOT;
1831 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
1840 return command_usage(&open_cmd);
1845 flags |= BDRV_O_RDWR;
1848 if (optind != argc - 1) {
1849 return command_usage(&open_cmd);
1852 return openfile(argv[optind], flags, growable);
1855 static int init_args_command(int index)
1857 /* only one device allowed so far */
1864 static int init_check_command(const cmdinfo_t *ct)
1866 if (ct->flags & CMD_FLAG_GLOBAL) {
1869 if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1870 fprintf(stderr, "no file open, try 'help open'\n");
1876 static void usage(const char *name)
1879 "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
1880 "QEMU Disk exerciser\n"
1882 " -c, --cmd command to execute\n"
1883 " -r, --read-only export read-only\n"
1884 " -s, --snapshot use snapshot file\n"
1885 " -n, --nocache disable host cache\n"
1886 " -g, --growable allow file to grow (only applies to protocols)\n"
1887 " -m, --misalign misalign allocations for O_DIRECT\n"
1888 " -k, --native-aio use kernel AIO implementation (on Linux only)\n"
1889 " -t, --cache=MODE use the given cache mode for the image\n"
1890 " -T, --trace FILE enable trace events listed in the given file\n"
1891 " -h, --help display this help and exit\n"
1892 " -V, --version output version information and exit\n"
1898 int main(int argc, char **argv)
1902 const char *sopt = "hVc:d:rsnmgkt:T:";
1903 const struct option lopt[] = {
1904 { "help", 0, NULL, 'h' },
1905 { "version", 0, NULL, 'V' },
1906 { "offset", 1, NULL, 'o' },
1907 { "cmd", 1, NULL, 'c' },
1908 { "read-only", 0, NULL, 'r' },
1909 { "snapshot", 0, NULL, 's' },
1910 { "nocache", 0, NULL, 'n' },
1911 { "misalign", 0, NULL, 'm' },
1912 { "growable", 0, NULL, 'g' },
1913 { "native-aio", 0, NULL, 'k' },
1914 { "discard", 1, NULL, 'd' },
1915 { "cache", 1, NULL, 't' },
1916 { "trace", 1, NULL, 'T' },
1917 { NULL, 0, NULL, 0 }
1921 int flags = BDRV_O_UNMAP;
1923 progname = basename(argv[0]);
1925 while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
1928 flags |= BDRV_O_SNAPSHOT;
1931 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
1934 if (bdrv_parse_discard_flags(optarg, &flags) < 0) {
1935 error_report("Invalid discard option: %s", optarg);
1940 add_user_command(optarg);
1952 flags |= BDRV_O_NATIVE_AIO;
1955 if (bdrv_parse_cache_flags(optarg, &flags) < 0) {
1956 error_report("Invalid cache option: %s", optarg);
1961 if (!trace_backend_init(optarg, NULL)) {
1962 exit(1); /* error message will have been printed */
1966 printf("%s version %s\n", progname, VERSION);
1977 if ((argc - optind) > 1) {
1982 qemu_init_main_loop();
1985 /* initialize commands */
1988 add_command(&open_cmd);
1989 add_command(&close_cmd);
1990 add_command(&read_cmd);
1991 add_command(&readv_cmd);
1992 add_command(&write_cmd);
1993 add_command(&writev_cmd);
1994 add_command(&multiwrite_cmd);
1995 add_command(&aio_read_cmd);
1996 add_command(&aio_write_cmd);
1997 add_command(&aio_flush_cmd);
1998 add_command(&flush_cmd);
1999 add_command(&truncate_cmd);
2000 add_command(&length_cmd);
2001 add_command(&info_cmd);
2002 add_command(&discard_cmd);
2003 add_command(&alloc_cmd);
2004 add_command(&map_cmd);
2005 add_command(&break_cmd);
2006 add_command(&resume_cmd);
2007 add_command(&wait_break_cmd);
2008 add_command(&abort_cmd);
2010 add_args_command(init_args_command);
2011 add_check_command(init_check_command);
2013 /* open the device */
2015 flags |= BDRV_O_RDWR;
2018 if ((argc - optind) == 1) {
2019 openfile(argv[optind], flags, growable);
2024 * Make sure all outstanding requests complete before the program exits.