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