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