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