]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-io-cmds.c
bsd-user: Implement several get/set system calls:
[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
2040 if (bs->drv && bs->drv->format_name) {
2041 printf("format name: %s\n", bs->drv->format_name);
2042 }
2043 if (bs->drv && bs->drv->protocol_name) {
2044 printf("format name: %s\n", bs->drv->protocol_name);
2045 }
2046
2047 ret = bdrv_get_info(bs, &bdi);
2048 if (ret) {
b32d7a39 2049 return ret;
797ac58c
KW
2050 }
2051
2052 cvtstr(bdi.cluster_size, s1, sizeof(s1));
2053 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
2054
2055 printf("cluster size: %s\n", s1);
2056 printf("vm state offset: %s\n", s2);
2057
1bf6e9ca
AS
2058 spec_info = bdrv_get_specific_info(bs, &local_err);
2059 if (local_err) {
2060 error_report_err(local_err);
2061 return -EIO;
2062 }
a8d8ecb7 2063 if (spec_info) {
3716470b 2064 bdrv_image_info_specific_dump(spec_info,
76c9e975
HR
2065 "Format specific information:\n",
2066 0);
a8d8ecb7
HR
2067 qapi_free_ImageInfoSpecific(spec_info);
2068 }
b32d7a39
HR
2069
2070 return 0;
797ac58c
KW
2071}
2072
2073
2074
2075static const cmdinfo_t info_cmd = {
2076 .name = "info",
2077 .altname = "i",
2078 .cfunc = info_f,
2079 .oneline = "prints information about the current file",
2080};
2081
2082static void discard_help(void)
2083{
2084 printf(
2085"\n"
2086" discards a range of bytes from the given offset\n"
2087"\n"
2088" Example:\n"
2089" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
2090"\n"
2091" Discards a segment of the currently open file.\n"
2092" -C, -- report statistics in a machine parsable format\n"
2093" -q, -- quiet mode, do not show I/O statistics\n"
2094"\n");
2095}
2096
b32d7a39 2097static int discard_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
2098
2099static const cmdinfo_t discard_cmd = {
2100 .name = "discard",
2101 .altname = "d",
2102 .cfunc = discard_f,
887354bd 2103 .perm = BLK_PERM_WRITE,
797ac58c
KW
2104 .argmin = 2,
2105 .argmax = -1,
2106 .args = "[-Cq] off len",
2107 .oneline = "discards a number of bytes at a specified offset",
2108 .help = discard_help,
2109};
2110
b32d7a39 2111static int discard_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2112{
50290c00 2113 struct timespec t1, t2;
dc38852a 2114 bool Cflag = false, qflag = false;
797ac58c 2115 int c, ret;
f5a5ca79 2116 int64_t offset, bytes;
797ac58c 2117
b062ad86 2118 while ((c = getopt(argc, argv, "Cq")) != -1) {
797ac58c
KW
2119 switch (c) {
2120 case 'C':
dc38852a 2121 Cflag = true;
797ac58c
KW
2122 break;
2123 case 'q':
dc38852a 2124 qflag = true;
797ac58c
KW
2125 break;
2126 default:
b444d0e9 2127 qemuio_command_usage(&discard_cmd);
b32d7a39 2128 return -EINVAL;
797ac58c
KW
2129 }
2130 }
2131
2132 if (optind != argc - 2) {
b444d0e9 2133 qemuio_command_usage(&discard_cmd);
b32d7a39 2134 return -EINVAL;
797ac58c
KW
2135 }
2136
2137 offset = cvtnum(argv[optind]);
2138 if (offset < 0) {
a9ecfa00 2139 print_cvtnum_err(offset, argv[optind]);
b32d7a39 2140 return offset;
797ac58c
KW
2141 }
2142
2143 optind++;
f5a5ca79
MP
2144 bytes = cvtnum(argv[optind]);
2145 if (bytes < 0) {
2146 print_cvtnum_err(bytes, argv[optind]);
b32d7a39 2147 return bytes;
41ae31e3 2148 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 2149 printf("length cannot exceed %"PRIu64", given %s\n",
41ae31e3 2150 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 2151 return -EINVAL;
797ac58c
KW
2152 }
2153
50290c00 2154 clock_gettime(CLOCK_MONOTONIC, &t1);
f5a5ca79 2155 ret = blk_pdiscard(blk, offset, bytes);
50290c00 2156 clock_gettime(CLOCK_MONOTONIC, &t2);
797ac58c
KW
2157
2158 if (ret < 0) {
2159 printf("discard failed: %s\n", strerror(-ret));
b32d7a39 2160 return ret;
797ac58c
KW
2161 }
2162
2163 /* Finally, report back -- -C gives a parsable format */
2164 if (!qflag) {
2165 t2 = tsub(t2, t1);
f5a5ca79 2166 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
797ac58c 2167 }
b32d7a39
HR
2168
2169 return 0;
797ac58c
KW
2170}
2171
b32d7a39 2172static int alloc_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2173{
4c7b7e9b 2174 BlockDriverState *bs = blk_bs(blk);
d6a644bb 2175 int64_t offset, start, remaining, count;
797ac58c 2176 char s1[64];
d6a644bb
EB
2177 int ret;
2178 int64_t num, sum_alloc;
797ac58c 2179
d6a644bb 2180 start = offset = cvtnum(argv[1]);
797ac58c 2181 if (offset < 0) {
a9ecfa00 2182 print_cvtnum_err(offset, argv[1]);
b32d7a39 2183 return offset;
797ac58c
KW
2184 }
2185
2186 if (argc == 3) {
4401fdc7
EB
2187 count = cvtnum(argv[2]);
2188 if (count < 0) {
2189 print_cvtnum_err(count, argv[2]);
b32d7a39 2190 return count;
797ac58c
KW
2191 }
2192 } else {
4401fdc7
EB
2193 count = BDRV_SECTOR_SIZE;
2194 }
797ac58c 2195
d6a644bb 2196 remaining = count;
797ac58c 2197 sum_alloc = 0;
797ac58c 2198 while (remaining) {
d6a644bb 2199 ret = bdrv_is_allocated(bs, offset, remaining, &num);
d663640c
PB
2200 if (ret < 0) {
2201 printf("is_allocated failed: %s\n", strerror(-ret));
b32d7a39 2202 return ret;
d663640c 2203 }
d6a644bb 2204 offset += num;
797ac58c
KW
2205 remaining -= num;
2206 if (ret) {
2207 sum_alloc += num;
2208 }
2209 if (num == 0) {
d6a644bb 2210 count -= remaining;
797ac58c
KW
2211 remaining = 0;
2212 }
2213 }
2214
d6a644bb 2215 cvtstr(start, s1, sizeof(s1));
797ac58c 2216
4401fdc7 2217 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
d6a644bb 2218 sum_alloc, count, s1);
b32d7a39 2219 return 0;
797ac58c
KW
2220}
2221
2222static const cmdinfo_t alloc_cmd = {
2223 .name = "alloc",
2224 .altname = "a",
2225 .argmin = 1,
2226 .argmax = 2,
2227 .cfunc = alloc_f,
4401fdc7
EB
2228 .args = "offset [count]",
2229 .oneline = "checks if offset is allocated in the file",
797ac58c
KW
2230};
2231
2232
d6a644bb
EB
2233static int map_is_allocated(BlockDriverState *bs, int64_t offset,
2234 int64_t bytes, int64_t *pnum)
797ac58c 2235{
d6a644bb 2236 int64_t num;
797ac58c
KW
2237 int ret, firstret;
2238
087f2fb3 2239 ret = bdrv_is_allocated(bs, offset, bytes, &num);
797ac58c
KW
2240 if (ret < 0) {
2241 return ret;
2242 }
2243
2244 firstret = ret;
2245 *pnum = num;
2246
d6a644bb
EB
2247 while (bytes > 0 && ret == firstret) {
2248 offset += num;
2249 bytes -= num;
797ac58c 2250
087f2fb3 2251 ret = bdrv_is_allocated(bs, offset, bytes, &num);
4b25bbc4 2252 if (ret == firstret && num) {
797ac58c
KW
2253 *pnum += num;
2254 } else {
2255 break;
2256 }
2257 }
2258
2259 return firstret;
2260}
2261
b32d7a39 2262static int map_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2263{
d6a644bb 2264 int64_t offset, bytes;
6f3c90af 2265 char s1[64], s2[64];
797ac58c
KW
2266 int64_t num;
2267 int ret;
2268 const char *retstr;
2269
2270 offset = 0;
d6a644bb
EB
2271 bytes = blk_getlength(blk);
2272 if (bytes < 0) {
2273 error_report("Failed to query image length: %s", strerror(-bytes));
b32d7a39 2274 return bytes;
4c7b7e9b
HR
2275 }
2276
d6a644bb
EB
2277 while (bytes) {
2278 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
797ac58c
KW
2279 if (ret < 0) {
2280 error_report("Failed to get allocation status: %s", strerror(-ret));
b32d7a39 2281 return ret;
4b25bbc4
HR
2282 } else if (!num) {
2283 error_report("Unexpected end of image");
b32d7a39 2284 return -EIO;
797ac58c
KW
2285 }
2286
2287 retstr = ret ? " allocated" : "not allocated";
d6a644bb
EB
2288 cvtstr(num, s1, sizeof(s1));
2289 cvtstr(offset, s2, sizeof(s2));
6f3c90af 2290 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
d6a644bb 2291 s1, num, retstr, s2, offset);
797ac58c
KW
2292
2293 offset += num;
d6a644bb
EB
2294 bytes -= num;
2295 }
b32d7a39
HR
2296
2297 return 0;
797ac58c
KW
2298}
2299
2300static const cmdinfo_t map_cmd = {
2301 .name = "map",
2302 .argmin = 0,
2303 .argmax = 0,
2304 .cfunc = map_f,
2305 .args = "",
2306 .oneline = "prints the allocated areas of a file",
2307};
2308
5bbd2e59
KW
2309static void reopen_help(void)
2310{
2311 printf(
2312"\n"
2313" Changes the open options of an already opened image\n"
2314"\n"
2315" Example:\n"
2316" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2317"\n"
2318" -r, -- Reopen the image read-only\n"
ea92203c 2319" -w, -- Reopen the image read-write\n"
5bbd2e59
KW
2320" -c, -- Change the cache mode to the given value\n"
2321" -o, -- Changes block driver options (cf. 'open' command)\n"
2322"\n");
2323}
2324
b32d7a39 2325static int reopen_f(BlockBackend *blk, int argc, char **argv);
5bbd2e59
KW
2326
2327static QemuOptsList reopen_opts = {
2328 .name = "reopen",
2329 .merge_lists = true,
2330 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2331 .desc = {
2332 /* no elements => accept any params */
2333 { /* end of list */ }
2334 },
2335};
2336
2337static const cmdinfo_t reopen_cmd = {
2338 .name = "reopen",
2339 .argmin = 0,
2340 .argmax = -1,
2341 .cfunc = reopen_f,
ea92203c 2342 .args = "[(-r|-w)] [-c cache] [-o options]",
5bbd2e59
KW
2343 .oneline = "reopens an image with new options",
2344 .help = reopen_help,
2345};
2346
b32d7a39 2347static int reopen_f(BlockBackend *blk, int argc, char **argv)
5bbd2e59
KW
2348{
2349 BlockDriverState *bs = blk_bs(blk);
2350 QemuOpts *qopts;
2351 QDict *opts;
2352 int c;
2353 int flags = bs->open_flags;
19dbecdc 2354 bool writethrough = !blk_enable_write_cache(blk);
ea92203c 2355 bool has_rw_option = false;
dc900c35 2356 bool has_cache_option = false;
5bbd2e59
KW
2357 Error *local_err = NULL;
2358
ea92203c 2359 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
5bbd2e59
KW
2360 switch (c) {
2361 case 'c':
19dbecdc 2362 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
5bbd2e59 2363 error_report("Invalid cache option: %s", optarg);
b32d7a39 2364 return -EINVAL;
5bbd2e59 2365 }
dc900c35 2366 has_cache_option = true;
5bbd2e59
KW
2367 break;
2368 case 'o':
2369 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2370 qemu_opts_reset(&reopen_opts);
b32d7a39 2371 return -EINVAL;
5bbd2e59
KW
2372 }
2373 break;
2374 case 'r':
ea92203c
KW
2375 if (has_rw_option) {
2376 error_report("Only one -r/-w option may be given");
b32d7a39 2377 return -EINVAL;
ea92203c 2378 }
5bbd2e59 2379 flags &= ~BDRV_O_RDWR;
ea92203c
KW
2380 has_rw_option = true;
2381 break;
2382 case 'w':
2383 if (has_rw_option) {
2384 error_report("Only one -r/-w option may be given");
b32d7a39 2385 return -EINVAL;
ea92203c
KW
2386 }
2387 flags |= BDRV_O_RDWR;
2388 has_rw_option = true;
5bbd2e59
KW
2389 break;
2390 default:
2391 qemu_opts_reset(&reopen_opts);
b444d0e9 2392 qemuio_command_usage(&reopen_cmd);
b32d7a39 2393 return -EINVAL;
5bbd2e59
KW
2394 }
2395 }
2396
2397 if (optind != argc) {
2398 qemu_opts_reset(&reopen_opts);
b444d0e9 2399 qemuio_command_usage(&reopen_cmd);
b32d7a39 2400 return -EINVAL;
5bbd2e59
KW
2401 }
2402
a8003ec4 2403 if (!writethrough != blk_enable_write_cache(blk) &&
19dbecdc
KW
2404 blk_get_attached_dev(blk))
2405 {
2406 error_report("Cannot change cache.writeback: Device attached");
2407 qemu_opts_reset(&reopen_opts);
b32d7a39 2408 return -EBUSY;
19dbecdc
KW
2409 }
2410
f3adefb2
KW
2411 if (!(flags & BDRV_O_RDWR)) {
2412 uint64_t orig_perm, orig_shared_perm;
2413
2414 bdrv_drain(bs);
2415
2416 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2417 blk_set_perm(blk,
2418 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2419 orig_shared_perm,
2420 &error_abort);
2421 }
2422
5bbd2e59 2423 qopts = qemu_opts_find(&reopen_opts, NULL);
dc900c35 2424 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
5bbd2e59
KW
2425 qemu_opts_reset(&reopen_opts);
2426
dc900c35
AG
2427 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2428 if (has_rw_option) {
2429 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2430 qobject_unref(opts);
2431 return -EINVAL;
2432 }
2433 } else {
2434 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2435 }
2436
2437 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2438 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2439 if (has_cache_option) {
2440 error_report("Cannot set both -c and the cache options");
2441 qobject_unref(opts);
2442 return -EINVAL;
2443 }
2444 } else {
2445 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2446 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2447 }
2448
6cf42ca2 2449 bdrv_reopen(bs, opts, true, &local_err);
1a63a907 2450
5bbd2e59
KW
2451 if (local_err) {
2452 error_report_err(local_err);
b32d7a39 2453 return -EINVAL;
5bbd2e59 2454 }
b32d7a39
HR
2455
2456 blk_set_enable_write_cache(blk, !writethrough);
2457 return 0;
5bbd2e59
KW
2458}
2459
b32d7a39 2460static int break_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2461{
2462 int ret;
2463
4c7b7e9b 2464 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
797ac58c
KW
2465 if (ret < 0) {
2466 printf("Could not set breakpoint: %s\n", strerror(-ret));
b32d7a39 2467 return ret;
797ac58c 2468 }
b32d7a39
HR
2469
2470 return 0;
797ac58c
KW
2471}
2472
b32d7a39 2473static int remove_break_f(BlockBackend *blk, int argc, char **argv)
4cc70e93
FZ
2474{
2475 int ret;
2476
4c7b7e9b 2477 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
4cc70e93
FZ
2478 if (ret < 0) {
2479 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
b32d7a39 2480 return ret;
4cc70e93 2481 }
b32d7a39
HR
2482
2483 return 0;
4cc70e93
FZ
2484}
2485
797ac58c
KW
2486static const cmdinfo_t break_cmd = {
2487 .name = "break",
2488 .argmin = 2,
2489 .argmax = 2,
2490 .cfunc = break_f,
2491 .args = "event tag",
2492 .oneline = "sets a breakpoint on event and tags the stopped "
2493 "request as tag",
2494};
2495
4cc70e93
FZ
2496static const cmdinfo_t remove_break_cmd = {
2497 .name = "remove_break",
2498 .argmin = 1,
2499 .argmax = 1,
2500 .cfunc = remove_break_f,
2501 .args = "tag",
2502 .oneline = "remove a breakpoint by tag",
2503};
2504
b32d7a39 2505static int resume_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2506{
2507 int ret;
2508
4c7b7e9b 2509 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
797ac58c
KW
2510 if (ret < 0) {
2511 printf("Could not resume request: %s\n", strerror(-ret));
b32d7a39 2512 return ret;
797ac58c 2513 }
b32d7a39
HR
2514
2515 return 0;
797ac58c
KW
2516}
2517
2518static const cmdinfo_t resume_cmd = {
2519 .name = "resume",
2520 .argmin = 1,
2521 .argmax = 1,
2522 .cfunc = resume_f,
2523 .args = "tag",
2524 .oneline = "resumes the request tagged as tag",
2525};
2526
b32d7a39 2527static int wait_break_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2528{
4c7b7e9b
HR
2529 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2530 aio_poll(blk_get_aio_context(blk), true);
797ac58c 2531 }
b32d7a39 2532 return 0;
797ac58c
KW
2533}
2534
2535static const cmdinfo_t wait_break_cmd = {
2536 .name = "wait_break",
2537 .argmin = 1,
2538 .argmax = 1,
2539 .cfunc = wait_break_f,
2540 .args = "tag",
2541 .oneline = "waits for the suspension of a request",
2542};
2543
b32d7a39 2544static int abort_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2545{
2546 abort();
2547}
2548
2549static const cmdinfo_t abort_cmd = {
2550 .name = "abort",
2551 .cfunc = abort_f,
2552 .flags = CMD_NOFILE_OK,
2553 .oneline = "simulate a program crash using abort(3)",
2554};
2555
0e82dc7b
HR
2556static void sigraise_help(void)
2557{
2558 printf(
2559"\n"
2560" raises the given signal\n"
2561"\n"
2562" Example:\n"
2563" 'sigraise %i' - raises SIGTERM\n"
2564"\n"
2565" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2566" given to sigraise.\n"
2567"\n", SIGTERM);
2568}
2569
b32d7a39 2570static int sigraise_f(BlockBackend *blk, int argc, char **argv);
0e82dc7b
HR
2571
2572static const cmdinfo_t sigraise_cmd = {
2573 .name = "sigraise",
2574 .cfunc = sigraise_f,
2575 .argmin = 1,
2576 .argmax = 1,
2577 .flags = CMD_NOFILE_OK,
2578 .args = "signal",
2579 .oneline = "raises a signal",
2580 .help = sigraise_help,
2581};
2582
b32d7a39 2583static int sigraise_f(BlockBackend *blk, int argc, char **argv)
0e82dc7b 2584{
9b0beaf3 2585 int64_t sig = cvtnum(argv[1]);
0e82dc7b 2586 if (sig < 0) {
a9ecfa00 2587 print_cvtnum_err(sig, argv[1]);
b32d7a39 2588 return sig;
9b0beaf3
JS
2589 } else if (sig > NSIG) {
2590 printf("signal argument '%s' is too large to be a valid signal\n",
2591 argv[1]);
b32d7a39 2592 return -EINVAL;
0e82dc7b
HR
2593 }
2594
2595 /* Using raise() to kill this process does not necessarily flush all open
2596 * streams. At least stdout and stderr (although the latter should be
2597 * non-buffered anyway) should be flushed, though. */
2598 fflush(stdout);
2599 fflush(stderr);
2600
2601 raise(sig);
b32d7a39
HR
2602
2603 return 0;
0e82dc7b
HR
2604}
2605
cd33d02a
KW
2606static void sleep_cb(void *opaque)
2607{
2608 bool *expired = opaque;
2609 *expired = true;
2610}
2611
b32d7a39 2612static int sleep_f(BlockBackend *blk, int argc, char **argv)
cd33d02a
KW
2613{
2614 char *endptr;
2615 long ms;
2616 struct QEMUTimer *timer;
2617 bool expired = false;
2618
2619 ms = strtol(argv[1], &endptr, 0);
2620 if (ms < 0 || *endptr != '\0') {
2621 printf("%s is not a valid number\n", argv[1]);
b32d7a39 2622 return -EINVAL;
cd33d02a
KW
2623 }
2624
2625 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2626 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2627
2628 while (!expired) {
2629 main_loop_wait(false);
2630 }
2631
2632 timer_free(timer);
b32d7a39 2633 return 0;
cd33d02a
KW
2634}
2635
2636static const cmdinfo_t sleep_cmd = {
2637 .name = "sleep",
2638 .argmin = 1,
2639 .argmax = 1,
2640 .cfunc = sleep_f,
2641 .flags = CMD_NOFILE_OK,
2642 .oneline = "waits for the given value in milliseconds",
2643};
2644
f18a834a
KW
2645static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2646{
da16f4b8 2647 printf("%s ", cmd);
f18a834a
KW
2648
2649 if (ct->args) {
2650 printf("%s ", ct->args);
2651 }
2652 printf("-- %s\n", ct->oneline);
2653}
2654
2655static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2656{
2657 help_oneline(cmd, ct);
2658 if (ct->help) {
2659 ct->help();
2660 }
2661}
2662
2663static void help_all(void)
2664{
2665 const cmdinfo_t *ct;
2666
2667 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2668 help_oneline(ct->name, ct);
2669 }
2670 printf("\nUse 'help commandname' for extended help.\n");
2671}
2672
b32d7a39 2673static int help_f(BlockBackend *blk, int argc, char **argv)
f18a834a
KW
2674{
2675 const cmdinfo_t *ct;
2676
da16f4b8 2677 if (argc < 2) {
f18a834a 2678 help_all();
b32d7a39 2679 return 0;
f18a834a
KW
2680 }
2681
2682 ct = find_command(argv[1]);
2683 if (ct == NULL) {
2684 printf("command %s not found\n", argv[1]);
b32d7a39 2685 return -EINVAL;
f18a834a
KW
2686 }
2687
2688 help_onecmd(argv[1], ct);
b32d7a39 2689 return 0;
f18a834a
KW
2690}
2691
2692static const cmdinfo_t help_cmd = {
2693 .name = "help",
2694 .altname = "?",
2695 .cfunc = help_f,
2696 .argmin = 0,
2697 .argmax = 1,
2698 .flags = CMD_FLAG_GLOBAL,
2699 .args = "[command]",
2700 .oneline = "help for one or all commands",
2701};
2702
78632a3d
VSO
2703/*
2704 * Called with aio context of blk acquired. Or with qemu_get_aio_context()
2705 * context acquired if blk is NULL.
2706 */
b32d7a39 2707int qemuio_command(BlockBackend *blk, const char *cmd)
dd583296
KW
2708{
2709 char *input;
2710 const cmdinfo_t *ct;
2711 char **v;
2712 int c;
b32d7a39 2713 int ret = 0;
dd583296
KW
2714
2715 input = g_strdup(cmd);
2716 v = breakline(input, &c);
2717 if (c) {
2718 ct = find_command(v[0]);
2719 if (ct) {
b32d7a39 2720 ret = command(blk, ct, c, v);
dd583296
KW
2721 } else {
2722 fprintf(stderr, "command \"%s\" not found\n", v[0]);
b32d7a39 2723 ret = -EINVAL;
dd583296
KW
2724 }
2725 }
2726 g_free(input);
2727 g_free(v);
b32d7a39
HR
2728
2729 return ret;
dd583296
KW
2730}
2731
797ac58c
KW
2732static void __attribute((constructor)) init_qemuio_commands(void)
2733{
2734 /* initialize commands */
c2cdf5c5
KW
2735 qemuio_add_command(&help_cmd);
2736 qemuio_add_command(&read_cmd);
2737 qemuio_add_command(&readv_cmd);
2738 qemuio_add_command(&write_cmd);
2739 qemuio_add_command(&writev_cmd);
c2cdf5c5
KW
2740 qemuio_add_command(&aio_read_cmd);
2741 qemuio_add_command(&aio_write_cmd);
2742 qemuio_add_command(&aio_flush_cmd);
2743 qemuio_add_command(&flush_cmd);
6d43eaa3
SL
2744 qemuio_add_command(&zone_report_cmd);
2745 qemuio_add_command(&zone_open_cmd);
2746 qemuio_add_command(&zone_close_cmd);
2747 qemuio_add_command(&zone_finish_cmd);
2748 qemuio_add_command(&zone_reset_cmd);
fe4fe70d 2749 qemuio_add_command(&zone_append_cmd);
c2cdf5c5
KW
2750 qemuio_add_command(&truncate_cmd);
2751 qemuio_add_command(&length_cmd);
2752 qemuio_add_command(&info_cmd);
2753 qemuio_add_command(&discard_cmd);
2754 qemuio_add_command(&alloc_cmd);
2755 qemuio_add_command(&map_cmd);
5bbd2e59 2756 qemuio_add_command(&reopen_cmd);
c2cdf5c5 2757 qemuio_add_command(&break_cmd);
4cc70e93 2758 qemuio_add_command(&remove_break_cmd);
c2cdf5c5
KW
2759 qemuio_add_command(&resume_cmd);
2760 qemuio_add_command(&wait_break_cmd);
2761 qemuio_add_command(&abort_cmd);
cd33d02a 2762 qemuio_add_command(&sleep_cmd);
0e82dc7b 2763 qemuio_add_command(&sigraise_cmd);
797ac58c 2764}