]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-io-cmds.c
hw/arm/virt-acpi-build: remove unnecessary variable mcfg_start
[mirror_qemu.git] / qemu-io-cmds.c
CommitLineData
797ac58c
KW
1/*
2 * Command line utility to exercise the QEMU I/O path.
3 *
093ea232 4 * Copyright (C) 2009-2016 Red Hat, Inc.
797ac58c
KW
5 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
9 */
10
80c71a24 11#include "qemu/osdep.h"
da34e65c 12#include "qapi/error.h"
dc900c35 13#include "qapi/qmp/qdict.h"
3d21994f 14#include "qemu-io.h"
4c7b7e9b
HR
15#include "sysemu/block-backend.h"
16#include "block/block.h"
17#include "block/block_int.h" /* for info_f() */
a8d8ecb7 18#include "block/qapi.h"
d49b6836 19#include "qemu/error-report.h"
6a1751b7 20#include "qemu/main-loop.h"
922a01a0 21#include "qemu/option.h"
cd33d02a 22#include "qemu/timer.h"
f348b6d1 23#include "qemu/cutils.h"
797ac58c
KW
24
25#define CMD_NOFILE_OK 0x01
26
f9883880 27bool qemuio_misalign;
797ac58c 28
c2cdf5c5
KW
29static cmdinfo_t *cmdtab;
30static int ncmds;
31
32static int compare_cmdname(const void *a, const void *b)
33{
34 return strcmp(((const cmdinfo_t *)a)->name,
35 ((const cmdinfo_t *)b)->name);
36}
37
38void qemuio_add_command(const cmdinfo_t *ci)
39{
6aabeb58
PM
40 /* ci->perm assumes a file is open, but the GLOBAL and NOFILE_OK
41 * flags allow it not to be, so that combination is invalid.
42 * Catch it now rather than letting it manifest as a crash if a
43 * particular set of command line options are used.
44 */
45 assert(ci->perm == 0 ||
46 (ci->flags & (CMD_FLAG_GLOBAL | CMD_NOFILE_OK)) == 0);
02c4f26b 47 cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds);
c2cdf5c5
KW
48 cmdtab[ncmds - 1] = *ci;
49 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
50}
51
b444d0e9 52void qemuio_command_usage(const cmdinfo_t *ci)
c2cdf5c5
KW
53{
54 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
c2cdf5c5
KW
55}
56
4c7b7e9b 57static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
c2cdf5c5
KW
58{
59 if (ct->flags & CMD_FLAG_GLOBAL) {
60 return 1;
61 }
4c7b7e9b 62 if (!(ct->flags & CMD_NOFILE_OK) && !blk) {
c2cdf5c5
KW
63 fprintf(stderr, "no file open, try 'help open'\n");
64 return 0;
65 }
66 return 1;
67}
68
b32d7a39
HR
69static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
70 char **argv)
c2cdf5c5
KW
71{
72 char *cmd = argv[0];
73
4c7b7e9b 74 if (!init_check_command(blk, ct)) {
b32d7a39 75 return -EINVAL;
c2cdf5c5
KW
76 }
77
78 if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
79 if (ct->argmax == -1) {
80 fprintf(stderr,
81 "bad argument count %d to %s, expected at least %d arguments\n",
82 argc-1, cmd, ct->argmin);
83 } else if (ct->argmin == ct->argmax) {
84 fprintf(stderr,
85 "bad argument count %d to %s, expected %d arguments\n",
86 argc-1, cmd, ct->argmin);
87 } else {
88 fprintf(stderr,
89 "bad argument count %d to %s, expected between %d and %d arguments\n",
90 argc-1, cmd, ct->argmin, ct->argmax);
91 }
b32d7a39 92 return -EINVAL;
c2cdf5c5 93 }
887354bd
KW
94
95 /* Request additional permissions if necessary for this command. The caller
96 * is responsible for restoring the original permissions afterwards if this
97 * is what it wants. */
98 if (ct->perm && blk_is_available(blk)) {
99 uint64_t orig_perm, orig_shared_perm;
100 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
101
102 if (ct->perm & ~orig_perm) {
103 uint64_t new_perm;
104 Error *local_err = NULL;
105 int ret;
106
107 new_perm = orig_perm | ct->perm;
108
109 ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
110 if (ret < 0) {
111 error_report_err(local_err);
b32d7a39 112 return ret;
887354bd
KW
113 }
114 }
115 }
116
d339d766 117 qemu_reset_optind();
b32d7a39 118 return ct->cfunc(blk, argc, argv);
c2cdf5c5
KW
119}
120
121static const cmdinfo_t *find_command(const char *cmd)
122{
123 cmdinfo_t *ct;
124
125 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
126 if (strcmp(ct->name, cmd) == 0 ||
127 (ct->altname && strcmp(ct->altname, cmd) == 0))
128 {
129 return (const cmdinfo_t *)ct;
130 }
131 }
132 return NULL;
133}
134
4694020d
SH
135/* Invoke fn() for commands with a matching prefix */
136void qemuio_complete_command(const char *input,
137 void (*fn)(const char *cmd, void *opaque),
138 void *opaque)
139{
140 cmdinfo_t *ct;
141 size_t input_len = strlen(input);
142
143 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
144 if (strncmp(input, ct->name, input_len) == 0) {
145 fn(ct->name, opaque);
146 }
147 }
148}
149
c2cdf5c5
KW
150static char **breakline(char *input, int *count)
151{
152 int c = 0;
153 char *p;
5839e53b 154 char **rval = g_new0(char *, 1);
c2cdf5c5
KW
155
156 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
157 if (!*p) {
158 continue;
159 }
160 c++;
08193dd5 161 rval = g_renew(char *, rval, (c + 1));
c2cdf5c5
KW
162 rval[c - 1] = p;
163 rval[c] = NULL;
164 }
165 *count = c;
166 return rval;
167}
168
797ac58c
KW
169static int64_t cvtnum(const char *s)
170{
f17fd4fd 171 int err;
f46bfdbf 172 uint64_t value;
ef5a7885 173
f17fd4fd
MA
174 err = qemu_strtosz(s, NULL, &value);
175 if (err < 0) {
176 return err;
177 }
f46bfdbf
MA
178 if (value > INT64_MAX) {
179 return -ERANGE;
180 }
f17fd4fd 181 return value;
797ac58c
KW
182}
183
a9ecfa00
JS
184static void print_cvtnum_err(int64_t rc, const char *arg)
185{
186 switch (rc) {
187 case -EINVAL:
188 printf("Parsing error: non-numeric argument,"
189 " or extraneous/unrecognized suffix -- %s\n", arg);
190 break;
191 case -ERANGE:
192 printf("Parsing error: argument too large -- %s\n", arg);
193 break;
194 default:
195 printf("Parsing error: %s\n", arg);
196 }
197}
198
0b613881
KW
199#define EXABYTES(x) ((long long)(x) << 60)
200#define PETABYTES(x) ((long long)(x) << 50)
201#define TERABYTES(x) ((long long)(x) << 40)
202#define GIGABYTES(x) ((long long)(x) << 30)
203#define MEGABYTES(x) ((long long)(x) << 20)
204#define KILOBYTES(x) ((long long)(x) << 10)
205
206#define TO_EXABYTES(x) ((x) / EXABYTES(1))
207#define TO_PETABYTES(x) ((x) / PETABYTES(1))
208#define TO_TERABYTES(x) ((x) / TERABYTES(1))
209#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
210#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
211#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
212
213static void cvtstr(double value, char *str, size_t size)
214{
215 char *trim;
216 const char *suffix;
217
218 if (value >= EXABYTES(1)) {
219 suffix = " EiB";
220 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
221 } else if (value >= PETABYTES(1)) {
222 suffix = " PiB";
223 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
224 } else if (value >= TERABYTES(1)) {
225 suffix = " TiB";
226 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
227 } else if (value >= GIGABYTES(1)) {
228 suffix = " GiB";
229 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
230 } else if (value >= MEGABYTES(1)) {
231 suffix = " MiB";
232 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
233 } else if (value >= KILOBYTES(1)) {
234 suffix = " KiB";
235 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
236 } else {
237 suffix = " bytes";
238 snprintf(str, size - 6, "%f", value);
239 }
240
241 trim = strstr(str, ".000");
242 if (trim) {
243 strcpy(trim, suffix);
244 } else {
245 strcat(str, suffix);
246 }
247}
248
249
250
251static struct timeval tsub(struct timeval t1, struct timeval t2)
252{
253 t1.tv_usec -= t2.tv_usec;
254 if (t1.tv_usec < 0) {
255 t1.tv_usec += 1000000;
256 t1.tv_sec--;
257 }
258 t1.tv_sec -= t2.tv_sec;
259 return t1;
260}
261
262static double tdiv(double value, struct timeval tv)
263{
264 return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
265}
266
267#define HOURS(sec) ((sec) / (60 * 60))
268#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
269#define SECONDS(sec) ((sec) % 60)
270
271enum {
272 DEFAULT_TIME = 0x0,
273 TERSE_FIXED_TIME = 0x1,
274 VERBOSE_FIXED_TIME = 0x2,
275};
276
277static void timestr(struct timeval *tv, char *ts, size_t size, int format)
278{
279 double usec = (double)tv->tv_usec / 1000000.0;
280
281 if (format & TERSE_FIXED_TIME) {
282 if (!HOURS(tv->tv_sec)) {
283 snprintf(ts, size, "%u:%02u.%02u",
284 (unsigned int) MINUTES(tv->tv_sec),
285 (unsigned int) SECONDS(tv->tv_sec),
286 (unsigned int) (usec * 100));
287 return;
288 }
289 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
290 }
291
292 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
293 snprintf(ts, size, "%u:%02u:%02u.%02u",
294 (unsigned int) HOURS(tv->tv_sec),
295 (unsigned int) MINUTES(tv->tv_sec),
296 (unsigned int) SECONDS(tv->tv_sec),
297 (unsigned int) (usec * 100));
298 } else {
299 snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
300 }
301}
302
797ac58c
KW
303/*
304 * Parse the pattern argument to various sub-commands.
305 *
306 * Because the pattern is used as an argument to memset it must evaluate
307 * to an unsigned integer that fits into a single byte.
308 */
309static int parse_pattern(const char *arg)
310{
311 char *endptr = NULL;
312 long pattern;
313
314 pattern = strtol(arg, &endptr, 0);
315 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
316 printf("%s is not a valid pattern byte\n", arg);
317 return -1;
318 }
319
320 return pattern;
321}
322
323/*
324 * Memory allocation helpers.
325 *
326 * Make sure memory is aligned by default, or purposefully misaligned if
327 * that is specified on the command line.
328 */
329
330#define MISALIGN_OFFSET 16
4c7b7e9b 331static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern)
797ac58c
KW
332{
333 void *buf;
334
335 if (qemuio_misalign) {
336 len += MISALIGN_OFFSET;
337 }
4c7b7e9b 338 buf = blk_blockalign(blk, len);
797ac58c
KW
339 memset(buf, pattern, len);
340 if (qemuio_misalign) {
341 buf += MISALIGN_OFFSET;
342 }
343 return buf;
344}
345
346static void qemu_io_free(void *p)
347{
348 if (qemuio_misalign) {
349 p -= MISALIGN_OFFSET;
350 }
351 qemu_vfree(p);
352}
353
9b0beaf3 354static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
797ac58c 355{
9b0beaf3
JS
356 uint64_t i;
357 int j;
797ac58c
KW
358 const uint8_t *p;
359
360 for (i = 0, p = buffer; i < len; i += 16) {
361 const uint8_t *s = p;
362
363 printf("%08" PRIx64 ": ", offset + i);
364 for (j = 0; j < 16 && i + j < len; j++, p++) {
365 printf("%02x ", *p);
366 }
367 printf(" ");
368 for (j = 0; j < 16 && i + j < len; j++, s++) {
369 if (isalnum(*s)) {
370 printf("%c", *s);
371 } else {
372 printf(".");
373 }
374 }
375 printf("\n");
376 }
377}
378
379static void print_report(const char *op, struct timeval *t, int64_t offset,
dc38852a 380 int64_t count, int64_t total, int cnt, bool Cflag)
797ac58c
KW
381{
382 char s1[64], s2[64], ts[64];
383
384 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
385 if (!Cflag) {
386 cvtstr((double)total, s1, sizeof(s1));
387 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
9b0beaf3 388 printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n",
797ac58c
KW
389 op, total, count, offset);
390 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
391 s1, cnt, ts, s2, tdiv((double)cnt, *t));
392 } else {/* bytes,ops,time,bytes/sec,ops/sec */
9b0beaf3 393 printf("%"PRId64",%d,%s,%.3f,%.3f\n",
797ac58c
KW
394 total, cnt, ts,
395 tdiv((double)total, *t),
396 tdiv((double)cnt, *t));
397 }
398}
399
400/*
401 * Parse multiple length statements for vectored I/O, and construct an I/O
402 * vector matching it.
403 */
404static void *
4c7b7e9b 405create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
797ac58c
KW
406 int pattern)
407{
408 size_t *sizes = g_new0(size_t, nr_iov);
409 size_t count = 0;
410 void *buf = NULL;
411 void *p;
412 int i;
413
414 for (i = 0; i < nr_iov; i++) {
415 char *arg = argv[i];
416 int64_t len;
417
418 len = cvtnum(arg);
419 if (len < 0) {
a9ecfa00 420 print_cvtnum_err(len, arg);
797ac58c
KW
421 goto fail;
422 }
423
3026c468
AG
424 if (len > BDRV_REQUEST_MAX_BYTES) {
425 printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg,
426 (uint64_t)BDRV_REQUEST_MAX_BYTES);
427 goto fail;
428 }
429
430 if (count > BDRV_REQUEST_MAX_BYTES - len) {
431 printf("The total number of bytes exceed the maximum size %" PRIu64
432 "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES);
797ac58c
KW
433 goto fail;
434 }
435
797ac58c
KW
436 sizes[i] = len;
437 count += len;
438 }
439
440 qemu_iovec_init(qiov, nr_iov);
441
4c7b7e9b 442 buf = p = qemu_io_alloc(blk, count, pattern);
797ac58c
KW
443
444 for (i = 0; i < nr_iov; i++) {
445 qemu_iovec_add(qiov, p, sizes[i]);
446 p += sizes[i];
447 }
448
449fail:
450 g_free(sizes);
451 return buf;
452}
453
9b0beaf3 454static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
f5a5ca79 455 int64_t bytes, int64_t *total)
797ac58c 456{
f5a5ca79 457 if (bytes > INT_MAX) {
9b0beaf3
JS
458 return -ERANGE;
459 }
460
f5a5ca79 461 *total = blk_pread(blk, offset, (uint8_t *)buf, bytes);
797ac58c
KW
462 if (*total < 0) {
463 return *total;
464 }
465 return 1;
466}
467
9b0beaf3 468static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
f5a5ca79 469 int64_t bytes, int flags, int64_t *total)
797ac58c 470{
f5a5ca79 471 if (bytes > INT_MAX) {
9b0beaf3
JS
472 return -ERANGE;
473 }
474
f5a5ca79 475 *total = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
797ac58c
KW
476 if (*total < 0) {
477 return *total;
478 }
479 return 1;
480}
481
482typedef struct {
4c7b7e9b 483 BlockBackend *blk;
797ac58c 484 int64_t offset;
f5a5ca79 485 int64_t bytes;
9b0beaf3 486 int64_t *total;
770e0e0e 487 int flags;
797ac58c
KW
488 int ret;
489 bool done;
490} CoWriteZeroes;
491
d004bd52 492static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
797ac58c
KW
493{
494 CoWriteZeroes *data = opaque;
495
f5a5ca79 496 data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
d004bd52 497 data->flags);
797ac58c
KW
498 data->done = true;
499 if (data->ret < 0) {
500 *data->total = data->ret;
501 return;
502 }
503
f5a5ca79 504 *data->total = data->bytes;
797ac58c
KW
505}
506
d004bd52 507static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
f5a5ca79 508 int64_t bytes, int flags, int64_t *total)
797ac58c
KW
509{
510 Coroutine *co;
511 CoWriteZeroes data = {
4c7b7e9b 512 .blk = blk,
797ac58c 513 .offset = offset,
f5a5ca79 514 .bytes = bytes,
797ac58c 515 .total = total,
770e0e0e 516 .flags = flags,
797ac58c
KW
517 .done = false,
518 };
519
f5a5ca79 520 if (bytes > INT_MAX) {
9b0beaf3
JS
521 return -ERANGE;
522 }
523
0b8b8753 524 co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
324ec3e4 525 bdrv_coroutine_enter(blk_bs(blk), co);
797ac58c 526 while (!data.done) {
4c7b7e9b 527 aio_poll(blk_get_aio_context(blk), true);
797ac58c
KW
528 }
529 if (data.ret < 0) {
530 return data.ret;
531 } else {
532 return 1;
533 }
534}
535
4c7b7e9b 536static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
f5a5ca79 537 int64_t bytes, int64_t *total)
797ac58c
KW
538{
539 int ret;
540
41ae31e3 541 if (bytes > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3
JS
542 return -ERANGE;
543 }
544
f5a5ca79 545 ret = blk_pwrite_compressed(blk, offset, buf, bytes);
797ac58c
KW
546 if (ret < 0) {
547 return ret;
548 }
f5a5ca79 549 *total = bytes;
797ac58c
KW
550 return 1;
551}
552
4c7b7e9b 553static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset,
9b0beaf3 554 int64_t count, int64_t *total)
797ac58c 555{
9b0beaf3
JS
556 if (count > INT_MAX) {
557 return -ERANGE;
558 }
559
4c7b7e9b 560 *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count);
797ac58c
KW
561 if (*total < 0) {
562 return *total;
563 }
564 return 1;
565}
566
4c7b7e9b 567static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset,
9b0beaf3 568 int64_t count, int64_t *total)
797ac58c 569{
9b0beaf3
JS
570 if (count > INT_MAX) {
571 return -ERANGE;
572 }
573
4c7b7e9b 574 *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count);
797ac58c
KW
575 if (*total < 0) {
576 return *total;
577 }
578 return 1;
579}
580
581#define NOT_DONE 0x7fffffff
582static void aio_rw_done(void *opaque, int ret)
583{
584 *(int *)opaque = ret;
585}
586
4c7b7e9b 587static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
797ac58c
KW
588 int64_t offset, int *total)
589{
590 int async_ret = NOT_DONE;
591
7b3f9712 592 blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret);
797ac58c
KW
593 while (async_ret == NOT_DONE) {
594 main_loop_wait(false);
595 }
596
597 *total = qiov->size;
598 return async_ret < 0 ? async_ret : 1;
599}
600
4c7b7e9b 601static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
770e0e0e 602 int64_t offset, int flags, int *total)
797ac58c
KW
603{
604 int async_ret = NOT_DONE;
605
770e0e0e 606 blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret);
797ac58c
KW
607 while (async_ret == NOT_DONE) {
608 main_loop_wait(false);
609 }
610
611 *total = qiov->size;
612 return async_ret < 0 ? async_ret : 1;
613}
614
797ac58c
KW
615static void read_help(void)
616{
617 printf(
618"\n"
619" reads a range of bytes from the given offset\n"
620"\n"
621" Example:\n"
622" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
623"\n"
624" Reads a segment of the currently open file, optionally dumping it to the\n"
625" standard output stream (with -v option) for subsequent inspection.\n"
626" -b, -- read from the VM state rather than the virtual disk\n"
627" -C, -- report statistics in a machine parsable format\n"
628" -l, -- length for pattern verification (only with -P)\n"
093ea232 629" -p, -- ignored for backwards compatibility\n"
797ac58c
KW
630" -P, -- use a pattern to verify read data\n"
631" -q, -- quiet mode, do not show I/O statistics\n"
632" -s, -- start offset for pattern verification (only with -P)\n"
633" -v, -- dump buffer to standard output\n"
634"\n");
635}
636
b32d7a39 637static int read_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
638
639static const cmdinfo_t read_cmd = {
640 .name = "read",
641 .altname = "r",
642 .cfunc = read_f,
643 .argmin = 2,
644 .argmax = -1,
093ea232 645 .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len",
797ac58c
KW
646 .oneline = "reads a number of bytes at a specified offset",
647 .help = read_help,
648};
649
b32d7a39 650static int read_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
651{
652 struct timeval t1, t2;
093ea232 653 bool Cflag = false, qflag = false, vflag = false;
dc38852a 654 bool Pflag = false, sflag = false, lflag = false, bflag = false;
b32d7a39 655 int c, cnt, ret;
797ac58c
KW
656 char *buf;
657 int64_t offset;
9b0beaf3 658 int64_t count;
797ac58c 659 /* Some compilers get confused and warn if this is not initialized. */
9b0beaf3
JS
660 int64_t total = 0;
661 int pattern = 0;
662 int64_t pattern_offset = 0, pattern_count = 0;
797ac58c 663
b062ad86 664 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
797ac58c
KW
665 switch (c) {
666 case 'b':
dc38852a 667 bflag = true;
797ac58c
KW
668 break;
669 case 'C':
dc38852a 670 Cflag = true;
797ac58c
KW
671 break;
672 case 'l':
dc38852a 673 lflag = true;
797ac58c
KW
674 pattern_count = cvtnum(optarg);
675 if (pattern_count < 0) {
a9ecfa00 676 print_cvtnum_err(pattern_count, optarg);
b32d7a39 677 return pattern_count;
797ac58c
KW
678 }
679 break;
680 case 'p':
093ea232 681 /* Ignored for backwards compatibility */
797ac58c
KW
682 break;
683 case 'P':
dc38852a 684 Pflag = true;
797ac58c
KW
685 pattern = parse_pattern(optarg);
686 if (pattern < 0) {
b32d7a39 687 return -EINVAL;
797ac58c
KW
688 }
689 break;
690 case 'q':
dc38852a 691 qflag = true;
797ac58c
KW
692 break;
693 case 's':
dc38852a 694 sflag = true;
797ac58c
KW
695 pattern_offset = cvtnum(optarg);
696 if (pattern_offset < 0) {
a9ecfa00 697 print_cvtnum_err(pattern_offset, optarg);
b32d7a39 698 return pattern_offset;
797ac58c
KW
699 }
700 break;
701 case 'v':
dc38852a 702 vflag = true;
797ac58c
KW
703 break;
704 default:
b444d0e9 705 qemuio_command_usage(&read_cmd);
b32d7a39 706 return -EINVAL;
797ac58c
KW
707 }
708 }
709
710 if (optind != argc - 2) {
b444d0e9 711 qemuio_command_usage(&read_cmd);
b32d7a39 712 return -EINVAL;
797ac58c
KW
713 }
714
797ac58c
KW
715 offset = cvtnum(argv[optind]);
716 if (offset < 0) {
a9ecfa00 717 print_cvtnum_err(offset, argv[optind]);
b32d7a39 718 return offset;
797ac58c
KW
719 }
720
721 optind++;
722 count = cvtnum(argv[optind]);
723 if (count < 0) {
a9ecfa00 724 print_cvtnum_err(count, argv[optind]);
b32d7a39 725 return count;
3026c468 726 } else if (count > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 727 printf("length cannot exceed %" PRIu64 ", given %s\n",
3026c468 728 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 729 return -EINVAL;
797ac58c
KW
730 }
731
732 if (!Pflag && (lflag || sflag)) {
b444d0e9 733 qemuio_command_usage(&read_cmd);
b32d7a39 734 return -EINVAL;
797ac58c
KW
735 }
736
737 if (!lflag) {
738 pattern_count = count - pattern_offset;
739 }
740
741 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
742 printf("pattern verification range exceeds end of read data\n");
b32d7a39 743 return -EINVAL;
797ac58c
KW
744 }
745
093ea232 746 if (bflag) {
1bce6b4c
EB
747 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
748 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
797ac58c 749 offset);
b32d7a39 750 return -EINVAL;
797ac58c 751 }
1bce6b4c
EB
752 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
753 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
797ac58c 754 count);
b32d7a39 755 return -EINVAL;
797ac58c
KW
756 }
757 }
758
4c7b7e9b 759 buf = qemu_io_alloc(blk, count, 0xab);
797ac58c
KW
760
761 gettimeofday(&t1, NULL);
7b3f9712 762 if (bflag) {
b32d7a39 763 ret = do_load_vmstate(blk, buf, offset, count, &total);
797ac58c 764 } else {
b32d7a39 765 ret = do_pread(blk, buf, offset, count, &total);
797ac58c
KW
766 }
767 gettimeofday(&t2, NULL);
768
b32d7a39
HR
769 if (ret < 0) {
770 printf("read failed: %s\n", strerror(-ret));
797ac58c
KW
771 goto out;
772 }
b32d7a39
HR
773 cnt = ret;
774
775 ret = 0;
797ac58c
KW
776
777 if (Pflag) {
778 void *cmp_buf = g_malloc(pattern_count);
779 memset(cmp_buf, pattern, pattern_count);
780 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
781 printf("Pattern verification failed at offset %"
9b0beaf3 782 PRId64 ", %"PRId64" bytes\n",
797ac58c 783 offset + pattern_offset, pattern_count);
b32d7a39 784 ret = -EINVAL;
797ac58c
KW
785 }
786 g_free(cmp_buf);
787 }
788
789 if (qflag) {
790 goto out;
791 }
792
793 if (vflag) {
794 dump_buffer(buf, offset, count);
795 }
796
797 /* Finally, report back -- -C gives a parsable format */
798 t2 = tsub(t2, t1);
799 print_report("read", &t2, offset, count, total, cnt, Cflag);
800
801out:
802 qemu_io_free(buf);
b32d7a39 803 return ret;
797ac58c
KW
804}
805
806static void readv_help(void)
807{
808 printf(
809"\n"
810" reads a range of bytes from the given offset into multiple buffers\n"
811"\n"
812" Example:\n"
813" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
814"\n"
815" Reads a segment of the currently open file, optionally dumping it to the\n"
816" standard output stream (with -v option) for subsequent inspection.\n"
817" Uses multiple iovec buffers if more than one byte range is specified.\n"
818" -C, -- report statistics in a machine parsable format\n"
819" -P, -- use a pattern to verify read data\n"
820" -v, -- dump buffer to standard output\n"
821" -q, -- quiet mode, do not show I/O statistics\n"
822"\n");
823}
824
b32d7a39 825static int readv_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
826
827static const cmdinfo_t readv_cmd = {
828 .name = "readv",
829 .cfunc = readv_f,
830 .argmin = 2,
831 .argmax = -1,
093ea232 832 .args = "[-Cqv] [-P pattern] off len [len..]",
797ac58c
KW
833 .oneline = "reads a number of bytes at a specified offset",
834 .help = readv_help,
835};
836
b32d7a39 837static int readv_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
838{
839 struct timeval t1, t2;
dc38852a 840 bool Cflag = false, qflag = false, vflag = false;
b32d7a39 841 int c, cnt, ret;
797ac58c
KW
842 char *buf;
843 int64_t offset;
844 /* Some compilers get confused and warn if this is not initialized. */
845 int total = 0;
846 int nr_iov;
847 QEMUIOVector qiov;
848 int pattern = 0;
dc38852a 849 bool Pflag = false;
797ac58c 850
b062ad86 851 while ((c = getopt(argc, argv, "CP:qv")) != -1) {
797ac58c
KW
852 switch (c) {
853 case 'C':
dc38852a 854 Cflag = true;
797ac58c
KW
855 break;
856 case 'P':
dc38852a 857 Pflag = true;
797ac58c
KW
858 pattern = parse_pattern(optarg);
859 if (pattern < 0) {
b32d7a39 860 return -EINVAL;
797ac58c
KW
861 }
862 break;
863 case 'q':
dc38852a 864 qflag = true;
797ac58c
KW
865 break;
866 case 'v':
dc38852a 867 vflag = true;
797ac58c
KW
868 break;
869 default:
b444d0e9 870 qemuio_command_usage(&readv_cmd);
b32d7a39 871 return -EINVAL;
797ac58c
KW
872 }
873 }
874
875 if (optind > argc - 2) {
b444d0e9 876 qemuio_command_usage(&readv_cmd);
b32d7a39 877 return -EINVAL;
797ac58c
KW
878 }
879
880
881 offset = cvtnum(argv[optind]);
882 if (offset < 0) {
a9ecfa00 883 print_cvtnum_err(offset, argv[optind]);
b32d7a39 884 return offset;
797ac58c
KW
885 }
886 optind++;
887
797ac58c 888 nr_iov = argc - optind;
4c7b7e9b 889 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
797ac58c 890 if (buf == NULL) {
b32d7a39 891 return -EINVAL;
797ac58c
KW
892 }
893
894 gettimeofday(&t1, NULL);
b32d7a39 895 ret = do_aio_readv(blk, &qiov, offset, &total);
797ac58c
KW
896 gettimeofday(&t2, NULL);
897
b32d7a39
HR
898 if (ret < 0) {
899 printf("readv failed: %s\n", strerror(-ret));
797ac58c
KW
900 goto out;
901 }
b32d7a39
HR
902 cnt = ret;
903
904 ret = 0;
797ac58c
KW
905
906 if (Pflag) {
907 void *cmp_buf = g_malloc(qiov.size);
908 memset(cmp_buf, pattern, qiov.size);
909 if (memcmp(buf, cmp_buf, qiov.size)) {
910 printf("Pattern verification failed at offset %"
cf67b692 911 PRId64 ", %zu bytes\n", offset, qiov.size);
b32d7a39 912 ret = -EINVAL;
797ac58c
KW
913 }
914 g_free(cmp_buf);
915 }
916
917 if (qflag) {
918 goto out;
919 }
920
921 if (vflag) {
922 dump_buffer(buf, offset, qiov.size);
923 }
924
925 /* Finally, report back -- -C gives a parsable format */
926 t2 = tsub(t2, t1);
927 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
928
929out:
930 qemu_iovec_destroy(&qiov);
931 qemu_io_free(buf);
b32d7a39 932 return ret;
797ac58c
KW
933}
934
935static void write_help(void)
936{
937 printf(
938"\n"
939" writes a range of bytes from the given offset\n"
940"\n"
941" Example:\n"
942" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
943"\n"
944" Writes into a segment of the currently open file, using a buffer\n"
945" filled with a set pattern (0xcdcdcdcd).\n"
946" -b, -- write to the VM state rather than the virtual disk\n"
4c7b7e9b 947" -c, -- write compressed data with blk_write_compressed\n"
770e0e0e 948" -f, -- use Force Unit Access semantics\n"
c6e3f520 949" -n, -- with -z, don't allow slow fallback\n"
093ea232 950" -p, -- ignored for backwards compatibility\n"
797ac58c
KW
951" -P, -- use different pattern to fill file\n"
952" -C, -- report statistics in a machine parsable format\n"
953" -q, -- quiet mode, do not show I/O statistics\n"
c2e001cc 954" -u, -- with -z, allow unmapping\n"
d004bd52 955" -z, -- write zeroes using blk_co_pwrite_zeroes\n"
797ac58c
KW
956"\n");
957}
958
b32d7a39 959static int write_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
960
961static const cmdinfo_t write_cmd = {
962 .name = "write",
963 .altname = "w",
964 .cfunc = write_f,
887354bd 965 .perm = BLK_PERM_WRITE,
797ac58c
KW
966 .argmin = 2,
967 .argmax = -1,
c6e3f520 968 .args = "[-bcCfnquz] [-P pattern] off len",
797ac58c
KW
969 .oneline = "writes a number of bytes at a specified offset",
970 .help = write_help,
971};
972
b32d7a39 973static int write_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
974{
975 struct timeval t1, t2;
093ea232 976 bool Cflag = false, qflag = false, bflag = false;
dc38852a 977 bool Pflag = false, zflag = false, cflag = false;
770e0e0e 978 int flags = 0;
b32d7a39 979 int c, cnt, ret;
797ac58c
KW
980 char *buf = NULL;
981 int64_t offset;
9b0beaf3 982 int64_t count;
797ac58c 983 /* Some compilers get confused and warn if this is not initialized. */
9b0beaf3 984 int64_t total = 0;
797ac58c
KW
985 int pattern = 0xcd;
986
c6e3f520 987 while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) {
797ac58c
KW
988 switch (c) {
989 case 'b':
dc38852a 990 bflag = true;
797ac58c
KW
991 break;
992 case 'c':
dc38852a 993 cflag = true;
797ac58c
KW
994 break;
995 case 'C':
dc38852a 996 Cflag = true;
797ac58c 997 break;
770e0e0e
EB
998 case 'f':
999 flags |= BDRV_REQ_FUA;
1000 break;
c6e3f520
KW
1001 case 'n':
1002 flags |= BDRV_REQ_NO_FALLBACK;
1003 break;
797ac58c 1004 case 'p':
093ea232 1005 /* Ignored for backwards compatibility */
797ac58c
KW
1006 break;
1007 case 'P':
dc38852a 1008 Pflag = true;
797ac58c
KW
1009 pattern = parse_pattern(optarg);
1010 if (pattern < 0) {
b32d7a39 1011 return -EINVAL;
797ac58c
KW
1012 }
1013 break;
1014 case 'q':
dc38852a 1015 qflag = true;
797ac58c 1016 break;
c2e001cc
EB
1017 case 'u':
1018 flags |= BDRV_REQ_MAY_UNMAP;
1019 break;
797ac58c 1020 case 'z':
dc38852a 1021 zflag = true;
797ac58c
KW
1022 break;
1023 default:
b444d0e9 1024 qemuio_command_usage(&write_cmd);
b32d7a39 1025 return -EINVAL;
797ac58c
KW
1026 }
1027 }
1028
1029 if (optind != argc - 2) {
b444d0e9 1030 qemuio_command_usage(&write_cmd);
b32d7a39 1031 return -EINVAL;
797ac58c
KW
1032 }
1033
093ea232
EB
1034 if (bflag && zflag) {
1035 printf("-b and -z cannot be specified at the same time\n");
b32d7a39 1036 return -EINVAL;
797ac58c
KW
1037 }
1038
770e0e0e
EB
1039 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
1040 printf("-f and -b or -c cannot be specified at the same time\n");
b32d7a39 1041 return -EINVAL;
770e0e0e
EB
1042 }
1043
c6e3f520
KW
1044 if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
1045 printf("-n requires -z to be specified\n");
1046 return -EINVAL;
1047 }
1048
c2e001cc
EB
1049 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
1050 printf("-u requires -z to be specified\n");
b32d7a39 1051 return -EINVAL;
c2e001cc
EB
1052 }
1053
797ac58c
KW
1054 if (zflag && Pflag) {
1055 printf("-z and -P cannot be specified at the same time\n");
b32d7a39 1056 return -EINVAL;
797ac58c
KW
1057 }
1058
1059 offset = cvtnum(argv[optind]);
1060 if (offset < 0) {
a9ecfa00 1061 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1062 return offset;
797ac58c
KW
1063 }
1064
1065 optind++;
1066 count = cvtnum(argv[optind]);
1067 if (count < 0) {
a9ecfa00 1068 print_cvtnum_err(count, argv[optind]);
b32d7a39 1069 return count;
3026c468 1070 } else if (count > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 1071 printf("length cannot exceed %" PRIu64 ", given %s\n",
3026c468 1072 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 1073 return -EINVAL;
797ac58c
KW
1074 }
1075
093ea232 1076 if (bflag || cflag) {
1bce6b4c
EB
1077 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
1078 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
797ac58c 1079 offset);
b32d7a39 1080 return -EINVAL;
797ac58c
KW
1081 }
1082
1bce6b4c
EB
1083 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
1084 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
797ac58c 1085 count);
b32d7a39 1086 return -EINVAL;
797ac58c
KW
1087 }
1088 }
1089
1090 if (!zflag) {
4c7b7e9b 1091 buf = qemu_io_alloc(blk, count, pattern);
797ac58c
KW
1092 }
1093
1094 gettimeofday(&t1, NULL);
7b3f9712 1095 if (bflag) {
b32d7a39 1096 ret = do_save_vmstate(blk, buf, offset, count, &total);
797ac58c 1097 } else if (zflag) {
b32d7a39 1098 ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
797ac58c 1099 } else if (cflag) {
b32d7a39 1100 ret = do_write_compressed(blk, buf, offset, count, &total);
797ac58c 1101 } else {
b32d7a39 1102 ret = do_pwrite(blk, buf, offset, count, flags, &total);
797ac58c
KW
1103 }
1104 gettimeofday(&t2, NULL);
1105
b32d7a39
HR
1106 if (ret < 0) {
1107 printf("write failed: %s\n", strerror(-ret));
797ac58c
KW
1108 goto out;
1109 }
b32d7a39
HR
1110 cnt = ret;
1111
1112 ret = 0;
797ac58c
KW
1113
1114 if (qflag) {
1115 goto out;
1116 }
1117
1118 /* Finally, report back -- -C gives a parsable format */
1119 t2 = tsub(t2, t1);
1120 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1121
1122out:
1123 if (!zflag) {
1124 qemu_io_free(buf);
1125 }
b32d7a39 1126 return ret;
797ac58c
KW
1127}
1128
1129static void
1130writev_help(void)
1131{
1132 printf(
1133"\n"
1134" writes a range of bytes from the given offset source from multiple buffers\n"
1135"\n"
1136" Example:\n"
6e6507c0 1137" 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
797ac58c
KW
1138"\n"
1139" Writes into a segment of the currently open file, using a buffer\n"
1140" filled with a set pattern (0xcdcdcdcd).\n"
1141" -P, -- use different pattern to fill file\n"
1142" -C, -- report statistics in a machine parsable format\n"
770e0e0e 1143" -f, -- use Force Unit Access semantics\n"
797ac58c
KW
1144" -q, -- quiet mode, do not show I/O statistics\n"
1145"\n");
1146}
1147
b32d7a39 1148static int writev_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1149
1150static const cmdinfo_t writev_cmd = {
1151 .name = "writev",
1152 .cfunc = writev_f,
887354bd 1153 .perm = BLK_PERM_WRITE,
797ac58c
KW
1154 .argmin = 2,
1155 .argmax = -1,
770e0e0e 1156 .args = "[-Cfq] [-P pattern] off len [len..]",
797ac58c
KW
1157 .oneline = "writes a number of bytes at a specified offset",
1158 .help = writev_help,
1159};
1160
b32d7a39 1161static int writev_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1162{
1163 struct timeval t1, t2;
dc38852a 1164 bool Cflag = false, qflag = false;
770e0e0e 1165 int flags = 0;
b32d7a39 1166 int c, cnt, ret;
797ac58c
KW
1167 char *buf;
1168 int64_t offset;
1169 /* Some compilers get confused and warn if this is not initialized. */
1170 int total = 0;
1171 int nr_iov;
1172 int pattern = 0xcd;
1173 QEMUIOVector qiov;
1174
4ca1d340 1175 while ((c = getopt(argc, argv, "CfqP:")) != -1) {
797ac58c
KW
1176 switch (c) {
1177 case 'C':
dc38852a 1178 Cflag = true;
797ac58c 1179 break;
770e0e0e
EB
1180 case 'f':
1181 flags |= BDRV_REQ_FUA;
1182 break;
797ac58c 1183 case 'q':
dc38852a 1184 qflag = true;
797ac58c
KW
1185 break;
1186 case 'P':
1187 pattern = parse_pattern(optarg);
1188 if (pattern < 0) {
b32d7a39 1189 return -EINVAL;
797ac58c
KW
1190 }
1191 break;
1192 default:
b444d0e9 1193 qemuio_command_usage(&writev_cmd);
b32d7a39 1194 return -EINVAL;
797ac58c
KW
1195 }
1196 }
1197
1198 if (optind > argc - 2) {
b444d0e9 1199 qemuio_command_usage(&writev_cmd);
b32d7a39 1200 return -EINVAL;
797ac58c
KW
1201 }
1202
1203 offset = cvtnum(argv[optind]);
1204 if (offset < 0) {
a9ecfa00 1205 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1206 return offset;
797ac58c
KW
1207 }
1208 optind++;
1209
797ac58c 1210 nr_iov = argc - optind;
4c7b7e9b 1211 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
797ac58c 1212 if (buf == NULL) {
b32d7a39 1213 return -EINVAL;
797ac58c
KW
1214 }
1215
1216 gettimeofday(&t1, NULL);
b32d7a39 1217 ret = do_aio_writev(blk, &qiov, offset, flags, &total);
797ac58c
KW
1218 gettimeofday(&t2, NULL);
1219
b32d7a39
HR
1220 if (ret < 0) {
1221 printf("writev failed: %s\n", strerror(-ret));
797ac58c
KW
1222 goto out;
1223 }
b32d7a39
HR
1224 cnt = ret;
1225
1226 ret = 0;
797ac58c
KW
1227
1228 if (qflag) {
1229 goto out;
1230 }
1231
1232 /* Finally, report back -- -C gives a parsable format */
1233 t2 = tsub(t2, t1);
1234 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1235out:
1236 qemu_iovec_destroy(&qiov);
1237 qemu_io_free(buf);
b32d7a39 1238 return ret;
797ac58c
KW
1239}
1240
797ac58c 1241struct aio_ctx {
4c7b7e9b 1242 BlockBackend *blk;
797ac58c
KW
1243 QEMUIOVector qiov;
1244 int64_t offset;
1245 char *buf;
dc38852a
EB
1246 bool qflag;
1247 bool vflag;
1248 bool Cflag;
1249 bool Pflag;
1250 bool zflag;
a91f9584 1251 BlockAcctCookie acct;
797ac58c
KW
1252 int pattern;
1253 struct timeval t1;
1254};
1255
1256static void aio_write_done(void *opaque, int ret)
1257{
1258 struct aio_ctx *ctx = opaque;
1259 struct timeval t2;
1260
1261 gettimeofday(&t2, NULL);
1262
1263
1264 if (ret < 0) {
1265 printf("aio_write failed: %s\n", strerror(-ret));
556c2b60 1266 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
797ac58c
KW
1267 goto out;
1268 }
1269
4c7b7e9b 1270 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
a91f9584 1271
797ac58c
KW
1272 if (ctx->qflag) {
1273 goto out;
1274 }
1275
1276 /* Finally, report back -- -C gives a parsable format */
1277 t2 = tsub(t2, ctx->t1);
1278 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1279 ctx->qiov.size, 1, ctx->Cflag);
1280out:
5ceb7765
KW
1281 if (!ctx->zflag) {
1282 qemu_io_free(ctx->buf);
1283 qemu_iovec_destroy(&ctx->qiov);
1284 }
797ac58c
KW
1285 g_free(ctx);
1286}
1287
1288static void aio_read_done(void *opaque, int ret)
1289{
1290 struct aio_ctx *ctx = opaque;
1291 struct timeval t2;
1292
1293 gettimeofday(&t2, NULL);
1294
1295 if (ret < 0) {
1296 printf("readv failed: %s\n", strerror(-ret));
556c2b60 1297 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
797ac58c
KW
1298 goto out;
1299 }
1300
1301 if (ctx->Pflag) {
1302 void *cmp_buf = g_malloc(ctx->qiov.size);
1303
1304 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1305 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1306 printf("Pattern verification failed at offset %"
cf67b692 1307 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
797ac58c
KW
1308 }
1309 g_free(cmp_buf);
1310 }
1311
4c7b7e9b 1312 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
a91f9584 1313
797ac58c
KW
1314 if (ctx->qflag) {
1315 goto out;
1316 }
1317
1318 if (ctx->vflag) {
1319 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1320 }
1321
1322 /* Finally, report back -- -C gives a parsable format */
1323 t2 = tsub(t2, ctx->t1);
1324 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1325 ctx->qiov.size, 1, ctx->Cflag);
1326out:
1327 qemu_io_free(ctx->buf);
1328 qemu_iovec_destroy(&ctx->qiov);
1329 g_free(ctx);
1330}
1331
1332static void aio_read_help(void)
1333{
1334 printf(
1335"\n"
1336" asynchronously reads a range of bytes from the given offset\n"
1337"\n"
1338" Example:\n"
1339" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1340"\n"
1341" Reads a segment of the currently open file, optionally dumping it to the\n"
1342" standard output stream (with -v option) for subsequent inspection.\n"
1343" The read is performed asynchronously and the aio_flush command must be\n"
1344" used to ensure all outstanding aio requests have been completed.\n"
b32d7a39
HR
1345" Note that due to its asynchronous nature, this command will be\n"
1346" considered successful once the request is submitted, independently\n"
1347" of potential I/O errors or pattern mismatches.\n"
797ac58c
KW
1348" -C, -- report statistics in a machine parsable format\n"
1349" -P, -- use a pattern to verify read data\n"
37546ff2 1350" -i, -- treat request as invalid, for exercising stats\n"
797ac58c
KW
1351" -v, -- dump buffer to standard output\n"
1352" -q, -- quiet mode, do not show I/O statistics\n"
1353"\n");
1354}
1355
b32d7a39 1356static int aio_read_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1357
1358static const cmdinfo_t aio_read_cmd = {
1359 .name = "aio_read",
1360 .cfunc = aio_read_f,
1361 .argmin = 2,
1362 .argmax = -1,
37546ff2 1363 .args = "[-Ciqv] [-P pattern] off len [len..]",
797ac58c
KW
1364 .oneline = "asynchronously reads a number of bytes",
1365 .help = aio_read_help,
1366};
1367
b32d7a39 1368static int aio_read_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1369{
1370 int nr_iov, c;
1371 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1372
4c7b7e9b 1373 ctx->blk = blk;
37546ff2 1374 while ((c = getopt(argc, argv, "CP:iqv")) != -1) {
797ac58c
KW
1375 switch (c) {
1376 case 'C':
dc38852a 1377 ctx->Cflag = true;
797ac58c
KW
1378 break;
1379 case 'P':
dc38852a 1380 ctx->Pflag = true;
797ac58c
KW
1381 ctx->pattern = parse_pattern(optarg);
1382 if (ctx->pattern < 0) {
1383 g_free(ctx);
b32d7a39 1384 return -EINVAL;
797ac58c
KW
1385 }
1386 break;
37546ff2
EB
1387 case 'i':
1388 printf("injecting invalid read request\n");
1389 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1390 g_free(ctx);
b32d7a39 1391 return 0;
797ac58c 1392 case 'q':
dc38852a 1393 ctx->qflag = true;
797ac58c
KW
1394 break;
1395 case 'v':
dc38852a 1396 ctx->vflag = true;
797ac58c
KW
1397 break;
1398 default:
1399 g_free(ctx);
b444d0e9 1400 qemuio_command_usage(&aio_read_cmd);
b32d7a39 1401 return -EINVAL;
797ac58c
KW
1402 }
1403 }
1404
1405 if (optind > argc - 2) {
1406 g_free(ctx);
b444d0e9 1407 qemuio_command_usage(&aio_read_cmd);
b32d7a39 1408 return -EINVAL;
797ac58c
KW
1409 }
1410
1411 ctx->offset = cvtnum(argv[optind]);
1412 if (ctx->offset < 0) {
b32d7a39
HR
1413 int ret = ctx->offset;
1414 print_cvtnum_err(ret, argv[optind]);
797ac58c 1415 g_free(ctx);
b32d7a39 1416 return ret;
797ac58c
KW
1417 }
1418 optind++;
1419
797ac58c 1420 nr_iov = argc - optind;
4c7b7e9b 1421 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
797ac58c 1422 if (ctx->buf == NULL) {
556c2b60 1423 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
797ac58c 1424 g_free(ctx);
b32d7a39 1425 return -EINVAL;
797ac58c
KW
1426 }
1427
1428 gettimeofday(&ctx->t1, NULL);
4c7b7e9b
HR
1429 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1430 BLOCK_ACCT_READ);
7b3f9712 1431 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
b32d7a39 1432 return 0;
797ac58c
KW
1433}
1434
1435static void aio_write_help(void)
1436{
1437 printf(
1438"\n"
1439" asynchronously writes a range of bytes from the given offset source\n"
1440" from multiple buffers\n"
1441"\n"
1442" Example:\n"
1443" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1444"\n"
1445" Writes into a segment of the currently open file, using a buffer\n"
1446" filled with a set pattern (0xcdcdcdcd).\n"
1447" The write is performed asynchronously and the aio_flush command must be\n"
1448" used to ensure all outstanding aio requests have been completed.\n"
b32d7a39
HR
1449" Note that due to its asynchronous nature, this command will be\n"
1450" considered successful once the request is submitted, independently\n"
1451" of potential I/O errors or pattern mismatches.\n"
797ac58c
KW
1452" -P, -- use different pattern to fill file\n"
1453" -C, -- report statistics in a machine parsable format\n"
770e0e0e 1454" -f, -- use Force Unit Access semantics\n"
37546ff2 1455" -i, -- treat request as invalid, for exercising stats\n"
797ac58c 1456" -q, -- quiet mode, do not show I/O statistics\n"
c2e001cc 1457" -u, -- with -z, allow unmapping\n"
d004bd52 1458" -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
797ac58c
KW
1459"\n");
1460}
1461
b32d7a39 1462static int aio_write_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1463
1464static const cmdinfo_t aio_write_cmd = {
1465 .name = "aio_write",
1466 .cfunc = aio_write_f,
887354bd 1467 .perm = BLK_PERM_WRITE,
797ac58c
KW
1468 .argmin = 2,
1469 .argmax = -1,
37546ff2 1470 .args = "[-Cfiquz] [-P pattern] off len [len..]",
797ac58c
KW
1471 .oneline = "asynchronously writes a number of bytes",
1472 .help = aio_write_help,
1473};
1474
b32d7a39 1475static int aio_write_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1476{
1477 int nr_iov, c;
1478 int pattern = 0xcd;
1479 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
770e0e0e 1480 int flags = 0;
797ac58c 1481
4c7b7e9b 1482 ctx->blk = blk;
37546ff2 1483 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
797ac58c
KW
1484 switch (c) {
1485 case 'C':
dc38852a 1486 ctx->Cflag = true;
797ac58c 1487 break;
770e0e0e
EB
1488 case 'f':
1489 flags |= BDRV_REQ_FUA;
1490 break;
797ac58c 1491 case 'q':
dc38852a 1492 ctx->qflag = true;
797ac58c 1493 break;
c2e001cc
EB
1494 case 'u':
1495 flags |= BDRV_REQ_MAY_UNMAP;
1496 break;
797ac58c
KW
1497 case 'P':
1498 pattern = parse_pattern(optarg);
1499 if (pattern < 0) {
1500 g_free(ctx);
b32d7a39 1501 return -EINVAL;
797ac58c
KW
1502 }
1503 break;
37546ff2
EB
1504 case 'i':
1505 printf("injecting invalid write request\n");
1506 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1507 g_free(ctx);
b32d7a39 1508 return 0;
5ceb7765 1509 case 'z':
dc38852a 1510 ctx->zflag = true;
5ceb7765 1511 break;
797ac58c
KW
1512 default:
1513 g_free(ctx);
b444d0e9 1514 qemuio_command_usage(&aio_write_cmd);
b32d7a39 1515 return -EINVAL;
797ac58c
KW
1516 }
1517 }
1518
1519 if (optind > argc - 2) {
1520 g_free(ctx);
b444d0e9 1521 qemuio_command_usage(&aio_write_cmd);
b32d7a39 1522 return -EINVAL;
797ac58c
KW
1523 }
1524
5ceb7765
KW
1525 if (ctx->zflag && optind != argc - 2) {
1526 printf("-z supports only a single length parameter\n");
1527 g_free(ctx);
b32d7a39 1528 return -EINVAL;
5ceb7765
KW
1529 }
1530
c2e001cc
EB
1531 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
1532 printf("-u requires -z to be specified\n");
4ca1d340 1533 g_free(ctx);
b32d7a39 1534 return -EINVAL;
c2e001cc
EB
1535 }
1536
5ceb7765
KW
1537 if (ctx->zflag && ctx->Pflag) {
1538 printf("-z and -P cannot be specified at the same time\n");
1539 g_free(ctx);
b32d7a39 1540 return -EINVAL;
5ceb7765
KW
1541 }
1542
797ac58c
KW
1543 ctx->offset = cvtnum(argv[optind]);
1544 if (ctx->offset < 0) {
b32d7a39
HR
1545 int ret = ctx->offset;
1546 print_cvtnum_err(ret, argv[optind]);
797ac58c 1547 g_free(ctx);
b32d7a39 1548 return ret;
797ac58c
KW
1549 }
1550 optind++;
1551
5ceb7765
KW
1552 if (ctx->zflag) {
1553 int64_t count = cvtnum(argv[optind]);
1554 if (count < 0) {
1555 print_cvtnum_err(count, argv[optind]);
0e01b76e 1556 g_free(ctx);
b32d7a39 1557 return count;
5ceb7765 1558 }
797ac58c 1559
5ceb7765 1560 ctx->qiov.size = count;
d004bd52
EB
1561 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done,
1562 ctx);
5ceb7765
KW
1563 } else {
1564 nr_iov = argc - optind;
1565 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
1566 pattern);
1567 if (ctx->buf == NULL) {
1568 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1569 g_free(ctx);
b32d7a39 1570 return -EINVAL;
5ceb7765
KW
1571 }
1572
1573 gettimeofday(&ctx->t1, NULL);
1574 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1575 BLOCK_ACCT_WRITE);
1576
770e0e0e
EB
1577 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
1578 ctx);
5ceb7765 1579 }
b32d7a39
HR
1580
1581 return 0;
797ac58c
KW
1582}
1583
b32d7a39 1584static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1585{
556c2b60
AG
1586 BlockAcctCookie cookie;
1587 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
4c7b7e9b 1588 blk_drain_all();
556c2b60 1589 block_acct_done(blk_get_stats(blk), &cookie);
b32d7a39 1590 return 0;
797ac58c
KW
1591}
1592
1593static const cmdinfo_t aio_flush_cmd = {
1594 .name = "aio_flush",
1595 .cfunc = aio_flush_f,
1596 .oneline = "completes all outstanding aio requests"
1597};
1598
b32d7a39 1599static int flush_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1600{
b32d7a39 1601 return blk_flush(blk);
797ac58c
KW
1602}
1603
1604static const cmdinfo_t flush_cmd = {
1605 .name = "flush",
1606 .altname = "f",
1607 .cfunc = flush_f,
1608 .oneline = "flush all in-core file state to disk",
1609};
1610
b32d7a39 1611static int truncate_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1612{
ed3d2ec9 1613 Error *local_err = NULL;
797ac58c
KW
1614 int64_t offset;
1615 int ret;
1616
1617 offset = cvtnum(argv[1]);
1618 if (offset < 0) {
a9ecfa00 1619 print_cvtnum_err(offset, argv[1]);
b32d7a39 1620 return offset;
797ac58c
KW
1621 }
1622
3a691c50 1623 ret = blk_truncate(blk, offset, PREALLOC_MODE_OFF, &local_err);
797ac58c 1624 if (ret < 0) {
ed3d2ec9 1625 error_report_err(local_err);
b32d7a39 1626 return ret;
797ac58c 1627 }
b32d7a39
HR
1628
1629 return 0;
797ac58c
KW
1630}
1631
1632static const cmdinfo_t truncate_cmd = {
1633 .name = "truncate",
1634 .altname = "t",
1635 .cfunc = truncate_f,
887354bd 1636 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
797ac58c
KW
1637 .argmin = 1,
1638 .argmax = 1,
1639 .args = "off",
1640 .oneline = "truncates the current file at the given offset",
1641};
1642
b32d7a39 1643static int length_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1644{
1645 int64_t size;
1646 char s1[64];
1647
4c7b7e9b 1648 size = blk_getlength(blk);
797ac58c
KW
1649 if (size < 0) {
1650 printf("getlength: %s\n", strerror(-size));
b32d7a39 1651 return size;
797ac58c
KW
1652 }
1653
1654 cvtstr(size, s1, sizeof(s1));
1655 printf("%s\n", s1);
b32d7a39 1656 return 0;
797ac58c
KW
1657}
1658
1659
1660static const cmdinfo_t length_cmd = {
1661 .name = "length",
1662 .altname = "l",
1663 .cfunc = length_f,
1664 .oneline = "gets the length of the current file",
1665};
1666
1667
b32d7a39 1668static int info_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1669{
4c7b7e9b 1670 BlockDriverState *bs = blk_bs(blk);
797ac58c 1671 BlockDriverInfo bdi;
a8d8ecb7 1672 ImageInfoSpecific *spec_info;
1bf6e9ca 1673 Error *local_err = NULL;
797ac58c
KW
1674 char s1[64], s2[64];
1675 int ret;
1676
1677 if (bs->drv && bs->drv->format_name) {
1678 printf("format name: %s\n", bs->drv->format_name);
1679 }
1680 if (bs->drv && bs->drv->protocol_name) {
1681 printf("format name: %s\n", bs->drv->protocol_name);
1682 }
1683
1684 ret = bdrv_get_info(bs, &bdi);
1685 if (ret) {
b32d7a39 1686 return ret;
797ac58c
KW
1687 }
1688
1689 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1690 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1691
1692 printf("cluster size: %s\n", s1);
1693 printf("vm state offset: %s\n", s2);
1694
1bf6e9ca
AS
1695 spec_info = bdrv_get_specific_info(bs, &local_err);
1696 if (local_err) {
1697 error_report_err(local_err);
1698 return -EIO;
1699 }
a8d8ecb7
HR
1700 if (spec_info) {
1701 printf("Format specific information:\n");
e1ce7d74 1702 bdrv_image_info_specific_dump(spec_info);
a8d8ecb7
HR
1703 qapi_free_ImageInfoSpecific(spec_info);
1704 }
b32d7a39
HR
1705
1706 return 0;
797ac58c
KW
1707}
1708
1709
1710
1711static const cmdinfo_t info_cmd = {
1712 .name = "info",
1713 .altname = "i",
1714 .cfunc = info_f,
1715 .oneline = "prints information about the current file",
1716};
1717
1718static void discard_help(void)
1719{
1720 printf(
1721"\n"
1722" discards a range of bytes from the given offset\n"
1723"\n"
1724" Example:\n"
1725" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1726"\n"
1727" Discards a segment of the currently open file.\n"
1728" -C, -- report statistics in a machine parsable format\n"
1729" -q, -- quiet mode, do not show I/O statistics\n"
1730"\n");
1731}
1732
b32d7a39 1733static int discard_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1734
1735static const cmdinfo_t discard_cmd = {
1736 .name = "discard",
1737 .altname = "d",
1738 .cfunc = discard_f,
887354bd 1739 .perm = BLK_PERM_WRITE,
797ac58c
KW
1740 .argmin = 2,
1741 .argmax = -1,
1742 .args = "[-Cq] off len",
1743 .oneline = "discards a number of bytes at a specified offset",
1744 .help = discard_help,
1745};
1746
b32d7a39 1747static int discard_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1748{
1749 struct timeval t1, t2;
dc38852a 1750 bool Cflag = false, qflag = false;
797ac58c 1751 int c, ret;
f5a5ca79 1752 int64_t offset, bytes;
797ac58c 1753
b062ad86 1754 while ((c = getopt(argc, argv, "Cq")) != -1) {
797ac58c
KW
1755 switch (c) {
1756 case 'C':
dc38852a 1757 Cflag = true;
797ac58c
KW
1758 break;
1759 case 'q':
dc38852a 1760 qflag = true;
797ac58c
KW
1761 break;
1762 default:
b444d0e9 1763 qemuio_command_usage(&discard_cmd);
b32d7a39 1764 return -EINVAL;
797ac58c
KW
1765 }
1766 }
1767
1768 if (optind != argc - 2) {
b444d0e9 1769 qemuio_command_usage(&discard_cmd);
b32d7a39 1770 return -EINVAL;
797ac58c
KW
1771 }
1772
1773 offset = cvtnum(argv[optind]);
1774 if (offset < 0) {
a9ecfa00 1775 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1776 return offset;
797ac58c
KW
1777 }
1778
1779 optind++;
f5a5ca79
MP
1780 bytes = cvtnum(argv[optind]);
1781 if (bytes < 0) {
1782 print_cvtnum_err(bytes, argv[optind]);
b32d7a39 1783 return bytes;
41ae31e3 1784 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 1785 printf("length cannot exceed %"PRIu64", given %s\n",
41ae31e3 1786 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 1787 return -EINVAL;
797ac58c
KW
1788 }
1789
1790 gettimeofday(&t1, NULL);
f5a5ca79 1791 ret = blk_pdiscard(blk, offset, bytes);
797ac58c
KW
1792 gettimeofday(&t2, NULL);
1793
1794 if (ret < 0) {
1795 printf("discard failed: %s\n", strerror(-ret));
b32d7a39 1796 return ret;
797ac58c
KW
1797 }
1798
1799 /* Finally, report back -- -C gives a parsable format */
1800 if (!qflag) {
1801 t2 = tsub(t2, t1);
f5a5ca79 1802 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
797ac58c 1803 }
b32d7a39
HR
1804
1805 return 0;
797ac58c
KW
1806}
1807
b32d7a39 1808static int alloc_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1809{
4c7b7e9b 1810 BlockDriverState *bs = blk_bs(blk);
d6a644bb 1811 int64_t offset, start, remaining, count;
797ac58c 1812 char s1[64];
d6a644bb
EB
1813 int ret;
1814 int64_t num, sum_alloc;
797ac58c 1815
d6a644bb 1816 start = offset = cvtnum(argv[1]);
797ac58c 1817 if (offset < 0) {
a9ecfa00 1818 print_cvtnum_err(offset, argv[1]);
b32d7a39 1819 return offset;
797ac58c
KW
1820 }
1821
1822 if (argc == 3) {
4401fdc7
EB
1823 count = cvtnum(argv[2]);
1824 if (count < 0) {
1825 print_cvtnum_err(count, argv[2]);
b32d7a39 1826 return count;
797ac58c
KW
1827 }
1828 } else {
4401fdc7
EB
1829 count = BDRV_SECTOR_SIZE;
1830 }
797ac58c 1831
d6a644bb 1832 remaining = count;
797ac58c 1833 sum_alloc = 0;
797ac58c 1834 while (remaining) {
d6a644bb 1835 ret = bdrv_is_allocated(bs, offset, remaining, &num);
d663640c
PB
1836 if (ret < 0) {
1837 printf("is_allocated failed: %s\n", strerror(-ret));
b32d7a39 1838 return ret;
d663640c 1839 }
d6a644bb 1840 offset += num;
797ac58c
KW
1841 remaining -= num;
1842 if (ret) {
1843 sum_alloc += num;
1844 }
1845 if (num == 0) {
d6a644bb 1846 count -= remaining;
797ac58c
KW
1847 remaining = 0;
1848 }
1849 }
1850
d6a644bb 1851 cvtstr(start, s1, sizeof(s1));
797ac58c 1852
4401fdc7 1853 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
d6a644bb 1854 sum_alloc, count, s1);
b32d7a39 1855 return 0;
797ac58c
KW
1856}
1857
1858static const cmdinfo_t alloc_cmd = {
1859 .name = "alloc",
1860 .altname = "a",
1861 .argmin = 1,
1862 .argmax = 2,
1863 .cfunc = alloc_f,
4401fdc7
EB
1864 .args = "offset [count]",
1865 .oneline = "checks if offset is allocated in the file",
797ac58c
KW
1866};
1867
1868
d6a644bb
EB
1869static int map_is_allocated(BlockDriverState *bs, int64_t offset,
1870 int64_t bytes, int64_t *pnum)
797ac58c 1871{
d6a644bb
EB
1872 int64_t num;
1873 int num_checked;
797ac58c
KW
1874 int ret, firstret;
1875
d6a644bb
EB
1876 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1877 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
797ac58c
KW
1878 if (ret < 0) {
1879 return ret;
1880 }
1881
1882 firstret = ret;
1883 *pnum = num;
1884
d6a644bb
EB
1885 while (bytes > 0 && ret == firstret) {
1886 offset += num;
1887 bytes -= num;
797ac58c 1888
d6a644bb
EB
1889 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1890 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
4b25bbc4 1891 if (ret == firstret && num) {
797ac58c
KW
1892 *pnum += num;
1893 } else {
1894 break;
1895 }
1896 }
1897
1898 return firstret;
1899}
1900
b32d7a39 1901static int map_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1902{
d6a644bb 1903 int64_t offset, bytes;
6f3c90af 1904 char s1[64], s2[64];
797ac58c
KW
1905 int64_t num;
1906 int ret;
1907 const char *retstr;
1908
1909 offset = 0;
d6a644bb
EB
1910 bytes = blk_getlength(blk);
1911 if (bytes < 0) {
1912 error_report("Failed to query image length: %s", strerror(-bytes));
b32d7a39 1913 return bytes;
4c7b7e9b
HR
1914 }
1915
d6a644bb
EB
1916 while (bytes) {
1917 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
797ac58c
KW
1918 if (ret < 0) {
1919 error_report("Failed to get allocation status: %s", strerror(-ret));
b32d7a39 1920 return ret;
4b25bbc4
HR
1921 } else if (!num) {
1922 error_report("Unexpected end of image");
b32d7a39 1923 return -EIO;
797ac58c
KW
1924 }
1925
1926 retstr = ret ? " allocated" : "not allocated";
d6a644bb
EB
1927 cvtstr(num, s1, sizeof(s1));
1928 cvtstr(offset, s2, sizeof(s2));
6f3c90af 1929 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
d6a644bb 1930 s1, num, retstr, s2, offset);
797ac58c
KW
1931
1932 offset += num;
d6a644bb
EB
1933 bytes -= num;
1934 }
b32d7a39
HR
1935
1936 return 0;
797ac58c
KW
1937}
1938
1939static const cmdinfo_t map_cmd = {
1940 .name = "map",
1941 .argmin = 0,
1942 .argmax = 0,
1943 .cfunc = map_f,
1944 .args = "",
1945 .oneline = "prints the allocated areas of a file",
1946};
1947
5bbd2e59
KW
1948static void reopen_help(void)
1949{
1950 printf(
1951"\n"
1952" Changes the open options of an already opened image\n"
1953"\n"
1954" Example:\n"
1955" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
1956"\n"
1957" -r, -- Reopen the image read-only\n"
ea92203c 1958" -w, -- Reopen the image read-write\n"
5bbd2e59
KW
1959" -c, -- Change the cache mode to the given value\n"
1960" -o, -- Changes block driver options (cf. 'open' command)\n"
1961"\n");
1962}
1963
b32d7a39 1964static int reopen_f(BlockBackend *blk, int argc, char **argv);
5bbd2e59
KW
1965
1966static QemuOptsList reopen_opts = {
1967 .name = "reopen",
1968 .merge_lists = true,
1969 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
1970 .desc = {
1971 /* no elements => accept any params */
1972 { /* end of list */ }
1973 },
1974};
1975
1976static const cmdinfo_t reopen_cmd = {
1977 .name = "reopen",
1978 .argmin = 0,
1979 .argmax = -1,
1980 .cfunc = reopen_f,
ea92203c 1981 .args = "[(-r|-w)] [-c cache] [-o options]",
5bbd2e59
KW
1982 .oneline = "reopens an image with new options",
1983 .help = reopen_help,
1984};
1985
b32d7a39 1986static int reopen_f(BlockBackend *blk, int argc, char **argv)
5bbd2e59
KW
1987{
1988 BlockDriverState *bs = blk_bs(blk);
1989 QemuOpts *qopts;
1990 QDict *opts;
1991 int c;
1992 int flags = bs->open_flags;
19dbecdc 1993 bool writethrough = !blk_enable_write_cache(blk);
ea92203c 1994 bool has_rw_option = false;
dc900c35 1995 bool has_cache_option = false;
5bbd2e59
KW
1996
1997 BlockReopenQueue *brq;
1998 Error *local_err = NULL;
1999
ea92203c 2000 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
5bbd2e59
KW
2001 switch (c) {
2002 case 'c':
19dbecdc 2003 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
5bbd2e59 2004 error_report("Invalid cache option: %s", optarg);
b32d7a39 2005 return -EINVAL;
5bbd2e59 2006 }
dc900c35 2007 has_cache_option = true;
5bbd2e59
KW
2008 break;
2009 case 'o':
2010 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2011 qemu_opts_reset(&reopen_opts);
b32d7a39 2012 return -EINVAL;
5bbd2e59
KW
2013 }
2014 break;
2015 case 'r':
ea92203c
KW
2016 if (has_rw_option) {
2017 error_report("Only one -r/-w option may be given");
b32d7a39 2018 return -EINVAL;
ea92203c 2019 }
5bbd2e59 2020 flags &= ~BDRV_O_RDWR;
ea92203c
KW
2021 has_rw_option = true;
2022 break;
2023 case 'w':
2024 if (has_rw_option) {
2025 error_report("Only one -r/-w option may be given");
b32d7a39 2026 return -EINVAL;
ea92203c
KW
2027 }
2028 flags |= BDRV_O_RDWR;
2029 has_rw_option = true;
5bbd2e59
KW
2030 break;
2031 default:
2032 qemu_opts_reset(&reopen_opts);
b444d0e9 2033 qemuio_command_usage(&reopen_cmd);
b32d7a39 2034 return -EINVAL;
5bbd2e59
KW
2035 }
2036 }
2037
2038 if (optind != argc) {
2039 qemu_opts_reset(&reopen_opts);
b444d0e9 2040 qemuio_command_usage(&reopen_cmd);
b32d7a39 2041 return -EINVAL;
5bbd2e59
KW
2042 }
2043
a8003ec4 2044 if (!writethrough != blk_enable_write_cache(blk) &&
19dbecdc
KW
2045 blk_get_attached_dev(blk))
2046 {
2047 error_report("Cannot change cache.writeback: Device attached");
2048 qemu_opts_reset(&reopen_opts);
b32d7a39 2049 return -EBUSY;
19dbecdc
KW
2050 }
2051
f3adefb2
KW
2052 if (!(flags & BDRV_O_RDWR)) {
2053 uint64_t orig_perm, orig_shared_perm;
2054
2055 bdrv_drain(bs);
2056
2057 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2058 blk_set_perm(blk,
2059 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2060 orig_shared_perm,
2061 &error_abort);
2062 }
2063
5bbd2e59 2064 qopts = qemu_opts_find(&reopen_opts, NULL);
dc900c35 2065 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
5bbd2e59
KW
2066 qemu_opts_reset(&reopen_opts);
2067
dc900c35
AG
2068 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2069 if (has_rw_option) {
2070 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2071 qobject_unref(opts);
2072 return -EINVAL;
2073 }
2074 } else {
2075 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2076 }
2077
2078 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2079 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2080 if (has_cache_option) {
2081 error_report("Cannot set both -c and the cache options");
2082 qobject_unref(opts);
2083 return -EINVAL;
2084 }
2085 } else {
2086 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2087 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2088 }
2089
1a63a907 2090 bdrv_subtree_drained_begin(bs);
077e8e20 2091 brq = bdrv_reopen_queue(NULL, bs, opts, true);
5019aece 2092 bdrv_reopen_multiple(brq, &local_err);
1a63a907
KW
2093 bdrv_subtree_drained_end(bs);
2094
5bbd2e59
KW
2095 if (local_err) {
2096 error_report_err(local_err);
b32d7a39 2097 return -EINVAL;
5bbd2e59 2098 }
b32d7a39
HR
2099
2100 blk_set_enable_write_cache(blk, !writethrough);
2101 return 0;
5bbd2e59
KW
2102}
2103
b32d7a39 2104static int break_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2105{
2106 int ret;
2107
4c7b7e9b 2108 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
797ac58c
KW
2109 if (ret < 0) {
2110 printf("Could not set breakpoint: %s\n", strerror(-ret));
b32d7a39 2111 return ret;
797ac58c 2112 }
b32d7a39
HR
2113
2114 return 0;
797ac58c
KW
2115}
2116
b32d7a39 2117static int remove_break_f(BlockBackend *blk, int argc, char **argv)
4cc70e93
FZ
2118{
2119 int ret;
2120
4c7b7e9b 2121 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
4cc70e93
FZ
2122 if (ret < 0) {
2123 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
b32d7a39 2124 return ret;
4cc70e93 2125 }
b32d7a39
HR
2126
2127 return 0;
4cc70e93
FZ
2128}
2129
797ac58c
KW
2130static const cmdinfo_t break_cmd = {
2131 .name = "break",
2132 .argmin = 2,
2133 .argmax = 2,
2134 .cfunc = break_f,
2135 .args = "event tag",
2136 .oneline = "sets a breakpoint on event and tags the stopped "
2137 "request as tag",
2138};
2139
4cc70e93
FZ
2140static const cmdinfo_t remove_break_cmd = {
2141 .name = "remove_break",
2142 .argmin = 1,
2143 .argmax = 1,
2144 .cfunc = remove_break_f,
2145 .args = "tag",
2146 .oneline = "remove a breakpoint by tag",
2147};
2148
b32d7a39 2149static int resume_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2150{
2151 int ret;
2152
4c7b7e9b 2153 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
797ac58c
KW
2154 if (ret < 0) {
2155 printf("Could not resume request: %s\n", strerror(-ret));
b32d7a39 2156 return ret;
797ac58c 2157 }
b32d7a39
HR
2158
2159 return 0;
797ac58c
KW
2160}
2161
2162static const cmdinfo_t resume_cmd = {
2163 .name = "resume",
2164 .argmin = 1,
2165 .argmax = 1,
2166 .cfunc = resume_f,
2167 .args = "tag",
2168 .oneline = "resumes the request tagged as tag",
2169};
2170
b32d7a39 2171static int wait_break_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2172{
4c7b7e9b
HR
2173 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2174 aio_poll(blk_get_aio_context(blk), true);
797ac58c 2175 }
b32d7a39 2176 return 0;
797ac58c
KW
2177}
2178
2179static const cmdinfo_t wait_break_cmd = {
2180 .name = "wait_break",
2181 .argmin = 1,
2182 .argmax = 1,
2183 .cfunc = wait_break_f,
2184 .args = "tag",
2185 .oneline = "waits for the suspension of a request",
2186};
2187
b32d7a39 2188static int abort_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2189{
2190 abort();
2191}
2192
2193static const cmdinfo_t abort_cmd = {
2194 .name = "abort",
2195 .cfunc = abort_f,
2196 .flags = CMD_NOFILE_OK,
2197 .oneline = "simulate a program crash using abort(3)",
2198};
2199
0e82dc7b
HR
2200static void sigraise_help(void)
2201{
2202 printf(
2203"\n"
2204" raises the given signal\n"
2205"\n"
2206" Example:\n"
2207" 'sigraise %i' - raises SIGTERM\n"
2208"\n"
2209" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2210" given to sigraise.\n"
2211"\n", SIGTERM);
2212}
2213
b32d7a39 2214static int sigraise_f(BlockBackend *blk, int argc, char **argv);
0e82dc7b
HR
2215
2216static const cmdinfo_t sigraise_cmd = {
2217 .name = "sigraise",
2218 .cfunc = sigraise_f,
2219 .argmin = 1,
2220 .argmax = 1,
2221 .flags = CMD_NOFILE_OK,
2222 .args = "signal",
2223 .oneline = "raises a signal",
2224 .help = sigraise_help,
2225};
2226
b32d7a39 2227static int sigraise_f(BlockBackend *blk, int argc, char **argv)
0e82dc7b 2228{
9b0beaf3 2229 int64_t sig = cvtnum(argv[1]);
0e82dc7b 2230 if (sig < 0) {
a9ecfa00 2231 print_cvtnum_err(sig, argv[1]);
b32d7a39 2232 return sig;
9b0beaf3
JS
2233 } else if (sig > NSIG) {
2234 printf("signal argument '%s' is too large to be a valid signal\n",
2235 argv[1]);
b32d7a39 2236 return -EINVAL;
0e82dc7b
HR
2237 }
2238
2239 /* Using raise() to kill this process does not necessarily flush all open
2240 * streams. At least stdout and stderr (although the latter should be
2241 * non-buffered anyway) should be flushed, though. */
2242 fflush(stdout);
2243 fflush(stderr);
2244
2245 raise(sig);
b32d7a39
HR
2246
2247 return 0;
0e82dc7b
HR
2248}
2249
cd33d02a
KW
2250static void sleep_cb(void *opaque)
2251{
2252 bool *expired = opaque;
2253 *expired = true;
2254}
2255
b32d7a39 2256static int sleep_f(BlockBackend *blk, int argc, char **argv)
cd33d02a
KW
2257{
2258 char *endptr;
2259 long ms;
2260 struct QEMUTimer *timer;
2261 bool expired = false;
2262
2263 ms = strtol(argv[1], &endptr, 0);
2264 if (ms < 0 || *endptr != '\0') {
2265 printf("%s is not a valid number\n", argv[1]);
b32d7a39 2266 return -EINVAL;
cd33d02a
KW
2267 }
2268
2269 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2270 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2271
2272 while (!expired) {
2273 main_loop_wait(false);
2274 }
2275
2276 timer_free(timer);
b32d7a39 2277 return 0;
cd33d02a
KW
2278}
2279
2280static const cmdinfo_t sleep_cmd = {
2281 .name = "sleep",
2282 .argmin = 1,
2283 .argmax = 1,
2284 .cfunc = sleep_f,
2285 .flags = CMD_NOFILE_OK,
2286 .oneline = "waits for the given value in milliseconds",
2287};
2288
f18a834a
KW
2289static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2290{
2291 if (cmd) {
2292 printf("%s ", cmd);
2293 } else {
2294 printf("%s ", ct->name);
2295 if (ct->altname) {
2296 printf("(or %s) ", ct->altname);
2297 }
2298 }
2299
2300 if (ct->args) {
2301 printf("%s ", ct->args);
2302 }
2303 printf("-- %s\n", ct->oneline);
2304}
2305
2306static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2307{
2308 help_oneline(cmd, ct);
2309 if (ct->help) {
2310 ct->help();
2311 }
2312}
2313
2314static void help_all(void)
2315{
2316 const cmdinfo_t *ct;
2317
2318 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2319 help_oneline(ct->name, ct);
2320 }
2321 printf("\nUse 'help commandname' for extended help.\n");
2322}
2323
b32d7a39 2324static int help_f(BlockBackend *blk, int argc, char **argv)
f18a834a
KW
2325{
2326 const cmdinfo_t *ct;
2327
2328 if (argc == 1) {
2329 help_all();
b32d7a39 2330 return 0;
f18a834a
KW
2331 }
2332
2333 ct = find_command(argv[1]);
2334 if (ct == NULL) {
2335 printf("command %s not found\n", argv[1]);
b32d7a39 2336 return -EINVAL;
f18a834a
KW
2337 }
2338
2339 help_onecmd(argv[1], ct);
b32d7a39 2340 return 0;
f18a834a
KW
2341}
2342
2343static const cmdinfo_t help_cmd = {
2344 .name = "help",
2345 .altname = "?",
2346 .cfunc = help_f,
2347 .argmin = 0,
2348 .argmax = 1,
2349 .flags = CMD_FLAG_GLOBAL,
2350 .args = "[command]",
2351 .oneline = "help for one or all commands",
2352};
2353
b32d7a39 2354int qemuio_command(BlockBackend *blk, const char *cmd)
dd583296 2355{
15afd94a 2356 AioContext *ctx;
dd583296
KW
2357 char *input;
2358 const cmdinfo_t *ct;
2359 char **v;
2360 int c;
b32d7a39 2361 int ret = 0;
dd583296
KW
2362
2363 input = g_strdup(cmd);
2364 v = breakline(input, &c);
2365 if (c) {
2366 ct = find_command(v[0]);
2367 if (ct) {
15afd94a
PB
2368 ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
2369 aio_context_acquire(ctx);
b32d7a39 2370 ret = command(blk, ct, c, v);
15afd94a 2371 aio_context_release(ctx);
dd583296
KW
2372 } else {
2373 fprintf(stderr, "command \"%s\" not found\n", v[0]);
b32d7a39 2374 ret = -EINVAL;
dd583296
KW
2375 }
2376 }
2377 g_free(input);
2378 g_free(v);
b32d7a39
HR
2379
2380 return ret;
dd583296
KW
2381}
2382
797ac58c
KW
2383static void __attribute((constructor)) init_qemuio_commands(void)
2384{
2385 /* initialize commands */
c2cdf5c5
KW
2386 qemuio_add_command(&help_cmd);
2387 qemuio_add_command(&read_cmd);
2388 qemuio_add_command(&readv_cmd);
2389 qemuio_add_command(&write_cmd);
2390 qemuio_add_command(&writev_cmd);
c2cdf5c5
KW
2391 qemuio_add_command(&aio_read_cmd);
2392 qemuio_add_command(&aio_write_cmd);
2393 qemuio_add_command(&aio_flush_cmd);
2394 qemuio_add_command(&flush_cmd);
2395 qemuio_add_command(&truncate_cmd);
2396 qemuio_add_command(&length_cmd);
2397 qemuio_add_command(&info_cmd);
2398 qemuio_add_command(&discard_cmd);
2399 qemuio_add_command(&alloc_cmd);
2400 qemuio_add_command(&map_cmd);
5bbd2e59 2401 qemuio_add_command(&reopen_cmd);
c2cdf5c5 2402 qemuio_add_command(&break_cmd);
4cc70e93 2403 qemuio_add_command(&remove_break_cmd);
c2cdf5c5
KW
2404 qemuio_add_command(&resume_cmd);
2405 qemuio_add_command(&wait_break_cmd);
2406 qemuio_add_command(&abort_cmd);
cd33d02a 2407 qemuio_add_command(&sleep_cmd);
0e82dc7b 2408 qemuio_add_command(&sigraise_cmd);
797ac58c 2409}