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