blob: 61880932b3ea008fd7bb4398a6eaa2a1465f3ae7 [file] [log] [blame]
aliguorie3aff4f2009-04-05 19:14:04 +00001/*
2 * Command line utility to exercise the QEMU I/O path.
3 *
4 * Copyright (C) 2009 Red Hat, Inc.
5 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
9 */
Stefan Weilc32d7662009-08-31 22:16:16 +020010#include <sys/time.h>
aliguorie3aff4f2009-04-05 19:14:04 +000011#include <sys/types.h>
12#include <stdarg.h>
13#include <stdio.h>
14#include <getopt.h>
Stefan Weilc32d7662009-08-31 22:16:16 +020015#include <libgen.h>
aliguorie3aff4f2009-04-05 19:14:04 +000016
17#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010018#include "qemu/main-loop.h"
Paolo Bonzini737e1502012-12-17 18:19:44 +010019#include "block/block_int.h"
aliguorie3aff4f2009-04-05 19:14:04 +000020#include "cmd.h"
Stefan Hajnoczid7bb72c2012-03-12 16:36:07 +000021#include "trace/control.h"
aliguorie3aff4f2009-04-05 19:14:04 +000022
23#define VERSION "0.0.1"
24
Devin Nakamura43642b32011-07-11 11:22:16 -040025#define CMD_NOFILE_OK 0x01
aliguorie3aff4f2009-04-05 19:14:04 +000026
27char *progname;
28static BlockDriverState *bs;
29
30static int misalign;
31
32/*
Christoph Hellwigcf070d72009-07-20 01:19:25 +020033 * Parse the pattern argument to various sub-commands.
34 *
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.
37 */
38static int parse_pattern(const char *arg)
39{
Devin Nakamura43642b32011-07-11 11:22:16 -040040 char *endptr = NULL;
41 long pattern;
Christoph Hellwigcf070d72009-07-20 01:19:25 +020042
Devin Nakamura43642b32011-07-11 11:22:16 -040043 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);
46 return -1;
47 }
Christoph Hellwigcf070d72009-07-20 01:19:25 +020048
Devin Nakamura43642b32011-07-11 11:22:16 -040049 return pattern;
Christoph Hellwigcf070d72009-07-20 01:19:25 +020050}
51
52/*
aliguorie3aff4f2009-04-05 19:14:04 +000053 * Memory allocation helpers.
54 *
55 * Make sure memory is aligned by default, or purposefully misaligned if
56 * that is specified on the command line.
57 */
58
Devin Nakamura43642b32011-07-11 11:22:16 -040059#define MISALIGN_OFFSET 16
aliguorie3aff4f2009-04-05 19:14:04 +000060static void *qemu_io_alloc(size_t len, int pattern)
61{
Devin Nakamura43642b32011-07-11 11:22:16 -040062 void *buf;
aliguorie3aff4f2009-04-05 19:14:04 +000063
Devin Nakamura43642b32011-07-11 11:22:16 -040064 if (misalign) {
65 len += MISALIGN_OFFSET;
66 }
67 buf = qemu_blockalign(bs, len);
68 memset(buf, pattern, len);
69 if (misalign) {
70 buf += MISALIGN_OFFSET;
71 }
72 return buf;
aliguorie3aff4f2009-04-05 19:14:04 +000073}
74
75static void qemu_io_free(void *p)
76{
Devin Nakamura43642b32011-07-11 11:22:16 -040077 if (misalign) {
78 p -= MISALIGN_OFFSET;
79 }
80 qemu_vfree(p);
aliguorie3aff4f2009-04-05 19:14:04 +000081}
82
Devin Nakamura43642b32011-07-11 11:22:16 -040083static void dump_buffer(const void *buffer, int64_t offset, int len)
aliguorie3aff4f2009-04-05 19:14:04 +000084{
Devin Nakamura43642b32011-07-11 11:22:16 -040085 int i, j;
86 const uint8_t *p;
aliguorie3aff4f2009-04-05 19:14:04 +000087
Devin Nakamura43642b32011-07-11 11:22:16 -040088 for (i = 0, p = buffer; i < len; i += 16) {
89 const uint8_t *s = p;
aliguorie3aff4f2009-04-05 19:14:04 +000090
Devin Nakamura43642b32011-07-11 11:22:16 -040091 printf("%08" PRIx64 ": ", offset + i);
92 for (j = 0; j < 16 && i + j < len; j++, p++) {
93 printf("%02x ", *p);
94 }
95 printf(" ");
96 for (j = 0; j < 16 && i + j < len; j++, s++) {
97 if (isalnum(*s)) {
98 printf("%c", *s);
99 } else {
100 printf(".");
101 }
102 }
103 printf("\n");
104 }
aliguorie3aff4f2009-04-05 19:14:04 +0000105}
106
Devin Nakamura43642b32011-07-11 11:22:16 -0400107static void print_report(const char *op, struct timeval *t, int64_t offset,
108 int count, int total, int cnt, int Cflag)
aliguorie3aff4f2009-04-05 19:14:04 +0000109{
Devin Nakamura43642b32011-07-11 11:22:16 -0400110 char s1[64], s2[64], ts[64];
aliguorie3aff4f2009-04-05 19:14:04 +0000111
Devin Nakamura43642b32011-07-11 11:22:16 -0400112 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
113 if (!Cflag) {
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",
122 total, cnt, ts,
123 tdiv((double)total, *t),
124 tdiv((double)cnt, *t));
125 }
aliguorie3aff4f2009-04-05 19:14:04 +0000126}
127
Christoph Hellwigcf572982009-07-10 13:33:42 +0200128/*
129 * Parse multiple length statements for vectored I/O, and construct an I/O
130 * vector matching it.
131 */
132static void *
133create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
134{
Stefan Hajnoczi031380d2012-01-16 09:28:06 +0000135 size_t *sizes = g_new0(size_t, nr_iov);
Devin Nakamura43642b32011-07-11 11:22:16 -0400136 size_t count = 0;
137 void *buf = NULL;
138 void *p;
139 int i;
Christoph Hellwigcf572982009-07-10 13:33:42 +0200140
Devin Nakamura43642b32011-07-11 11:22:16 -0400141 for (i = 0; i < nr_iov; i++) {
142 char *arg = argv[i];
143 int64_t len;
Christoph Hellwigcf572982009-07-10 13:33:42 +0200144
Devin Nakamura43642b32011-07-11 11:22:16 -0400145 len = cvtnum(arg);
146 if (len < 0) {
147 printf("non-numeric length argument -- %s\n", arg);
148 goto fail;
149 }
Christoph Hellwigcf572982009-07-10 13:33:42 +0200150
Devin Nakamura43642b32011-07-11 11:22:16 -0400151 /* should be SIZE_T_MAX, but that doesn't exist */
152 if (len > INT_MAX) {
153 printf("too large length argument -- %s\n", arg);
154 goto fail;
155 }
Christoph Hellwigcf572982009-07-10 13:33:42 +0200156
Devin Nakamura43642b32011-07-11 11:22:16 -0400157 if (len & 0x1ff) {
158 printf("length argument %" PRId64
159 " is not sector aligned\n", len);
160 goto fail;
161 }
Christoph Hellwigcf572982009-07-10 13:33:42 +0200162
Devin Nakamura43642b32011-07-11 11:22:16 -0400163 sizes[i] = len;
164 count += len;
165 }
Christoph Hellwigcf572982009-07-10 13:33:42 +0200166
Devin Nakamura43642b32011-07-11 11:22:16 -0400167 qemu_iovec_init(qiov, nr_iov);
Christoph Hellwigcf572982009-07-10 13:33:42 +0200168
Devin Nakamura43642b32011-07-11 11:22:16 -0400169 buf = p = qemu_io_alloc(count, pattern);
Christoph Hellwigcf572982009-07-10 13:33:42 +0200170
Devin Nakamura43642b32011-07-11 11:22:16 -0400171 for (i = 0; i < nr_iov; i++) {
172 qemu_iovec_add(qiov, p, sizes[i]);
173 p += sizes[i];
174 }
Christoph Hellwigcf572982009-07-10 13:33:42 +0200175
Kevin Wolf40a0d7c2009-11-18 10:42:59 +0100176fail:
Stefan Hajnoczi031380d2012-01-16 09:28:06 +0000177 g_free(sizes);
Devin Nakamura43642b32011-07-11 11:22:16 -0400178 return buf;
Christoph Hellwigcf572982009-07-10 13:33:42 +0200179}
180
aliguorie3aff4f2009-04-05 19:14:04 +0000181static int do_read(char *buf, int64_t offset, int count, int *total)
182{
Devin Nakamura43642b32011-07-11 11:22:16 -0400183 int ret;
aliguorie3aff4f2009-04-05 19:14:04 +0000184
Devin Nakamura43642b32011-07-11 11:22:16 -0400185 ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
186 if (ret < 0) {
187 return ret;
188 }
189 *total = count;
190 return 1;
aliguorie3aff4f2009-04-05 19:14:04 +0000191}
192
193static int do_write(char *buf, int64_t offset, int count, int *total)
194{
Devin Nakamura43642b32011-07-11 11:22:16 -0400195 int ret;
aliguorie3aff4f2009-04-05 19:14:04 +0000196
Devin Nakamura43642b32011-07-11 11:22:16 -0400197 ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
198 if (ret < 0) {
199 return ret;
200 }
201 *total = count;
202 return 1;
aliguorie3aff4f2009-04-05 19:14:04 +0000203}
204
205static int do_pread(char *buf, int64_t offset, int count, int *total)
206{
Devin Nakamura43642b32011-07-11 11:22:16 -0400207 *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
208 if (*total < 0) {
209 return *total;
210 }
211 return 1;
aliguorie3aff4f2009-04-05 19:14:04 +0000212}
213
214static int do_pwrite(char *buf, int64_t offset, int count, int *total)
215{
Devin Nakamura43642b32011-07-11 11:22:16 -0400216 *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
217 if (*total < 0) {
218 return *total;
219 }
220 return 1;
aliguorie3aff4f2009-04-05 19:14:04 +0000221}
222
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000223typedef struct {
224 int64_t offset;
225 int count;
226 int *total;
227 int ret;
228 bool done;
229} CoWriteZeroes;
230
231static void coroutine_fn co_write_zeroes_entry(void *opaque)
232{
233 CoWriteZeroes *data = opaque;
234
235 data->ret = bdrv_co_write_zeroes(bs, data->offset / BDRV_SECTOR_SIZE,
236 data->count / BDRV_SECTOR_SIZE);
237 data->done = true;
238 if (data->ret < 0) {
239 *data->total = data->ret;
240 return;
241 }
242
243 *data->total = data->count;
244}
245
246static int do_co_write_zeroes(int64_t offset, int count, int *total)
247{
248 Coroutine *co;
249 CoWriteZeroes data = {
250 .offset = offset,
251 .count = count,
252 .total = total,
253 .done = false,
254 };
255
256 co = qemu_coroutine_create(co_write_zeroes_entry);
257 qemu_coroutine_enter(co, &data);
258 while (!data.done) {
259 qemu_aio_wait();
260 }
261 if (data.ret < 0) {
262 return data.ret;
263 } else {
264 return 1;
265 }
266}
267
Kevin Wolf791bfa32012-12-04 16:35:12 +0100268static int do_write_compressed(char *buf, int64_t offset, int count, int *total)
269{
270 int ret;
271
272 ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
273 if (ret < 0) {
274 return ret;
275 }
276 *total = count;
277 return 1;
278}
279
Kevin Wolfca94dbc2009-07-15 12:06:58 +0200280static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
281{
Devin Nakamura43642b32011-07-11 11:22:16 -0400282 *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
283 if (*total < 0) {
284 return *total;
285 }
286 return 1;
Kevin Wolfca94dbc2009-07-15 12:06:58 +0200287}
288
289static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
290{
Devin Nakamura43642b32011-07-11 11:22:16 -0400291 *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
292 if (*total < 0) {
293 return *total;
294 }
295 return 1;
Kevin Wolfca94dbc2009-07-15 12:06:58 +0200296}
297
aliguorie3aff4f2009-04-05 19:14:04 +0000298#define NOT_DONE 0x7fffffff
299static void aio_rw_done(void *opaque, int ret)
300{
Devin Nakamura43642b32011-07-11 11:22:16 -0400301 *(int *)opaque = ret;
aliguorie3aff4f2009-04-05 19:14:04 +0000302}
303
304static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
305{
Devin Nakamura43642b32011-07-11 11:22:16 -0400306 int async_ret = NOT_DONE;
aliguorie3aff4f2009-04-05 19:14:04 +0000307
Paolo Bonziniad54ae82011-11-30 09:12:30 +0100308 bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
309 aio_rw_done, &async_ret);
Devin Nakamura43642b32011-07-11 11:22:16 -0400310 while (async_ret == NOT_DONE) {
Paolo Bonzinia5a52382012-04-12 14:00:51 +0200311 main_loop_wait(false);
Devin Nakamura43642b32011-07-11 11:22:16 -0400312 }
aliguorie3aff4f2009-04-05 19:14:04 +0000313
Devin Nakamura43642b32011-07-11 11:22:16 -0400314 *total = qiov->size;
315 return async_ret < 0 ? async_ret : 1;
aliguorie3aff4f2009-04-05 19:14:04 +0000316}
317
318static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
319{
Devin Nakamura43642b32011-07-11 11:22:16 -0400320 int async_ret = NOT_DONE;
aliguorie3aff4f2009-04-05 19:14:04 +0000321
Paolo Bonziniad54ae82011-11-30 09:12:30 +0100322 bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
323 aio_rw_done, &async_ret);
Devin Nakamura43642b32011-07-11 11:22:16 -0400324 while (async_ret == NOT_DONE) {
Paolo Bonzinia5a52382012-04-12 14:00:51 +0200325 main_loop_wait(false);
Devin Nakamura43642b32011-07-11 11:22:16 -0400326 }
aliguorie3aff4f2009-04-05 19:14:04 +0000327
Devin Nakamura43642b32011-07-11 11:22:16 -0400328 *total = qiov->size;
329 return async_ret < 0 ? async_ret : 1;
aliguorie3aff4f2009-04-05 19:14:04 +0000330}
331
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200332struct multiwrite_async_ret {
Devin Nakamura43642b32011-07-11 11:22:16 -0400333 int num_done;
334 int error;
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200335};
336
337static void multiwrite_cb(void *opaque, int ret)
338{
Devin Nakamura43642b32011-07-11 11:22:16 -0400339 struct multiwrite_async_ret *async_ret = opaque;
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200340
Devin Nakamura43642b32011-07-11 11:22:16 -0400341 async_ret->num_done++;
342 if (ret < 0) {
343 async_ret->error = ret;
344 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200345}
346
347static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
348{
Devin Nakamura43642b32011-07-11 11:22:16 -0400349 int i, ret;
350 struct multiwrite_async_ret async_ret = {
351 .num_done = 0,
352 .error = 0,
353 };
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200354
Devin Nakamura43642b32011-07-11 11:22:16 -0400355 *total = 0;
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;
360 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200361
Devin Nakamura43642b32011-07-11 11:22:16 -0400362 ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
363 if (ret < 0) {
364 return ret;
365 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200366
Devin Nakamura43642b32011-07-11 11:22:16 -0400367 while (async_ret.num_done < num_reqs) {
Paolo Bonzinia5a52382012-04-12 14:00:51 +0200368 main_loop_wait(false);
Devin Nakamura43642b32011-07-11 11:22:16 -0400369 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200370
Devin Nakamura43642b32011-07-11 11:22:16 -0400371 return async_ret.error < 0 ? async_ret.error : 1;
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200372}
aliguorie3aff4f2009-04-05 19:14:04 +0000373
Devin Nakamura43642b32011-07-11 11:22:16 -0400374static void read_help(void)
aliguorie3aff4f2009-04-05 19:14:04 +0000375{
Devin Nakamura43642b32011-07-11 11:22:16 -0400376 printf(
aliguorie3aff4f2009-04-05 19:14:04 +0000377"\n"
378" reads a range of bytes from the given offset\n"
379"\n"
380" Example:\n"
381" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
382"\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"
Kevin Wolfca94dbc2009-07-15 12:06:58 +0200385" -b, -- read from the VM state rather than the virtual disk\n"
Kevin Wolfd9654a52009-04-23 15:11:13 +0200386" -C, -- report statistics in a machine parsable format\n"
387" -l, -- length for pattern verification (only with -P)\n"
aliguorie3aff4f2009-04-05 19:14:04 +0000388" -p, -- use bdrv_pread to read the file\n"
aliguoric48101a2009-04-18 15:36:23 +0000389" -P, -- use a pattern to verify read data\n"
Kevin Wolf095343a2010-12-17 11:55:37 +0100390" -q, -- quiet mode, do not show I/O statistics\n"
Kevin Wolfd9654a52009-04-23 15:11:13 +0200391" -s, -- start offset for pattern verification (only with -P)\n"
392" -v, -- dump buffer to standard output\n"
aliguorie3aff4f2009-04-05 19:14:04 +0000393"\n");
394}
395
Blue Swirl22a2bdc2009-11-21 09:06:46 +0000396static int read_f(int argc, char **argv);
397
398static const cmdinfo_t read_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -0400399 .name = "read",
400 .altname = "r",
401 .cfunc = read_f,
402 .argmin = 2,
403 .argmax = -1,
404 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
405 .oneline = "reads a number of bytes at a specified offset",
406 .help = read_help,
Blue Swirl22a2bdc2009-11-21 09:06:46 +0000407};
408
Devin Nakamura43642b32011-07-11 11:22:16 -0400409static int read_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +0000410{
Devin Nakamura43642b32011-07-11 11:22:16 -0400411 struct timeval t1, t2;
412 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
413 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
414 int c, cnt;
415 char *buf;
416 int64_t offset;
417 int count;
418 /* Some compilers get confused and warn if this is not initialized. */
419 int total = 0;
420 int pattern = 0, pattern_offset = 0, pattern_count = 0;
aliguorie3aff4f2009-04-05 19:14:04 +0000421
Devin Nakamura43642b32011-07-11 11:22:16 -0400422 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
423 switch (c) {
424 case 'b':
425 bflag = 1;
426 break;
427 case 'C':
428 Cflag = 1;
429 break;
430 case 'l':
431 lflag = 1;
432 pattern_count = cvtnum(optarg);
433 if (pattern_count < 0) {
434 printf("non-numeric length argument -- %s\n", optarg);
435 return 0;
436 }
437 break;
438 case 'p':
439 pflag = 1;
440 break;
441 case 'P':
442 Pflag = 1;
443 pattern = parse_pattern(optarg);
444 if (pattern < 0) {
445 return 0;
446 }
447 break;
448 case 'q':
449 qflag = 1;
450 break;
451 case 's':
452 sflag = 1;
453 pattern_offset = cvtnum(optarg);
454 if (pattern_offset < 0) {
455 printf("non-numeric length argument -- %s\n", optarg);
456 return 0;
457 }
458 break;
459 case 'v':
460 vflag = 1;
461 break;
462 default:
463 return command_usage(&read_cmd);
464 }
465 }
aliguorie3aff4f2009-04-05 19:14:04 +0000466
Devin Nakamura43642b32011-07-11 11:22:16 -0400467 if (optind != argc - 2) {
468 return command_usage(&read_cmd);
469 }
aliguorie3aff4f2009-04-05 19:14:04 +0000470
Devin Nakamura43642b32011-07-11 11:22:16 -0400471 if (bflag && pflag) {
472 printf("-b and -p cannot be specified at the same time\n");
473 return 0;
474 }
Kevin Wolfca94dbc2009-07-15 12:06:58 +0200475
Devin Nakamura43642b32011-07-11 11:22:16 -0400476 offset = cvtnum(argv[optind]);
477 if (offset < 0) {
478 printf("non-numeric length argument -- %s\n", argv[optind]);
479 return 0;
480 }
aliguorie3aff4f2009-04-05 19:14:04 +0000481
Devin Nakamura43642b32011-07-11 11:22:16 -0400482 optind++;
483 count = cvtnum(argv[optind]);
484 if (count < 0) {
485 printf("non-numeric length argument -- %s\n", argv[optind]);
486 return 0;
487 }
aliguorie3aff4f2009-04-05 19:14:04 +0000488
Kevin Wolfd9654a52009-04-23 15:11:13 +0200489 if (!Pflag && (lflag || sflag)) {
490 return command_usage(&read_cmd);
491 }
492
493 if (!lflag) {
494 pattern_count = count - pattern_offset;
495 }
496
497 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
Dong Xu Wang07f35072011-11-22 18:06:26 +0800498 printf("pattern verification range exceeds end of read data\n");
Kevin Wolfd9654a52009-04-23 15:11:13 +0200499 return 0;
500 }
501
Devin Nakamura5afc8b32011-07-11 11:20:25 -0400502 if (!pflag) {
Devin Nakamura43642b32011-07-11 11:22:16 -0400503 if (offset & 0x1ff) {
504 printf("offset %" PRId64 " is not sector aligned\n",
505 offset);
506 return 0;
507 }
508 if (count & 0x1ff) {
509 printf("count %d is not sector aligned\n",
510 count);
511 return 0;
512 }
Devin Nakamura5afc8b32011-07-11 11:20:25 -0400513 }
aliguorie3aff4f2009-04-05 19:14:04 +0000514
Devin Nakamura43642b32011-07-11 11:22:16 -0400515 buf = qemu_io_alloc(count, 0xab);
aliguorie3aff4f2009-04-05 19:14:04 +0000516
Devin Nakamura43642b32011-07-11 11:22:16 -0400517 gettimeofday(&t1, NULL);
518 if (pflag) {
519 cnt = do_pread(buf, offset, count, &total);
520 } else if (bflag) {
521 cnt = do_load_vmstate(buf, offset, count, &total);
522 } else {
523 cnt = do_read(buf, offset, count, &total);
524 }
525 gettimeofday(&t2, NULL);
aliguorie3aff4f2009-04-05 19:14:04 +0000526
Devin Nakamura43642b32011-07-11 11:22:16 -0400527 if (cnt < 0) {
528 printf("read failed: %s\n", strerror(-cnt));
529 goto out;
530 }
aliguorie3aff4f2009-04-05 19:14:04 +0000531
Devin Nakamura43642b32011-07-11 11:22:16 -0400532 if (Pflag) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +0000533 void *cmp_buf = g_malloc(pattern_count);
Devin Nakamura43642b32011-07-11 11:22:16 -0400534 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);
539 }
Stefan Hajnoczi031380d2012-01-16 09:28:06 +0000540 g_free(cmp_buf);
Devin Nakamura43642b32011-07-11 11:22:16 -0400541 }
aliguorie3aff4f2009-04-05 19:14:04 +0000542
Devin Nakamura43642b32011-07-11 11:22:16 -0400543 if (qflag) {
544 goto out;
545 }
aliguoric48101a2009-04-18 15:36:23 +0000546
Devin Nakamura43642b32011-07-11 11:22:16 -0400547 if (vflag) {
548 dump_buffer(buf, offset, count);
549 }
aliguorie3aff4f2009-04-05 19:14:04 +0000550
Devin Nakamura43642b32011-07-11 11:22:16 -0400551 /* Finally, report back -- -C gives a parsable format */
552 t2 = tsub(t2, t1);
553 print_report("read", &t2, offset, count, total, cnt, Cflag);
aliguorie3aff4f2009-04-05 19:14:04 +0000554
Kevin Wolf7d8abfc2009-07-10 13:33:52 +0200555out:
Devin Nakamura43642b32011-07-11 11:22:16 -0400556 qemu_io_free(buf);
aliguorie3aff4f2009-04-05 19:14:04 +0000557
Devin Nakamura43642b32011-07-11 11:22:16 -0400558 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +0000559}
560
Devin Nakamura43642b32011-07-11 11:22:16 -0400561static void readv_help(void)
aliguorie3aff4f2009-04-05 19:14:04 +0000562{
Devin Nakamura43642b32011-07-11 11:22:16 -0400563 printf(
aliguorie3aff4f2009-04-05 19:14:04 +0000564"\n"
565" reads a range of bytes from the given offset into multiple buffers\n"
566"\n"
567" Example:\n"
568" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
569"\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"
aliguoric48101a2009-04-18 15:36:23 +0000574" -P, -- use a pattern to verify read data\n"
aliguorie3aff4f2009-04-05 19:14:04 +0000575" -v, -- dump buffer to standard output\n"
Kevin Wolf095343a2010-12-17 11:55:37 +0100576" -q, -- quiet mode, do not show I/O statistics\n"
aliguorie3aff4f2009-04-05 19:14:04 +0000577"\n");
578}
579
Blue Swirl22a2bdc2009-11-21 09:06:46 +0000580static int readv_f(int argc, char **argv);
581
582static const cmdinfo_t readv_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -0400583 .name = "readv",
584 .cfunc = readv_f,
585 .argmin = 2,
586 .argmax = -1,
587 .args = "[-Cqv] [-P pattern ] off len [len..]",
588 .oneline = "reads a number of bytes at a specified offset",
589 .help = readv_help,
Blue Swirl22a2bdc2009-11-21 09:06:46 +0000590};
591
Devin Nakamura43642b32011-07-11 11:22:16 -0400592static int readv_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +0000593{
Devin Nakamura43642b32011-07-11 11:22:16 -0400594 struct timeval t1, t2;
595 int Cflag = 0, qflag = 0, vflag = 0;
596 int c, cnt;
597 char *buf;
598 int64_t offset;
599 /* Some compilers get confused and warn if this is not initialized. */
600 int total = 0;
601 int nr_iov;
602 QEMUIOVector qiov;
603 int pattern = 0;
604 int Pflag = 0;
aliguorie3aff4f2009-04-05 19:14:04 +0000605
Devin Nakamura43642b32011-07-11 11:22:16 -0400606 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
607 switch (c) {
608 case 'C':
609 Cflag = 1;
610 break;
611 case 'P':
612 Pflag = 1;
613 pattern = parse_pattern(optarg);
614 if (pattern < 0) {
615 return 0;
616 }
617 break;
618 case 'q':
619 qflag = 1;
620 break;
621 case 'v':
622 vflag = 1;
623 break;
624 default:
625 return command_usage(&readv_cmd);
626 }
627 }
aliguorie3aff4f2009-04-05 19:14:04 +0000628
Devin Nakamura43642b32011-07-11 11:22:16 -0400629 if (optind > argc - 2) {
630 return command_usage(&readv_cmd);
631 }
aliguorie3aff4f2009-04-05 19:14:04 +0000632
633
Devin Nakamura43642b32011-07-11 11:22:16 -0400634 offset = cvtnum(argv[optind]);
635 if (offset < 0) {
636 printf("non-numeric length argument -- %s\n", argv[optind]);
637 return 0;
638 }
639 optind++;
aliguorie3aff4f2009-04-05 19:14:04 +0000640
Devin Nakamura43642b32011-07-11 11:22:16 -0400641 if (offset & 0x1ff) {
642 printf("offset %" PRId64 " is not sector aligned\n",
643 offset);
644 return 0;
645 }
aliguorie3aff4f2009-04-05 19:14:04 +0000646
Devin Nakamura43642b32011-07-11 11:22:16 -0400647 nr_iov = argc - optind;
648 buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
Kevin Wolff2360622011-10-31 11:36:32 +0100649 if (buf == NULL) {
650 return 0;
651 }
aliguorie3aff4f2009-04-05 19:14:04 +0000652
Devin Nakamura43642b32011-07-11 11:22:16 -0400653 gettimeofday(&t1, NULL);
654 cnt = do_aio_readv(&qiov, offset, &total);
655 gettimeofday(&t2, NULL);
aliguorie3aff4f2009-04-05 19:14:04 +0000656
Devin Nakamura43642b32011-07-11 11:22:16 -0400657 if (cnt < 0) {
658 printf("readv failed: %s\n", strerror(-cnt));
659 goto out;
660 }
aliguorie3aff4f2009-04-05 19:14:04 +0000661
Devin Nakamura43642b32011-07-11 11:22:16 -0400662 if (Pflag) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +0000663 void *cmp_buf = g_malloc(qiov.size);
Devin Nakamura43642b32011-07-11 11:22:16 -0400664 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);
668 }
Stefan Hajnoczi031380d2012-01-16 09:28:06 +0000669 g_free(cmp_buf);
Devin Nakamura43642b32011-07-11 11:22:16 -0400670 }
aliguoric48101a2009-04-18 15:36:23 +0000671
Devin Nakamura43642b32011-07-11 11:22:16 -0400672 if (qflag) {
673 goto out;
674 }
aliguorie3aff4f2009-04-05 19:14:04 +0000675
Devin Nakamura43642b32011-07-11 11:22:16 -0400676 if (vflag) {
677 dump_buffer(buf, offset, qiov.size);
678 }
aliguorie3aff4f2009-04-05 19:14:04 +0000679
Devin Nakamura43642b32011-07-11 11:22:16 -0400680 /* Finally, report back -- -C gives a parsable format */
681 t2 = tsub(t2, t1);
682 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
aliguorie3aff4f2009-04-05 19:14:04 +0000683
Kevin Wolf7d8abfc2009-07-10 13:33:52 +0200684out:
Kevin Wolf9e559532012-07-02 15:13:53 +0200685 qemu_iovec_destroy(&qiov);
Devin Nakamura43642b32011-07-11 11:22:16 -0400686 qemu_io_free(buf);
687 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +0000688}
689
Devin Nakamura43642b32011-07-11 11:22:16 -0400690static void write_help(void)
aliguorie3aff4f2009-04-05 19:14:04 +0000691{
Devin Nakamura43642b32011-07-11 11:22:16 -0400692 printf(
aliguorie3aff4f2009-04-05 19:14:04 +0000693"\n"
694" writes a range of bytes from the given offset\n"
695"\n"
696" Example:\n"
697" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
698"\n"
699" Writes into a segment of the currently open file, using a buffer\n"
700" filled with a set pattern (0xcdcdcdcd).\n"
Kevin Wolfca94dbc2009-07-15 12:06:58 +0200701" -b, -- write to the VM state rather than the virtual disk\n"
Kevin Wolf791bfa32012-12-04 16:35:12 +0100702" -c, -- write compressed data with bdrv_write_compressed\n"
aliguorie3aff4f2009-04-05 19:14:04 +0000703" -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"
Kevin Wolf095343a2010-12-17 11:55:37 +0100706" -q, -- quiet mode, do not show I/O statistics\n"
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000707" -z, -- write zeroes using bdrv_co_write_zeroes\n"
aliguorie3aff4f2009-04-05 19:14:04 +0000708"\n");
709}
710
Blue Swirl22a2bdc2009-11-21 09:06:46 +0000711static int write_f(int argc, char **argv);
712
713static const cmdinfo_t write_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -0400714 .name = "write",
715 .altname = "w",
716 .cfunc = write_f,
717 .argmin = 2,
718 .argmax = -1,
Kevin Wolf791bfa32012-12-04 16:35:12 +0100719 .args = "[-bcCpqz] [-P pattern ] off len",
Devin Nakamura43642b32011-07-11 11:22:16 -0400720 .oneline = "writes a number of bytes at a specified offset",
721 .help = write_help,
Blue Swirl22a2bdc2009-11-21 09:06:46 +0000722};
723
Devin Nakamura43642b32011-07-11 11:22:16 -0400724static int write_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +0000725{
Devin Nakamura43642b32011-07-11 11:22:16 -0400726 struct timeval t1, t2;
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000727 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
Kevin Wolf791bfa32012-12-04 16:35:12 +0100728 int cflag = 0;
Devin Nakamura43642b32011-07-11 11:22:16 -0400729 int c, cnt;
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000730 char *buf = NULL;
Devin Nakamura43642b32011-07-11 11:22:16 -0400731 int64_t offset;
732 int count;
733 /* Some compilers get confused and warn if this is not initialized. */
734 int total = 0;
735 int pattern = 0xcd;
aliguorie3aff4f2009-04-05 19:14:04 +0000736
Kevin Wolf791bfa32012-12-04 16:35:12 +0100737 while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
Devin Nakamura43642b32011-07-11 11:22:16 -0400738 switch (c) {
739 case 'b':
740 bflag = 1;
741 break;
Kevin Wolf791bfa32012-12-04 16:35:12 +0100742 case 'c':
743 cflag = 1;
744 break;
Devin Nakamura43642b32011-07-11 11:22:16 -0400745 case 'C':
746 Cflag = 1;
747 break;
748 case 'p':
749 pflag = 1;
750 break;
751 case 'P':
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000752 Pflag = 1;
Devin Nakamura43642b32011-07-11 11:22:16 -0400753 pattern = parse_pattern(optarg);
754 if (pattern < 0) {
755 return 0;
756 }
757 break;
758 case 'q':
759 qflag = 1;
760 break;
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000761 case 'z':
762 zflag = 1;
763 break;
Devin Nakamura43642b32011-07-11 11:22:16 -0400764 default:
765 return command_usage(&write_cmd);
766 }
767 }
aliguorie3aff4f2009-04-05 19:14:04 +0000768
Devin Nakamura43642b32011-07-11 11:22:16 -0400769 if (optind != argc - 2) {
770 return command_usage(&write_cmd);
771 }
aliguorie3aff4f2009-04-05 19:14:04 +0000772
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000773 if (bflag + pflag + zflag > 1) {
774 printf("-b, -p, or -z cannot be specified at the same time\n");
775 return 0;
776 }
777
778 if (zflag && Pflag) {
779 printf("-z and -P cannot be specified at the same time\n");
Devin Nakamura43642b32011-07-11 11:22:16 -0400780 return 0;
781 }
Kevin Wolfca94dbc2009-07-15 12:06:58 +0200782
Devin Nakamura43642b32011-07-11 11:22:16 -0400783 offset = cvtnum(argv[optind]);
784 if (offset < 0) {
785 printf("non-numeric length argument -- %s\n", argv[optind]);
786 return 0;
787 }
aliguorie3aff4f2009-04-05 19:14:04 +0000788
Devin Nakamura43642b32011-07-11 11:22:16 -0400789 optind++;
790 count = cvtnum(argv[optind]);
791 if (count < 0) {
792 printf("non-numeric length argument -- %s\n", argv[optind]);
793 return 0;
794 }
aliguorie3aff4f2009-04-05 19:14:04 +0000795
Devin Nakamura43642b32011-07-11 11:22:16 -0400796 if (!pflag) {
797 if (offset & 0x1ff) {
798 printf("offset %" PRId64 " is not sector aligned\n",
799 offset);
800 return 0;
801 }
aliguorie3aff4f2009-04-05 19:14:04 +0000802
Devin Nakamura43642b32011-07-11 11:22:16 -0400803 if (count & 0x1ff) {
804 printf("count %d is not sector aligned\n",
805 count);
806 return 0;
807 }
808 }
aliguorie3aff4f2009-04-05 19:14:04 +0000809
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000810 if (!zflag) {
811 buf = qemu_io_alloc(count, pattern);
812 }
aliguorie3aff4f2009-04-05 19:14:04 +0000813
Devin Nakamura43642b32011-07-11 11:22:16 -0400814 gettimeofday(&t1, NULL);
815 if (pflag) {
816 cnt = do_pwrite(buf, offset, count, &total);
817 } else if (bflag) {
818 cnt = do_save_vmstate(buf, offset, count, &total);
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000819 } else if (zflag) {
820 cnt = do_co_write_zeroes(offset, count, &total);
Kevin Wolf791bfa32012-12-04 16:35:12 +0100821 } else if (cflag) {
822 cnt = do_write_compressed(buf, offset, count, &total);
Devin Nakamura43642b32011-07-11 11:22:16 -0400823 } else {
824 cnt = do_write(buf, offset, count, &total);
825 }
826 gettimeofday(&t2, NULL);
aliguorie3aff4f2009-04-05 19:14:04 +0000827
Devin Nakamura43642b32011-07-11 11:22:16 -0400828 if (cnt < 0) {
829 printf("write failed: %s\n", strerror(-cnt));
830 goto out;
831 }
aliguorie3aff4f2009-04-05 19:14:04 +0000832
Devin Nakamura43642b32011-07-11 11:22:16 -0400833 if (qflag) {
834 goto out;
835 }
aliguorie3aff4f2009-04-05 19:14:04 +0000836
Devin Nakamura43642b32011-07-11 11:22:16 -0400837 /* Finally, report back -- -C gives a parsable format */
838 t2 = tsub(t2, t1);
839 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
aliguorie3aff4f2009-04-05 19:14:04 +0000840
Kevin Wolf7d8abfc2009-07-10 13:33:52 +0200841out:
Stefan Hajnoczi71b58b82012-02-07 13:27:29 +0000842 if (!zflag) {
843 qemu_io_free(buf);
844 }
aliguorie3aff4f2009-04-05 19:14:04 +0000845
Devin Nakamura43642b32011-07-11 11:22:16 -0400846 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +0000847}
848
aliguorie3aff4f2009-04-05 19:14:04 +0000849static void
850writev_help(void)
851{
Devin Nakamura43642b32011-07-11 11:22:16 -0400852 printf(
aliguorie3aff4f2009-04-05 19:14:04 +0000853"\n"
854" writes a range of bytes from the given offset source from multiple buffers\n"
855"\n"
856" Example:\n"
857" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
858"\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"
Kevin Wolf095343a2010-12-17 11:55:37 +0100863" -q, -- quiet mode, do not show I/O statistics\n"
aliguorie3aff4f2009-04-05 19:14:04 +0000864"\n");
865}
866
Blue Swirl22a2bdc2009-11-21 09:06:46 +0000867static int writev_f(int argc, char **argv);
868
869static const cmdinfo_t writev_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -0400870 .name = "writev",
871 .cfunc = writev_f,
872 .argmin = 2,
873 .argmax = -1,
874 .args = "[-Cq] [-P pattern ] off len [len..]",
875 .oneline = "writes a number of bytes at a specified offset",
876 .help = writev_help,
Blue Swirl22a2bdc2009-11-21 09:06:46 +0000877};
878
Devin Nakamura43642b32011-07-11 11:22:16 -0400879static int writev_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +0000880{
Devin Nakamura43642b32011-07-11 11:22:16 -0400881 struct timeval t1, t2;
882 int Cflag = 0, qflag = 0;
883 int c, cnt;
884 char *buf;
885 int64_t offset;
886 /* Some compilers get confused and warn if this is not initialized. */
887 int total = 0;
888 int nr_iov;
889 int pattern = 0xcd;
890 QEMUIOVector qiov;
aliguorie3aff4f2009-04-05 19:14:04 +0000891
Devin Nakamura43642b32011-07-11 11:22:16 -0400892 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
893 switch (c) {
894 case 'C':
895 Cflag = 1;
896 break;
897 case 'q':
898 qflag = 1;
899 break;
900 case 'P':
901 pattern = parse_pattern(optarg);
902 if (pattern < 0) {
903 return 0;
904 }
905 break;
906 default:
907 return command_usage(&writev_cmd);
908 }
909 }
aliguorie3aff4f2009-04-05 19:14:04 +0000910
Devin Nakamura43642b32011-07-11 11:22:16 -0400911 if (optind > argc - 2) {
912 return command_usage(&writev_cmd);
913 }
aliguorie3aff4f2009-04-05 19:14:04 +0000914
Devin Nakamura43642b32011-07-11 11:22:16 -0400915 offset = cvtnum(argv[optind]);
916 if (offset < 0) {
917 printf("non-numeric length argument -- %s\n", argv[optind]);
918 return 0;
919 }
920 optind++;
aliguorie3aff4f2009-04-05 19:14:04 +0000921
Devin Nakamura43642b32011-07-11 11:22:16 -0400922 if (offset & 0x1ff) {
923 printf("offset %" PRId64 " is not sector aligned\n",
924 offset);
925 return 0;
926 }
aliguorie3aff4f2009-04-05 19:14:04 +0000927
Devin Nakamura43642b32011-07-11 11:22:16 -0400928 nr_iov = argc - optind;
929 buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
Kevin Wolff2360622011-10-31 11:36:32 +0100930 if (buf == NULL) {
931 return 0;
932 }
aliguorie3aff4f2009-04-05 19:14:04 +0000933
Devin Nakamura43642b32011-07-11 11:22:16 -0400934 gettimeofday(&t1, NULL);
935 cnt = do_aio_writev(&qiov, offset, &total);
936 gettimeofday(&t2, NULL);
aliguorie3aff4f2009-04-05 19:14:04 +0000937
Devin Nakamura43642b32011-07-11 11:22:16 -0400938 if (cnt < 0) {
939 printf("writev failed: %s\n", strerror(-cnt));
940 goto out;
941 }
aliguorie3aff4f2009-04-05 19:14:04 +0000942
Devin Nakamura43642b32011-07-11 11:22:16 -0400943 if (qflag) {
944 goto out;
945 }
aliguorie3aff4f2009-04-05 19:14:04 +0000946
Devin Nakamura43642b32011-07-11 11:22:16 -0400947 /* Finally, report back -- -C gives a parsable format */
948 t2 = tsub(t2, t1);
949 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
Kevin Wolf7d8abfc2009-07-10 13:33:52 +0200950out:
Kevin Wolf9e559532012-07-02 15:13:53 +0200951 qemu_iovec_destroy(&qiov);
Devin Nakamura43642b32011-07-11 11:22:16 -0400952 qemu_io_free(buf);
953 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +0000954}
955
Devin Nakamura43642b32011-07-11 11:22:16 -0400956static void multiwrite_help(void)
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200957{
Devin Nakamura43642b32011-07-11 11:22:16 -0400958 printf(
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200959"\n"
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"
962"\n"
963" Example:\n"
Stefan Weilb2bedb22011-09-12 22:33:01 +0200964" 'multiwrite 512 1k 1k ; 4k 1k'\n"
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200965" writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
966"\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"
973"\n");
974}
975
976static int multiwrite_f(int argc, char **argv);
977
978static const cmdinfo_t multiwrite_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -0400979 .name = "multiwrite",
980 .cfunc = multiwrite_f,
981 .argmin = 2,
982 .argmax = -1,
983 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
984 .oneline = "issues multiple write requests at once",
985 .help = multiwrite_help,
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200986};
987
Devin Nakamura43642b32011-07-11 11:22:16 -0400988static int multiwrite_f(int argc, char **argv)
Kevin Wolf776cbbb2010-05-21 11:37:26 +0200989{
Devin Nakamura43642b32011-07-11 11:22:16 -0400990 struct timeval t1, t2;
991 int Cflag = 0, qflag = 0;
992 int c, cnt;
993 char **buf;
994 int64_t offset, first_offset = 0;
995 /* Some compilers get confused and warn if this is not initialized. */
996 int total = 0;
997 int nr_iov;
998 int nr_reqs;
999 int pattern = 0xcd;
1000 QEMUIOVector *qiovs;
1001 int i;
1002 BlockRequest *reqs;
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001003
Devin Nakamura43642b32011-07-11 11:22:16 -04001004 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1005 switch (c) {
1006 case 'C':
1007 Cflag = 1;
1008 break;
1009 case 'q':
1010 qflag = 1;
1011 break;
1012 case 'P':
1013 pattern = parse_pattern(optarg);
1014 if (pattern < 0) {
1015 return 0;
1016 }
1017 break;
1018 default:
1019 return command_usage(&writev_cmd);
1020 }
1021 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001022
Devin Nakamura43642b32011-07-11 11:22:16 -04001023 if (optind > argc - 2) {
1024 return command_usage(&writev_cmd);
1025 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001026
Devin Nakamura43642b32011-07-11 11:22:16 -04001027 nr_reqs = 1;
1028 for (i = optind; i < argc; i++) {
1029 if (!strcmp(argv[i], ";")) {
1030 nr_reqs++;
1031 }
1032 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001033
Kevin Wolff2360622011-10-31 11:36:32 +01001034 reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1035 buf = g_malloc0(nr_reqs * sizeof(*buf));
Anthony Liguori7267c092011-08-20 22:09:37 -05001036 qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001037
Kevin Wolf67403db2011-10-31 11:49:21 +01001038 for (i = 0; i < nr_reqs && optind < argc; i++) {
Devin Nakamura43642b32011-07-11 11:22:16 -04001039 int j;
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001040
Devin Nakamura43642b32011-07-11 11:22:16 -04001041 /* Read the offset of the request */
1042 offset = cvtnum(argv[optind]);
1043 if (offset < 0) {
1044 printf("non-numeric offset argument -- %s\n", argv[optind]);
Kevin Wolf67403db2011-10-31 11:49:21 +01001045 goto out;
Devin Nakamura43642b32011-07-11 11:22:16 -04001046 }
1047 optind++;
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001048
Devin Nakamura43642b32011-07-11 11:22:16 -04001049 if (offset & 0x1ff) {
1050 printf("offset %lld is not sector aligned\n",
1051 (long long)offset);
Kevin Wolf67403db2011-10-31 11:49:21 +01001052 goto out;
Devin Nakamura43642b32011-07-11 11:22:16 -04001053 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001054
1055 if (i == 0) {
1056 first_offset = offset;
1057 }
1058
Devin Nakamura43642b32011-07-11 11:22:16 -04001059 /* Read lengths for qiov entries */
1060 for (j = optind; j < argc; j++) {
1061 if (!strcmp(argv[j], ";")) {
1062 break;
1063 }
1064 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001065
Devin Nakamura43642b32011-07-11 11:22:16 -04001066 nr_iov = j - optind;
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001067
Devin Nakamura43642b32011-07-11 11:22:16 -04001068 /* Build request */
Kevin Wolff2360622011-10-31 11:36:32 +01001069 buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern);
1070 if (buf[i] == NULL) {
1071 goto out;
1072 }
1073
Devin Nakamura43642b32011-07-11 11:22:16 -04001074 reqs[i].qiov = &qiovs[i];
Devin Nakamura43642b32011-07-11 11:22:16 -04001075 reqs[i].sector = offset >> 9;
1076 reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001077
Devin Nakamura43642b32011-07-11 11:22:16 -04001078 optind = j + 1;
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001079
Devin Nakamura43642b32011-07-11 11:22:16 -04001080 pattern++;
1081 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001082
Kevin Wolf67403db2011-10-31 11:49:21 +01001083 /* If there were empty requests at the end, ignore them */
1084 nr_reqs = i;
1085
Devin Nakamura43642b32011-07-11 11:22:16 -04001086 gettimeofday(&t1, NULL);
1087 cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
1088 gettimeofday(&t2, NULL);
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001089
Devin Nakamura43642b32011-07-11 11:22:16 -04001090 if (cnt < 0) {
1091 printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1092 goto out;
1093 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001094
Devin Nakamura43642b32011-07-11 11:22:16 -04001095 if (qflag) {
1096 goto out;
1097 }
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001098
Devin Nakamura43642b32011-07-11 11:22:16 -04001099 /* Finally, report back -- -C gives a parsable format */
1100 t2 = tsub(t2, t1);
1101 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001102out:
Devin Nakamura43642b32011-07-11 11:22:16 -04001103 for (i = 0; i < nr_reqs; i++) {
1104 qemu_io_free(buf[i]);
Kevin Wolff2360622011-10-31 11:36:32 +01001105 if (reqs[i].qiov != NULL) {
1106 qemu_iovec_destroy(&qiovs[i]);
1107 }
Devin Nakamura43642b32011-07-11 11:22:16 -04001108 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001109 g_free(buf);
1110 g_free(reqs);
1111 g_free(qiovs);
Devin Nakamura43642b32011-07-11 11:22:16 -04001112 return 0;
Kevin Wolf776cbbb2010-05-21 11:37:26 +02001113}
1114
Christoph Hellwig95533d52009-06-20 21:10:44 +02001115struct aio_ctx {
Devin Nakamura43642b32011-07-11 11:22:16 -04001116 QEMUIOVector qiov;
1117 int64_t offset;
1118 char *buf;
1119 int qflag;
1120 int vflag;
1121 int Cflag;
1122 int Pflag;
1123 int pattern;
1124 struct timeval t1;
Christoph Hellwig95533d52009-06-20 21:10:44 +02001125};
1126
Devin Nakamura43642b32011-07-11 11:22:16 -04001127static void aio_write_done(void *opaque, int ret)
Christoph Hellwig95533d52009-06-20 21:10:44 +02001128{
Devin Nakamura43642b32011-07-11 11:22:16 -04001129 struct aio_ctx *ctx = opaque;
1130 struct timeval t2;
Christoph Hellwig95533d52009-06-20 21:10:44 +02001131
Devin Nakamura43642b32011-07-11 11:22:16 -04001132 gettimeofday(&t2, NULL);
Christoph Hellwig95533d52009-06-20 21:10:44 +02001133
Christoph Hellwig95533d52009-06-20 21:10:44 +02001134
Devin Nakamura43642b32011-07-11 11:22:16 -04001135 if (ret < 0) {
1136 printf("aio_write failed: %s\n", strerror(-ret));
1137 goto out;
1138 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001139
Devin Nakamura43642b32011-07-11 11:22:16 -04001140 if (ctx->qflag) {
1141 goto out;
1142 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001143
Devin Nakamura43642b32011-07-11 11:22:16 -04001144 /* 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);
Kevin Wolf7d8abfc2009-07-10 13:33:52 +02001148out:
Devin Nakamura43642b32011-07-11 11:22:16 -04001149 qemu_io_free(ctx->buf);
Kevin Wolf9e559532012-07-02 15:13:53 +02001150 qemu_iovec_destroy(&ctx->qiov);
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001151 g_free(ctx);
Christoph Hellwig95533d52009-06-20 21:10:44 +02001152}
1153
Devin Nakamura43642b32011-07-11 11:22:16 -04001154static void aio_read_done(void *opaque, int ret)
Christoph Hellwig95533d52009-06-20 21:10:44 +02001155{
Devin Nakamura43642b32011-07-11 11:22:16 -04001156 struct aio_ctx *ctx = opaque;
1157 struct timeval t2;
Christoph Hellwig95533d52009-06-20 21:10:44 +02001158
Devin Nakamura43642b32011-07-11 11:22:16 -04001159 gettimeofday(&t2, NULL);
Christoph Hellwig95533d52009-06-20 21:10:44 +02001160
Devin Nakamura43642b32011-07-11 11:22:16 -04001161 if (ret < 0) {
1162 printf("readv failed: %s\n", strerror(-ret));
1163 goto out;
1164 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001165
Devin Nakamura43642b32011-07-11 11:22:16 -04001166 if (ctx->Pflag) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001167 void *cmp_buf = g_malloc(ctx->qiov.size);
Christoph Hellwig95533d52009-06-20 21:10:44 +02001168
Devin Nakamura43642b32011-07-11 11:22:16 -04001169 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);
1173 }
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001174 g_free(cmp_buf);
Devin Nakamura43642b32011-07-11 11:22:16 -04001175 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001176
Devin Nakamura43642b32011-07-11 11:22:16 -04001177 if (ctx->qflag) {
1178 goto out;
1179 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001180
Devin Nakamura43642b32011-07-11 11:22:16 -04001181 if (ctx->vflag) {
1182 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1183 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001184
Devin Nakamura43642b32011-07-11 11:22:16 -04001185 /* 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);
Kevin Wolf7d8abfc2009-07-10 13:33:52 +02001189out:
Devin Nakamura43642b32011-07-11 11:22:16 -04001190 qemu_io_free(ctx->buf);
Kevin Wolf9e559532012-07-02 15:13:53 +02001191 qemu_iovec_destroy(&ctx->qiov);
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001192 g_free(ctx);
Christoph Hellwig95533d52009-06-20 21:10:44 +02001193}
1194
Devin Nakamura43642b32011-07-11 11:22:16 -04001195static void aio_read_help(void)
Christoph Hellwig95533d52009-06-20 21:10:44 +02001196{
Devin Nakamura43642b32011-07-11 11:22:16 -04001197 printf(
Christoph Hellwig95533d52009-06-20 21:10:44 +02001198"\n"
1199" asynchronously reads a range of bytes from the given offset\n"
1200"\n"
1201" Example:\n"
1202" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1203"\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"
Christoph Hellwige432cef2010-03-28 12:19:31 +02001206" The read is performed asynchronously and the aio_flush command must be\n"
Laszlo Ersek96bab412012-01-24 21:13:28 +01001207" used to ensure all outstanding aio requests have been completed.\n"
Christoph Hellwig95533d52009-06-20 21:10:44 +02001208" -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"
Kevin Wolf095343a2010-12-17 11:55:37 +01001211" -q, -- quiet mode, do not show I/O statistics\n"
Christoph Hellwig95533d52009-06-20 21:10:44 +02001212"\n");
1213}
1214
Blue Swirl22a2bdc2009-11-21 09:06:46 +00001215static int aio_read_f(int argc, char **argv);
1216
1217static const cmdinfo_t aio_read_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001218 .name = "aio_read",
1219 .cfunc = aio_read_f,
1220 .argmin = 2,
1221 .argmax = -1,
1222 .args = "[-Cqv] [-P pattern ] off len [len..]",
1223 .oneline = "asynchronously reads a number of bytes",
1224 .help = aio_read_help,
Blue Swirl22a2bdc2009-11-21 09:06:46 +00001225};
1226
Devin Nakamura43642b32011-07-11 11:22:16 -04001227static int aio_read_f(int argc, char **argv)
Christoph Hellwig95533d52009-06-20 21:10:44 +02001228{
Devin Nakamura43642b32011-07-11 11:22:16 -04001229 int nr_iov, c;
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001230 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
Christoph Hellwig95533d52009-06-20 21:10:44 +02001231
Devin Nakamura43642b32011-07-11 11:22:16 -04001232 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1233 switch (c) {
1234 case 'C':
1235 ctx->Cflag = 1;
1236 break;
1237 case 'P':
1238 ctx->Pflag = 1;
1239 ctx->pattern = parse_pattern(optarg);
1240 if (ctx->pattern < 0) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001241 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001242 return 0;
1243 }
1244 break;
1245 case 'q':
1246 ctx->qflag = 1;
1247 break;
1248 case 'v':
1249 ctx->vflag = 1;
1250 break;
1251 default:
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001252 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001253 return command_usage(&aio_read_cmd);
1254 }
1255 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001256
Devin Nakamura43642b32011-07-11 11:22:16 -04001257 if (optind > argc - 2) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001258 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001259 return command_usage(&aio_read_cmd);
1260 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001261
Devin Nakamura43642b32011-07-11 11:22:16 -04001262 ctx->offset = cvtnum(argv[optind]);
1263 if (ctx->offset < 0) {
1264 printf("non-numeric length argument -- %s\n", argv[optind]);
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001265 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001266 return 0;
1267 }
1268 optind++;
Christoph Hellwig95533d52009-06-20 21:10:44 +02001269
Devin Nakamura43642b32011-07-11 11:22:16 -04001270 if (ctx->offset & 0x1ff) {
1271 printf("offset %" PRId64 " is not sector aligned\n",
1272 ctx->offset);
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001273 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001274 return 0;
1275 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001276
Devin Nakamura43642b32011-07-11 11:22:16 -04001277 nr_iov = argc - optind;
1278 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
Kevin Wolff2360622011-10-31 11:36:32 +01001279 if (ctx->buf == NULL) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001280 g_free(ctx);
Kevin Wolff2360622011-10-31 11:36:32 +01001281 return 0;
1282 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001283
Devin Nakamura43642b32011-07-11 11:22:16 -04001284 gettimeofday(&ctx->t1, NULL);
Paolo Bonziniad54ae82011-11-30 09:12:30 +01001285 bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1286 ctx->qiov.size >> 9, aio_read_done, ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001287 return 0;
Christoph Hellwig95533d52009-06-20 21:10:44 +02001288}
1289
Devin Nakamura43642b32011-07-11 11:22:16 -04001290static void aio_write_help(void)
Christoph Hellwig95533d52009-06-20 21:10:44 +02001291{
Devin Nakamura43642b32011-07-11 11:22:16 -04001292 printf(
Christoph Hellwig95533d52009-06-20 21:10:44 +02001293"\n"
Devin Nakamura43642b32011-07-11 11:22:16 -04001294" asynchronously writes a range of bytes from the given offset source\n"
Christoph Hellwig95533d52009-06-20 21:10:44 +02001295" from multiple buffers\n"
1296"\n"
1297" Example:\n"
1298" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1299"\n"
1300" Writes into a segment of the currently open file, using a buffer\n"
1301" filled with a set pattern (0xcdcdcdcd).\n"
Christoph Hellwige432cef2010-03-28 12:19:31 +02001302" The write is performed asynchronously and the aio_flush command must be\n"
Laszlo Ersek96bab412012-01-24 21:13:28 +01001303" used to ensure all outstanding aio requests have been completed.\n"
Christoph Hellwig95533d52009-06-20 21:10:44 +02001304" -P, -- use different pattern to fill file\n"
1305" -C, -- report statistics in a machine parsable format\n"
Kevin Wolf095343a2010-12-17 11:55:37 +01001306" -q, -- quiet mode, do not show I/O statistics\n"
Christoph Hellwig95533d52009-06-20 21:10:44 +02001307"\n");
1308}
1309
Blue Swirl22a2bdc2009-11-21 09:06:46 +00001310static int aio_write_f(int argc, char **argv);
1311
1312static const cmdinfo_t aio_write_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001313 .name = "aio_write",
1314 .cfunc = aio_write_f,
1315 .argmin = 2,
1316 .argmax = -1,
1317 .args = "[-Cq] [-P pattern ] off len [len..]",
1318 .oneline = "asynchronously writes a number of bytes",
1319 .help = aio_write_help,
Blue Swirl22a2bdc2009-11-21 09:06:46 +00001320};
Christoph Hellwig95533d52009-06-20 21:10:44 +02001321
Devin Nakamura43642b32011-07-11 11:22:16 -04001322static int aio_write_f(int argc, char **argv)
Christoph Hellwig95533d52009-06-20 21:10:44 +02001323{
Devin Nakamura43642b32011-07-11 11:22:16 -04001324 int nr_iov, c;
1325 int pattern = 0xcd;
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001326 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
Christoph Hellwig95533d52009-06-20 21:10:44 +02001327
Devin Nakamura43642b32011-07-11 11:22:16 -04001328 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1329 switch (c) {
1330 case 'C':
1331 ctx->Cflag = 1;
1332 break;
1333 case 'q':
1334 ctx->qflag = 1;
1335 break;
1336 case 'P':
1337 pattern = parse_pattern(optarg);
1338 if (pattern < 0) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001339 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001340 return 0;
1341 }
1342 break;
1343 default:
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001344 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001345 return command_usage(&aio_write_cmd);
1346 }
1347 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001348
Devin Nakamura43642b32011-07-11 11:22:16 -04001349 if (optind > argc - 2) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001350 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001351 return command_usage(&aio_write_cmd);
1352 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001353
Devin Nakamura43642b32011-07-11 11:22:16 -04001354 ctx->offset = cvtnum(argv[optind]);
1355 if (ctx->offset < 0) {
1356 printf("non-numeric length argument -- %s\n", argv[optind]);
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001357 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001358 return 0;
1359 }
1360 optind++;
Christoph Hellwig95533d52009-06-20 21:10:44 +02001361
Devin Nakamura43642b32011-07-11 11:22:16 -04001362 if (ctx->offset & 0x1ff) {
1363 printf("offset %" PRId64 " is not sector aligned\n",
1364 ctx->offset);
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001365 g_free(ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001366 return 0;
1367 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001368
Devin Nakamura43642b32011-07-11 11:22:16 -04001369 nr_iov = argc - optind;
1370 ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
Kevin Wolff2360622011-10-31 11:36:32 +01001371 if (ctx->buf == NULL) {
Stefan Hajnoczi031380d2012-01-16 09:28:06 +00001372 g_free(ctx);
Kevin Wolff2360622011-10-31 11:36:32 +01001373 return 0;
1374 }
Christoph Hellwig95533d52009-06-20 21:10:44 +02001375
Devin Nakamura43642b32011-07-11 11:22:16 -04001376 gettimeofday(&ctx->t1, NULL);
Paolo Bonziniad54ae82011-11-30 09:12:30 +01001377 bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1378 ctx->qiov.size >> 9, aio_write_done, ctx);
Devin Nakamura43642b32011-07-11 11:22:16 -04001379 return 0;
Christoph Hellwig95533d52009-06-20 21:10:44 +02001380}
1381
Devin Nakamura43642b32011-07-11 11:22:16 -04001382static int aio_flush_f(int argc, char **argv)
Christoph Hellwig95533d52009-06-20 21:10:44 +02001383{
Kevin Wolfe7c8b092012-11-13 16:41:22 +01001384 bdrv_drain_all();
Devin Nakamura43642b32011-07-11 11:22:16 -04001385 return 0;
Christoph Hellwig95533d52009-06-20 21:10:44 +02001386}
1387
1388static const cmdinfo_t aio_flush_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001389 .name = "aio_flush",
1390 .cfunc = aio_flush_f,
1391 .oneline = "completes all outstanding aio requests"
Christoph Hellwig95533d52009-06-20 21:10:44 +02001392};
1393
Devin Nakamura43642b32011-07-11 11:22:16 -04001394static int flush_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +00001395{
Devin Nakamura43642b32011-07-11 11:22:16 -04001396 bdrv_flush(bs);
1397 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +00001398}
1399
1400static const cmdinfo_t flush_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001401 .name = "flush",
1402 .altname = "f",
1403 .cfunc = flush_f,
1404 .oneline = "flush all in-core file state to disk",
aliguorie3aff4f2009-04-05 19:14:04 +00001405};
1406
Devin Nakamura43642b32011-07-11 11:22:16 -04001407static int truncate_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +00001408{
Devin Nakamura43642b32011-07-11 11:22:16 -04001409 int64_t offset;
1410 int ret;
aliguorie3aff4f2009-04-05 19:14:04 +00001411
Devin Nakamura43642b32011-07-11 11:22:16 -04001412 offset = cvtnum(argv[1]);
1413 if (offset < 0) {
1414 printf("non-numeric truncate argument -- %s\n", argv[1]);
1415 return 0;
1416 }
aliguorie3aff4f2009-04-05 19:14:04 +00001417
Devin Nakamura43642b32011-07-11 11:22:16 -04001418 ret = bdrv_truncate(bs, offset);
1419 if (ret < 0) {
1420 printf("truncate: %s\n", strerror(-ret));
1421 return 0;
1422 }
aliguorie3aff4f2009-04-05 19:14:04 +00001423
Devin Nakamura43642b32011-07-11 11:22:16 -04001424 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +00001425}
1426
1427static const cmdinfo_t truncate_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001428 .name = "truncate",
1429 .altname = "t",
1430 .cfunc = truncate_f,
1431 .argmin = 1,
1432 .argmax = 1,
1433 .args = "off",
1434 .oneline = "truncates the current file at the given offset",
aliguorie3aff4f2009-04-05 19:14:04 +00001435};
1436
Devin Nakamura43642b32011-07-11 11:22:16 -04001437static int length_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +00001438{
Devin Nakamura43642b32011-07-11 11:22:16 -04001439 int64_t size;
1440 char s1[64];
aliguorie3aff4f2009-04-05 19:14:04 +00001441
Devin Nakamura43642b32011-07-11 11:22:16 -04001442 size = bdrv_getlength(bs);
1443 if (size < 0) {
1444 printf("getlength: %s\n", strerror(-size));
1445 return 0;
1446 }
aliguorie3aff4f2009-04-05 19:14:04 +00001447
Devin Nakamura43642b32011-07-11 11:22:16 -04001448 cvtstr(size, s1, sizeof(s1));
1449 printf("%s\n", s1);
1450 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +00001451}
1452
1453
1454static const cmdinfo_t length_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001455 .name = "length",
1456 .altname = "l",
1457 .cfunc = length_f,
1458 .oneline = "gets the length of the current file",
aliguorie3aff4f2009-04-05 19:14:04 +00001459};
1460
1461
Devin Nakamura43642b32011-07-11 11:22:16 -04001462static int info_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +00001463{
Devin Nakamura43642b32011-07-11 11:22:16 -04001464 BlockDriverInfo bdi;
1465 char s1[64], s2[64];
1466 int ret;
aliguorie3aff4f2009-04-05 19:14:04 +00001467
Devin Nakamura43642b32011-07-11 11:22:16 -04001468 if (bs->drv && bs->drv->format_name) {
1469 printf("format name: %s\n", bs->drv->format_name);
1470 }
1471 if (bs->drv && bs->drv->protocol_name) {
1472 printf("format name: %s\n", bs->drv->protocol_name);
1473 }
aliguorie3aff4f2009-04-05 19:14:04 +00001474
Devin Nakamura43642b32011-07-11 11:22:16 -04001475 ret = bdrv_get_info(bs, &bdi);
1476 if (ret) {
1477 return 0;
1478 }
aliguorie3aff4f2009-04-05 19:14:04 +00001479
Devin Nakamura43642b32011-07-11 11:22:16 -04001480 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1481 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
aliguorie3aff4f2009-04-05 19:14:04 +00001482
Devin Nakamura43642b32011-07-11 11:22:16 -04001483 printf("cluster size: %s\n", s1);
1484 printf("vm state offset: %s\n", s2);
aliguorie3aff4f2009-04-05 19:14:04 +00001485
Devin Nakamura43642b32011-07-11 11:22:16 -04001486 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +00001487}
1488
1489
1490
1491static const cmdinfo_t info_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001492 .name = "info",
1493 .altname = "i",
1494 .cfunc = info_f,
1495 .oneline = "prints information about the current file",
aliguorie3aff4f2009-04-05 19:14:04 +00001496};
1497
Devin Nakamura43642b32011-07-11 11:22:16 -04001498static void discard_help(void)
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001499{
Devin Nakamura43642b32011-07-11 11:22:16 -04001500 printf(
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001501"\n"
1502" discards a range of bytes from the given offset\n"
1503"\n"
1504" Example:\n"
1505" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1506"\n"
1507" Discards a segment of the currently open file.\n"
1508" -C, -- report statistics in a machine parsable format\n"
Kevin Wolf095343a2010-12-17 11:55:37 +01001509" -q, -- quiet mode, do not show I/O statistics\n"
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001510"\n");
1511}
1512
1513static int discard_f(int argc, char **argv);
1514
1515static const cmdinfo_t discard_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001516 .name = "discard",
1517 .altname = "d",
1518 .cfunc = discard_f,
1519 .argmin = 2,
1520 .argmax = -1,
1521 .args = "[-Cq] off len",
1522 .oneline = "discards a number of bytes at a specified offset",
1523 .help = discard_help,
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001524};
1525
Devin Nakamura43642b32011-07-11 11:22:16 -04001526static int discard_f(int argc, char **argv)
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001527{
Devin Nakamura43642b32011-07-11 11:22:16 -04001528 struct timeval t1, t2;
1529 int Cflag = 0, qflag = 0;
1530 int c, ret;
1531 int64_t offset;
1532 int count;
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001533
Devin Nakamura43642b32011-07-11 11:22:16 -04001534 while ((c = getopt(argc, argv, "Cq")) != EOF) {
1535 switch (c) {
1536 case 'C':
1537 Cflag = 1;
1538 break;
1539 case 'q':
1540 qflag = 1;
1541 break;
1542 default:
1543 return command_usage(&discard_cmd);
1544 }
1545 }
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001546
Devin Nakamura43642b32011-07-11 11:22:16 -04001547 if (optind != argc - 2) {
1548 return command_usage(&discard_cmd);
1549 }
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001550
Devin Nakamura43642b32011-07-11 11:22:16 -04001551 offset = cvtnum(argv[optind]);
1552 if (offset < 0) {
1553 printf("non-numeric length argument -- %s\n", argv[optind]);
1554 return 0;
1555 }
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001556
Devin Nakamura43642b32011-07-11 11:22:16 -04001557 optind++;
1558 count = cvtnum(argv[optind]);
1559 if (count < 0) {
1560 printf("non-numeric length argument -- %s\n", argv[optind]);
1561 return 0;
1562 }
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001563
Devin Nakamura43642b32011-07-11 11:22:16 -04001564 gettimeofday(&t1, NULL);
1565 ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1566 count >> BDRV_SECTOR_BITS);
1567 gettimeofday(&t2, NULL);
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001568
Devin Nakamura43642b32011-07-11 11:22:16 -04001569 if (ret < 0) {
1570 printf("discard failed: %s\n", strerror(-ret));
1571 goto out;
1572 }
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001573
Devin Nakamura43642b32011-07-11 11:22:16 -04001574 /* Finally, report back -- -C gives a parsable format */
1575 if (!qflag) {
1576 t2 = tsub(t2, t1);
1577 print_report("discard", &t2, offset, count, count, 1, Cflag);
1578 }
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001579
1580out:
Devin Nakamura43642b32011-07-11 11:22:16 -04001581 return 0;
Stefan Hajnocziedff5db2010-12-13 09:36:26 +00001582}
1583
Devin Nakamura43642b32011-07-11 11:22:16 -04001584static int alloc_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +00001585{
Paolo Bonzinicc785c32012-05-08 16:51:52 +02001586 int64_t offset, sector_num;
Devin Nakamura43642b32011-07-11 11:22:16 -04001587 int nb_sectors, remaining;
1588 char s1[64];
1589 int num, sum_alloc;
1590 int ret;
aliguorie3aff4f2009-04-05 19:14:04 +00001591
Devin Nakamura43642b32011-07-11 11:22:16 -04001592 offset = cvtnum(argv[1]);
1593 if (offset & 0x1ff) {
1594 printf("offset %" PRId64 " is not sector aligned\n",
1595 offset);
1596 return 0;
1597 }
aliguorie3aff4f2009-04-05 19:14:04 +00001598
Devin Nakamura43642b32011-07-11 11:22:16 -04001599 if (argc == 3) {
1600 nb_sectors = cvtnum(argv[2]);
1601 } else {
1602 nb_sectors = 1;
1603 }
aliguorie3aff4f2009-04-05 19:14:04 +00001604
Devin Nakamura43642b32011-07-11 11:22:16 -04001605 remaining = nb_sectors;
1606 sum_alloc = 0;
Paolo Bonzinicc785c32012-05-08 16:51:52 +02001607 sector_num = offset >> 9;
Devin Nakamura43642b32011-07-11 11:22:16 -04001608 while (remaining) {
Paolo Bonzinicc785c32012-05-08 16:51:52 +02001609 ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1610 sector_num += num;
Devin Nakamura43642b32011-07-11 11:22:16 -04001611 remaining -= num;
1612 if (ret) {
1613 sum_alloc += num;
1614 }
Paolo Bonzinicc785c32012-05-08 16:51:52 +02001615 if (num == 0) {
1616 nb_sectors -= remaining;
1617 remaining = 0;
1618 }
Devin Nakamura43642b32011-07-11 11:22:16 -04001619 }
aliguorie3aff4f2009-04-05 19:14:04 +00001620
Devin Nakamura43642b32011-07-11 11:22:16 -04001621 cvtstr(offset, s1, sizeof(s1));
aliguorie3aff4f2009-04-05 19:14:04 +00001622
Devin Nakamura43642b32011-07-11 11:22:16 -04001623 printf("%d/%d sectors allocated at offset %s\n",
1624 sum_alloc, nb_sectors, s1);
1625 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +00001626}
1627
1628static const cmdinfo_t alloc_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001629 .name = "alloc",
1630 .altname = "a",
1631 .argmin = 1,
1632 .argmax = 2,
1633 .cfunc = alloc_f,
1634 .args = "off [sectors]",
1635 .oneline = "checks if a sector is present in the file",
aliguorie3aff4f2009-04-05 19:14:04 +00001636};
1637
Devin Nakamura43642b32011-07-11 11:22:16 -04001638static int map_f(int argc, char **argv)
Kevin Wolf191c2892010-09-16 13:18:08 +02001639{
Devin Nakamura43642b32011-07-11 11:22:16 -04001640 int64_t offset;
1641 int64_t nb_sectors;
1642 char s1[64];
1643 int num, num_checked;
1644 int ret;
1645 const char *retstr;
Kevin Wolf191c2892010-09-16 13:18:08 +02001646
Devin Nakamura43642b32011-07-11 11:22:16 -04001647 offset = 0;
1648 nb_sectors = bs->total_sectors;
Kevin Wolf191c2892010-09-16 13:18:08 +02001649
Devin Nakamura43642b32011-07-11 11:22:16 -04001650 do {
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);
Kevin Wolf191c2892010-09-16 13:18:08 +02001657
Devin Nakamura43642b32011-07-11 11:22:16 -04001658 offset += num;
1659 nb_sectors -= num;
1660 } while (offset < bs->total_sectors);
Kevin Wolf191c2892010-09-16 13:18:08 +02001661
Devin Nakamura43642b32011-07-11 11:22:16 -04001662 return 0;
Kevin Wolf191c2892010-09-16 13:18:08 +02001663}
1664
1665static const cmdinfo_t map_cmd = {
1666 .name = "map",
1667 .argmin = 0,
1668 .argmax = 0,
1669 .cfunc = map_f,
1670 .args = "",
1671 .oneline = "prints the allocated areas of a file",
1672};
1673
Kevin Wolf41c695c2012-12-06 14:32:58 +01001674static int break_f(int argc, char **argv)
1675{
1676 int ret;
1677
1678 ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1679 if (ret < 0) {
1680 printf("Could not set breakpoint: %s\n", strerror(-ret));
1681 }
1682
1683 return 0;
1684}
1685
1686static const cmdinfo_t break_cmd = {
1687 .name = "break",
1688 .argmin = 2,
1689 .argmax = 2,
1690 .cfunc = break_f,
1691 .args = "event tag",
1692 .oneline = "sets a breakpoint on event and tags the stopped "
1693 "request as tag",
1694};
1695
1696static int resume_f(int argc, char **argv)
1697{
1698 int ret;
1699
1700 ret = bdrv_debug_resume(bs, argv[1]);
1701 if (ret < 0) {
1702 printf("Could not resume request: %s\n", strerror(-ret));
1703 }
1704
1705 return 0;
1706}
1707
1708static const cmdinfo_t resume_cmd = {
1709 .name = "resume",
1710 .argmin = 1,
1711 .argmax = 1,
1712 .cfunc = resume_f,
1713 .args = "tag",
1714 .oneline = "resumes the request tagged as tag",
1715};
1716
1717static int wait_break_f(int argc, char **argv)
1718{
1719 while (!bdrv_debug_is_suspended(bs, argv[1])) {
1720 qemu_aio_wait();
1721 }
1722
1723 return 0;
1724}
1725
1726static const cmdinfo_t wait_break_cmd = {
1727 .name = "wait_break",
1728 .argmin = 1,
1729 .argmax = 1,
1730 .cfunc = wait_break_f,
1731 .args = "tag",
1732 .oneline = "waits for the suspension of a request",
1733};
1734
Stefan Hajnoczie01c30d2012-07-27 09:05:23 +01001735static int abort_f(int argc, char **argv)
1736{
1737 abort();
1738}
1739
1740static const cmdinfo_t abort_cmd = {
1741 .name = "abort",
1742 .cfunc = abort_f,
1743 .flags = CMD_NOFILE_OK,
1744 .oneline = "simulate a program crash using abort(3)",
1745};
Kevin Wolf191c2892010-09-16 13:18:08 +02001746
Devin Nakamura43642b32011-07-11 11:22:16 -04001747static int close_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +00001748{
Stefan Hajnoczib4657852011-10-27 10:54:26 +01001749 bdrv_delete(bs);
Devin Nakamura43642b32011-07-11 11:22:16 -04001750 bs = NULL;
1751 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +00001752}
1753
1754static const cmdinfo_t close_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001755 .name = "close",
1756 .altname = "c",
1757 .cfunc = close_f,
1758 .oneline = "close the current open file",
aliguorie3aff4f2009-04-05 19:14:04 +00001759};
1760
Christoph Hellwig9c4bab22009-07-10 13:33:47 +02001761static int openfile(char *name, int flags, int growable)
aliguorie3aff4f2009-04-05 19:14:04 +00001762{
Devin Nakamura43642b32011-07-11 11:22:16 -04001763 if (bs) {
1764 fprintf(stderr, "file open already, try 'help close'\n");
1765 return 1;
1766 }
aliguorie3aff4f2009-04-05 19:14:04 +00001767
Devin Nakamura43642b32011-07-11 11:22:16 -04001768 if (growable) {
1769 if (bdrv_file_open(&bs, name, flags)) {
1770 fprintf(stderr, "%s: can't open device %s\n", progname, name);
1771 return 1;
1772 }
1773 } else {
1774 bs = bdrv_new("hda");
Christoph Hellwig6db95602010-04-05 16:53:57 +02001775
Devin Nakamura43642b32011-07-11 11:22:16 -04001776 if (bdrv_open(bs, name, flags, NULL) < 0) {
1777 fprintf(stderr, "%s: can't open device %s\n", progname, name);
Stefan Hajnoczib4657852011-10-27 10:54:26 +01001778 bdrv_delete(bs);
Devin Nakamura43642b32011-07-11 11:22:16 -04001779 bs = NULL;
1780 return 1;
1781 }
1782 }
Christoph Hellwig1db69472009-07-15 23:11:21 +02001783
Devin Nakamura43642b32011-07-11 11:22:16 -04001784 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +00001785}
1786
Devin Nakamura43642b32011-07-11 11:22:16 -04001787static void open_help(void)
aliguorie3aff4f2009-04-05 19:14:04 +00001788{
Devin Nakamura43642b32011-07-11 11:22:16 -04001789 printf(
aliguorie3aff4f2009-04-05 19:14:04 +00001790"\n"
1791" opens a new file in the requested mode\n"
1792"\n"
1793" Example:\n"
1794" 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
1795"\n"
1796" Opens a file for subsequent use by all of the other qemu-io commands.\n"
aliguorie3aff4f2009-04-05 19:14:04 +00001797" -r, -- open file read-only\n"
1798" -s, -- use snapshot file\n"
1799" -n, -- disable host cache\n"
Christoph Hellwig9c4bab22009-07-10 13:33:47 +02001800" -g, -- allow file to grow (only applies to protocols)"
aliguorie3aff4f2009-04-05 19:14:04 +00001801"\n");
1802}
1803
Blue Swirl22a2bdc2009-11-21 09:06:46 +00001804static int open_f(int argc, char **argv);
1805
1806static const cmdinfo_t open_cmd = {
Devin Nakamura43642b32011-07-11 11:22:16 -04001807 .name = "open",
1808 .altname = "o",
1809 .cfunc = open_f,
1810 .argmin = 1,
1811 .argmax = -1,
1812 .flags = CMD_NOFILE_OK,
1813 .args = "[-Crsn] [path]",
1814 .oneline = "open the file specified by path",
1815 .help = open_help,
Blue Swirl22a2bdc2009-11-21 09:06:46 +00001816};
aliguorie3aff4f2009-04-05 19:14:04 +00001817
Devin Nakamura43642b32011-07-11 11:22:16 -04001818static int open_f(int argc, char **argv)
aliguorie3aff4f2009-04-05 19:14:04 +00001819{
Devin Nakamura43642b32011-07-11 11:22:16 -04001820 int flags = 0;
1821 int readonly = 0;
1822 int growable = 0;
1823 int c;
aliguorie3aff4f2009-04-05 19:14:04 +00001824
Devin Nakamura43642b32011-07-11 11:22:16 -04001825 while ((c = getopt(argc, argv, "snrg")) != EOF) {
1826 switch (c) {
1827 case 's':
1828 flags |= BDRV_O_SNAPSHOT;
1829 break;
1830 case 'n':
1831 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
1832 break;
1833 case 'r':
1834 readonly = 1;
1835 break;
1836 case 'g':
1837 growable = 1;
1838 break;
1839 default:
1840 return command_usage(&open_cmd);
Naphtali Spreif5edb012010-01-17 16:48:13 +02001841 }
Devin Nakamura43642b32011-07-11 11:22:16 -04001842 }
aliguorie3aff4f2009-04-05 19:14:04 +00001843
Devin Nakamura43642b32011-07-11 11:22:16 -04001844 if (!readonly) {
1845 flags |= BDRV_O_RDWR;
1846 }
aliguorie3aff4f2009-04-05 19:14:04 +00001847
Devin Nakamura43642b32011-07-11 11:22:16 -04001848 if (optind != argc - 1) {
1849 return command_usage(&open_cmd);
1850 }
1851
1852 return openfile(argv[optind], flags, growable);
aliguorie3aff4f2009-04-05 19:14:04 +00001853}
1854
Devin Nakamura43642b32011-07-11 11:22:16 -04001855static int init_args_command(int index)
aliguorie3aff4f2009-04-05 19:14:04 +00001856{
Devin Nakamura43642b32011-07-11 11:22:16 -04001857 /* only one device allowed so far */
1858 if (index >= 1) {
1859 return 0;
1860 }
1861 return ++index;
aliguorie3aff4f2009-04-05 19:14:04 +00001862}
1863
Devin Nakamura43642b32011-07-11 11:22:16 -04001864static int init_check_command(const cmdinfo_t *ct)
aliguorie3aff4f2009-04-05 19:14:04 +00001865{
Devin Nakamura43642b32011-07-11 11:22:16 -04001866 if (ct->flags & CMD_FLAG_GLOBAL) {
1867 return 1;
1868 }
1869 if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1870 fprintf(stderr, "no file open, try 'help open'\n");
1871 return 0;
1872 }
1873 return 1;
aliguorie3aff4f2009-04-05 19:14:04 +00001874}
1875
1876static void usage(const char *name)
1877{
Devin Nakamura43642b32011-07-11 11:22:16 -04001878 printf(
Christoph Hellwig9a2d77a2010-01-20 18:13:42 +01001879"Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
Stefan Weil84844a22009-06-22 15:08:47 +02001880"QEMU Disk exerciser\n"
aliguorie3aff4f2009-04-05 19:14:04 +00001881"\n"
aliguorie3aff4f2009-04-05 19:14:04 +00001882" -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"
Christoph Hellwig1db69472009-07-15 23:11:21 +02001886" -g, --growable allow file to grow (only applies to protocols)\n"
aliguorie3aff4f2009-04-05 19:14:04 +00001887" -m, --misalign misalign allocations for O_DIRECT\n"
Christoph Hellwig5c6c3a62009-08-20 16:58:35 +02001888" -k, --native-aio use kernel AIO implementation (on Linux only)\n"
Kevin Wolf592fa072012-04-18 12:07:39 +02001889" -t, --cache=MODE use the given cache mode for the image\n"
Stefan Hajnoczid7bb72c2012-03-12 16:36:07 +00001890" -T, --trace FILE enable trace events listed in the given file\n"
aliguorie3aff4f2009-04-05 19:14:04 +00001891" -h, --help display this help and exit\n"
1892" -V, --version output version information and exit\n"
1893"\n",
Devin Nakamura43642b32011-07-11 11:22:16 -04001894 name);
aliguorie3aff4f2009-04-05 19:14:04 +00001895}
1896
1897
1898int main(int argc, char **argv)
1899{
Devin Nakamura43642b32011-07-11 11:22:16 -04001900 int readonly = 0;
1901 int growable = 0;
Kevin Wolf592fa072012-04-18 12:07:39 +02001902 const char *sopt = "hVc:rsnmgkt:T:";
Devin Nakamura43642b32011-07-11 11:22:16 -04001903 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' },
Kevin Wolf592fa072012-04-18 12:07:39 +02001914 { "cache", 1, NULL, 't' },
Stefan Hajnoczid7bb72c2012-03-12 16:36:07 +00001915 { "trace", 1, NULL, 'T' },
Devin Nakamura43642b32011-07-11 11:22:16 -04001916 { NULL, 0, NULL, 0 }
1917 };
1918 int c;
1919 int opt_index = 0;
1920 int flags = 0;
aliguorie3aff4f2009-04-05 19:14:04 +00001921
Devin Nakamura43642b32011-07-11 11:22:16 -04001922 progname = basename(argv[0]);
aliguorie3aff4f2009-04-05 19:14:04 +00001923
Devin Nakamura43642b32011-07-11 11:22:16 -04001924 while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
1925 switch (c) {
1926 case 's':
1927 flags |= BDRV_O_SNAPSHOT;
1928 break;
1929 case 'n':
1930 flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
1931 break;
1932 case 'c':
1933 add_user_command(optarg);
1934 break;
1935 case 'r':
1936 readonly = 1;
1937 break;
1938 case 'm':
1939 misalign = 1;
1940 break;
1941 case 'g':
1942 growable = 1;
1943 break;
1944 case 'k':
1945 flags |= BDRV_O_NATIVE_AIO;
1946 break;
Kevin Wolf592fa072012-04-18 12:07:39 +02001947 case 't':
1948 if (bdrv_parse_cache_flags(optarg, &flags) < 0) {
1949 error_report("Invalid cache option: %s", optarg);
1950 exit(1);
1951 }
1952 break;
Stefan Hajnoczid7bb72c2012-03-12 16:36:07 +00001953 case 'T':
1954 if (!trace_backend_init(optarg, NULL)) {
1955 exit(1); /* error message will have been printed */
1956 }
1957 break;
Devin Nakamura43642b32011-07-11 11:22:16 -04001958 case 'V':
1959 printf("%s version %s\n", progname, VERSION);
1960 exit(0);
1961 case 'h':
1962 usage(progname);
1963 exit(0);
1964 default:
1965 usage(progname);
1966 exit(1);
Naphtali Spreif5edb012010-01-17 16:48:13 +02001967 }
Devin Nakamura43642b32011-07-11 11:22:16 -04001968 }
aliguorie3aff4f2009-04-05 19:14:04 +00001969
Devin Nakamura43642b32011-07-11 11:22:16 -04001970 if ((argc - optind) > 1) {
1971 usage(progname);
1972 exit(1);
1973 }
aliguorie3aff4f2009-04-05 19:14:04 +00001974
Zhi Yong Wua57d1142012-02-19 22:24:59 +08001975 qemu_init_main_loop();
Paolo Bonzini2592c592012-11-03 18:10:17 +01001976 bdrv_init();
Zhi Yong Wua57d1142012-02-19 22:24:59 +08001977
Devin Nakamura43642b32011-07-11 11:22:16 -04001978 /* initialize commands */
1979 quit_init();
1980 help_init();
1981 add_command(&open_cmd);
1982 add_command(&close_cmd);
1983 add_command(&read_cmd);
1984 add_command(&readv_cmd);
1985 add_command(&write_cmd);
1986 add_command(&writev_cmd);
1987 add_command(&multiwrite_cmd);
1988 add_command(&aio_read_cmd);
1989 add_command(&aio_write_cmd);
1990 add_command(&aio_flush_cmd);
1991 add_command(&flush_cmd);
1992 add_command(&truncate_cmd);
1993 add_command(&length_cmd);
1994 add_command(&info_cmd);
1995 add_command(&discard_cmd);
1996 add_command(&alloc_cmd);
1997 add_command(&map_cmd);
Kevin Wolf41c695c2012-12-06 14:32:58 +01001998 add_command(&break_cmd);
1999 add_command(&resume_cmd);
2000 add_command(&wait_break_cmd);
Stefan Hajnoczie01c30d2012-07-27 09:05:23 +01002001 add_command(&abort_cmd);
Devin Nakamura43642b32011-07-11 11:22:16 -04002002
2003 add_args_command(init_args_command);
2004 add_check_command(init_check_command);
2005
2006 /* open the device */
2007 if (!readonly) {
2008 flags |= BDRV_O_RDWR;
2009 }
2010
2011 if ((argc - optind) == 1) {
2012 openfile(argv[optind], flags, growable);
2013 }
2014 command_loop();
2015
2016 /*
Stefan Hajnoczi922453b2011-11-30 12:23:43 +00002017 * Make sure all outstanding requests complete before the program exits.
Devin Nakamura43642b32011-07-11 11:22:16 -04002018 */
Stefan Hajnoczi922453b2011-11-30 12:23:43 +00002019 bdrv_drain_all();
Devin Nakamura43642b32011-07-11 11:22:16 -04002020
2021 if (bs) {
Stefan Hajnoczib4657852011-10-27 10:54:26 +01002022 bdrv_delete(bs);
Devin Nakamura43642b32011-07-11 11:22:16 -04002023 }
2024 return 0;
aliguorie3aff4f2009-04-05 19:14:04 +00002025}