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