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