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