]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-io-cmds.c
usb: remove unnecessary NULL device check from usb_ep_get()
[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"
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,
c2e001cc 967 .args = "[-bcCfquz] [-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
KW
973{
974 struct timeval 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
c2e001cc 986 while ((c = getopt(argc, argv, "bcCfpP: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;
797ac58c 1000 case 'p':
093ea232 1001 /* Ignored for backwards compatibility */
797ac58c
KW
1002 break;
1003 case 'P':
dc38852a 1004 Pflag = true;
797ac58c
KW
1005 pattern = parse_pattern(optarg);
1006 if (pattern < 0) {
b32d7a39 1007 return -EINVAL;
797ac58c
KW
1008 }
1009 break;
1010 case 'q':
dc38852a 1011 qflag = true;
797ac58c 1012 break;
c2e001cc
EB
1013 case 'u':
1014 flags |= BDRV_REQ_MAY_UNMAP;
1015 break;
797ac58c 1016 case 'z':
dc38852a 1017 zflag = true;
797ac58c
KW
1018 break;
1019 default:
b444d0e9 1020 qemuio_command_usage(&write_cmd);
b32d7a39 1021 return -EINVAL;
797ac58c
KW
1022 }
1023 }
1024
1025 if (optind != argc - 2) {
b444d0e9 1026 qemuio_command_usage(&write_cmd);
b32d7a39 1027 return -EINVAL;
797ac58c
KW
1028 }
1029
093ea232
EB
1030 if (bflag && zflag) {
1031 printf("-b and -z cannot be specified at the same time\n");
b32d7a39 1032 return -EINVAL;
797ac58c
KW
1033 }
1034
770e0e0e
EB
1035 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
1036 printf("-f and -b or -c cannot be specified at the same time\n");
b32d7a39 1037 return -EINVAL;
770e0e0e
EB
1038 }
1039
c2e001cc
EB
1040 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
1041 printf("-u requires -z to be specified\n");
b32d7a39 1042 return -EINVAL;
c2e001cc
EB
1043 }
1044
797ac58c
KW
1045 if (zflag && Pflag) {
1046 printf("-z and -P cannot be specified at the same time\n");
b32d7a39 1047 return -EINVAL;
797ac58c
KW
1048 }
1049
1050 offset = cvtnum(argv[optind]);
1051 if (offset < 0) {
a9ecfa00 1052 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1053 return offset;
797ac58c
KW
1054 }
1055
1056 optind++;
1057 count = cvtnum(argv[optind]);
1058 if (count < 0) {
a9ecfa00 1059 print_cvtnum_err(count, argv[optind]);
b32d7a39 1060 return count;
3026c468 1061 } else if (count > BDRV_REQUEST_MAX_BYTES) {
9b0beaf3 1062 printf("length cannot exceed %" PRIu64 ", given %s\n",
3026c468 1063 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
b32d7a39 1064 return -EINVAL;
797ac58c
KW
1065 }
1066
093ea232 1067 if (bflag || cflag) {
1bce6b4c
EB
1068 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
1069 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
797ac58c 1070 offset);
b32d7a39 1071 return -EINVAL;
797ac58c
KW
1072 }
1073
1bce6b4c
EB
1074 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
1075 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
797ac58c 1076 count);
b32d7a39 1077 return -EINVAL;
797ac58c
KW
1078 }
1079 }
1080
1081 if (!zflag) {
4c7b7e9b 1082 buf = qemu_io_alloc(blk, count, pattern);
797ac58c
KW
1083 }
1084
1085 gettimeofday(&t1, NULL);
7b3f9712 1086 if (bflag) {
b32d7a39 1087 ret = do_save_vmstate(blk, buf, offset, count, &total);
797ac58c 1088 } else if (zflag) {
b32d7a39 1089 ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
797ac58c 1090 } else if (cflag) {
b32d7a39 1091 ret = do_write_compressed(blk, buf, offset, count, &total);
797ac58c 1092 } else {
b32d7a39 1093 ret = do_pwrite(blk, buf, offset, count, flags, &total);
797ac58c
KW
1094 }
1095 gettimeofday(&t2, NULL);
1096
b32d7a39
HR
1097 if (ret < 0) {
1098 printf("write failed: %s\n", strerror(-ret));
797ac58c
KW
1099 goto out;
1100 }
b32d7a39
HR
1101 cnt = ret;
1102
1103 ret = 0;
797ac58c
KW
1104
1105 if (qflag) {
1106 goto out;
1107 }
1108
1109 /* Finally, report back -- -C gives a parsable format */
1110 t2 = tsub(t2, t1);
1111 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1112
1113out:
1114 if (!zflag) {
1115 qemu_io_free(buf);
1116 }
b32d7a39 1117 return ret;
797ac58c
KW
1118}
1119
1120static void
1121writev_help(void)
1122{
1123 printf(
1124"\n"
1125" writes a range of bytes from the given offset source from multiple buffers\n"
1126"\n"
1127" Example:\n"
6e6507c0 1128" 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
797ac58c
KW
1129"\n"
1130" Writes into a segment of the currently open file, using a buffer\n"
1131" filled with a set pattern (0xcdcdcdcd).\n"
1132" -P, -- use different pattern to fill file\n"
1133" -C, -- report statistics in a machine parsable format\n"
770e0e0e 1134" -f, -- use Force Unit Access semantics\n"
797ac58c
KW
1135" -q, -- quiet mode, do not show I/O statistics\n"
1136"\n");
1137}
1138
b32d7a39 1139static int writev_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1140
1141static const cmdinfo_t writev_cmd = {
1142 .name = "writev",
1143 .cfunc = writev_f,
887354bd 1144 .perm = BLK_PERM_WRITE,
797ac58c
KW
1145 .argmin = 2,
1146 .argmax = -1,
770e0e0e 1147 .args = "[-Cfq] [-P pattern] off len [len..]",
797ac58c
KW
1148 .oneline = "writes a number of bytes at a specified offset",
1149 .help = writev_help,
1150};
1151
b32d7a39 1152static int writev_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1153{
1154 struct timeval t1, t2;
dc38852a 1155 bool Cflag = false, qflag = false;
770e0e0e 1156 int flags = 0;
b32d7a39 1157 int c, cnt, ret;
797ac58c
KW
1158 char *buf;
1159 int64_t offset;
1160 /* Some compilers get confused and warn if this is not initialized. */
1161 int total = 0;
1162 int nr_iov;
1163 int pattern = 0xcd;
1164 QEMUIOVector qiov;
1165
4ca1d340 1166 while ((c = getopt(argc, argv, "CfqP:")) != -1) {
797ac58c
KW
1167 switch (c) {
1168 case 'C':
dc38852a 1169 Cflag = true;
797ac58c 1170 break;
770e0e0e
EB
1171 case 'f':
1172 flags |= BDRV_REQ_FUA;
1173 break;
797ac58c 1174 case 'q':
dc38852a 1175 qflag = true;
797ac58c
KW
1176 break;
1177 case 'P':
1178 pattern = parse_pattern(optarg);
1179 if (pattern < 0) {
b32d7a39 1180 return -EINVAL;
797ac58c
KW
1181 }
1182 break;
1183 default:
b444d0e9 1184 qemuio_command_usage(&writev_cmd);
b32d7a39 1185 return -EINVAL;
797ac58c
KW
1186 }
1187 }
1188
1189 if (optind > argc - 2) {
b444d0e9 1190 qemuio_command_usage(&writev_cmd);
b32d7a39 1191 return -EINVAL;
797ac58c
KW
1192 }
1193
1194 offset = cvtnum(argv[optind]);
1195 if (offset < 0) {
a9ecfa00 1196 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1197 return offset;
797ac58c
KW
1198 }
1199 optind++;
1200
797ac58c 1201 nr_iov = argc - optind;
4c7b7e9b 1202 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
797ac58c 1203 if (buf == NULL) {
b32d7a39 1204 return -EINVAL;
797ac58c
KW
1205 }
1206
1207 gettimeofday(&t1, NULL);
b32d7a39 1208 ret = do_aio_writev(blk, &qiov, offset, flags, &total);
797ac58c
KW
1209 gettimeofday(&t2, NULL);
1210
b32d7a39
HR
1211 if (ret < 0) {
1212 printf("writev failed: %s\n", strerror(-ret));
797ac58c
KW
1213 goto out;
1214 }
b32d7a39
HR
1215 cnt = ret;
1216
1217 ret = 0;
797ac58c
KW
1218
1219 if (qflag) {
1220 goto out;
1221 }
1222
1223 /* Finally, report back -- -C gives a parsable format */
1224 t2 = tsub(t2, t1);
1225 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1226out:
1227 qemu_iovec_destroy(&qiov);
1228 qemu_io_free(buf);
b32d7a39 1229 return ret;
797ac58c
KW
1230}
1231
797ac58c 1232struct aio_ctx {
4c7b7e9b 1233 BlockBackend *blk;
797ac58c
KW
1234 QEMUIOVector qiov;
1235 int64_t offset;
1236 char *buf;
dc38852a
EB
1237 bool qflag;
1238 bool vflag;
1239 bool Cflag;
1240 bool Pflag;
1241 bool zflag;
a91f9584 1242 BlockAcctCookie acct;
797ac58c
KW
1243 int pattern;
1244 struct timeval t1;
1245};
1246
1247static void aio_write_done(void *opaque, int ret)
1248{
1249 struct aio_ctx *ctx = opaque;
1250 struct timeval t2;
1251
1252 gettimeofday(&t2, NULL);
1253
1254
1255 if (ret < 0) {
1256 printf("aio_write failed: %s\n", strerror(-ret));
556c2b60 1257 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
797ac58c
KW
1258 goto out;
1259 }
1260
4c7b7e9b 1261 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
a91f9584 1262
797ac58c
KW
1263 if (ctx->qflag) {
1264 goto out;
1265 }
1266
1267 /* Finally, report back -- -C gives a parsable format */
1268 t2 = tsub(t2, ctx->t1);
1269 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1270 ctx->qiov.size, 1, ctx->Cflag);
1271out:
5ceb7765
KW
1272 if (!ctx->zflag) {
1273 qemu_io_free(ctx->buf);
1274 qemu_iovec_destroy(&ctx->qiov);
1275 }
797ac58c
KW
1276 g_free(ctx);
1277}
1278
1279static void aio_read_done(void *opaque, int ret)
1280{
1281 struct aio_ctx *ctx = opaque;
1282 struct timeval t2;
1283
1284 gettimeofday(&t2, NULL);
1285
1286 if (ret < 0) {
1287 printf("readv failed: %s\n", strerror(-ret));
556c2b60 1288 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
797ac58c
KW
1289 goto out;
1290 }
1291
1292 if (ctx->Pflag) {
1293 void *cmp_buf = g_malloc(ctx->qiov.size);
1294
1295 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1296 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1297 printf("Pattern verification failed at offset %"
cf67b692 1298 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
797ac58c
KW
1299 }
1300 g_free(cmp_buf);
1301 }
1302
4c7b7e9b 1303 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
a91f9584 1304
797ac58c
KW
1305 if (ctx->qflag) {
1306 goto out;
1307 }
1308
1309 if (ctx->vflag) {
1310 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1311 }
1312
1313 /* Finally, report back -- -C gives a parsable format */
1314 t2 = tsub(t2, ctx->t1);
1315 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1316 ctx->qiov.size, 1, ctx->Cflag);
1317out:
1318 qemu_io_free(ctx->buf);
1319 qemu_iovec_destroy(&ctx->qiov);
1320 g_free(ctx);
1321}
1322
1323static void aio_read_help(void)
1324{
1325 printf(
1326"\n"
1327" asynchronously reads a range of bytes from the given offset\n"
1328"\n"
1329" Example:\n"
1330" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1331"\n"
1332" Reads a segment of the currently open file, optionally dumping it to the\n"
1333" standard output stream (with -v option) for subsequent inspection.\n"
1334" The read is performed asynchronously and the aio_flush command must be\n"
1335" used to ensure all outstanding aio requests have been completed.\n"
b32d7a39
HR
1336" Note that due to its asynchronous nature, this command will be\n"
1337" considered successful once the request is submitted, independently\n"
1338" of potential I/O errors or pattern mismatches.\n"
797ac58c
KW
1339" -C, -- report statistics in a machine parsable format\n"
1340" -P, -- use a pattern to verify read data\n"
37546ff2 1341" -i, -- treat request as invalid, for exercising stats\n"
797ac58c
KW
1342" -v, -- dump buffer to standard output\n"
1343" -q, -- quiet mode, do not show I/O statistics\n"
1344"\n");
1345}
1346
b32d7a39 1347static int aio_read_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1348
1349static const cmdinfo_t aio_read_cmd = {
1350 .name = "aio_read",
1351 .cfunc = aio_read_f,
1352 .argmin = 2,
1353 .argmax = -1,
37546ff2 1354 .args = "[-Ciqv] [-P pattern] off len [len..]",
797ac58c
KW
1355 .oneline = "asynchronously reads a number of bytes",
1356 .help = aio_read_help,
1357};
1358
b32d7a39 1359static int aio_read_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1360{
1361 int nr_iov, c;
1362 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1363
4c7b7e9b 1364 ctx->blk = blk;
37546ff2 1365 while ((c = getopt(argc, argv, "CP:iqv")) != -1) {
797ac58c
KW
1366 switch (c) {
1367 case 'C':
dc38852a 1368 ctx->Cflag = true;
797ac58c
KW
1369 break;
1370 case 'P':
dc38852a 1371 ctx->Pflag = true;
797ac58c
KW
1372 ctx->pattern = parse_pattern(optarg);
1373 if (ctx->pattern < 0) {
1374 g_free(ctx);
b32d7a39 1375 return -EINVAL;
797ac58c
KW
1376 }
1377 break;
37546ff2
EB
1378 case 'i':
1379 printf("injecting invalid read request\n");
1380 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1381 g_free(ctx);
b32d7a39 1382 return 0;
797ac58c 1383 case 'q':
dc38852a 1384 ctx->qflag = true;
797ac58c
KW
1385 break;
1386 case 'v':
dc38852a 1387 ctx->vflag = true;
797ac58c
KW
1388 break;
1389 default:
1390 g_free(ctx);
b444d0e9 1391 qemuio_command_usage(&aio_read_cmd);
b32d7a39 1392 return -EINVAL;
797ac58c
KW
1393 }
1394 }
1395
1396 if (optind > argc - 2) {
1397 g_free(ctx);
b444d0e9 1398 qemuio_command_usage(&aio_read_cmd);
b32d7a39 1399 return -EINVAL;
797ac58c
KW
1400 }
1401
1402 ctx->offset = cvtnum(argv[optind]);
1403 if (ctx->offset < 0) {
b32d7a39
HR
1404 int ret = ctx->offset;
1405 print_cvtnum_err(ret, argv[optind]);
797ac58c 1406 g_free(ctx);
b32d7a39 1407 return ret;
797ac58c
KW
1408 }
1409 optind++;
1410
797ac58c 1411 nr_iov = argc - optind;
4c7b7e9b 1412 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
797ac58c 1413 if (ctx->buf == NULL) {
556c2b60 1414 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
797ac58c 1415 g_free(ctx);
b32d7a39 1416 return -EINVAL;
797ac58c
KW
1417 }
1418
1419 gettimeofday(&ctx->t1, NULL);
4c7b7e9b
HR
1420 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1421 BLOCK_ACCT_READ);
7b3f9712 1422 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
b32d7a39 1423 return 0;
797ac58c
KW
1424}
1425
1426static void aio_write_help(void)
1427{
1428 printf(
1429"\n"
1430" asynchronously writes a range of bytes from the given offset source\n"
1431" from multiple buffers\n"
1432"\n"
1433" Example:\n"
1434" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1435"\n"
1436" Writes into a segment of the currently open file, using a buffer\n"
1437" filled with a set pattern (0xcdcdcdcd).\n"
1438" The write is performed asynchronously and the aio_flush command must be\n"
1439" used to ensure all outstanding aio requests have been completed.\n"
b32d7a39
HR
1440" Note that due to its asynchronous nature, this command will be\n"
1441" considered successful once the request is submitted, independently\n"
1442" of potential I/O errors or pattern mismatches.\n"
797ac58c
KW
1443" -P, -- use different pattern to fill file\n"
1444" -C, -- report statistics in a machine parsable format\n"
770e0e0e 1445" -f, -- use Force Unit Access semantics\n"
37546ff2 1446" -i, -- treat request as invalid, for exercising stats\n"
797ac58c 1447" -q, -- quiet mode, do not show I/O statistics\n"
c2e001cc 1448" -u, -- with -z, allow unmapping\n"
d004bd52 1449" -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
797ac58c
KW
1450"\n");
1451}
1452
b32d7a39 1453static int aio_write_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1454
1455static const cmdinfo_t aio_write_cmd = {
1456 .name = "aio_write",
1457 .cfunc = aio_write_f,
887354bd 1458 .perm = BLK_PERM_WRITE,
797ac58c
KW
1459 .argmin = 2,
1460 .argmax = -1,
37546ff2 1461 .args = "[-Cfiquz] [-P pattern] off len [len..]",
797ac58c
KW
1462 .oneline = "asynchronously writes a number of bytes",
1463 .help = aio_write_help,
1464};
1465
b32d7a39 1466static int aio_write_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1467{
1468 int nr_iov, c;
1469 int pattern = 0xcd;
1470 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
770e0e0e 1471 int flags = 0;
797ac58c 1472
4c7b7e9b 1473 ctx->blk = blk;
37546ff2 1474 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
797ac58c
KW
1475 switch (c) {
1476 case 'C':
dc38852a 1477 ctx->Cflag = true;
797ac58c 1478 break;
770e0e0e
EB
1479 case 'f':
1480 flags |= BDRV_REQ_FUA;
1481 break;
797ac58c 1482 case 'q':
dc38852a 1483 ctx->qflag = true;
797ac58c 1484 break;
c2e001cc
EB
1485 case 'u':
1486 flags |= BDRV_REQ_MAY_UNMAP;
1487 break;
797ac58c
KW
1488 case 'P':
1489 pattern = parse_pattern(optarg);
1490 if (pattern < 0) {
1491 g_free(ctx);
b32d7a39 1492 return -EINVAL;
797ac58c
KW
1493 }
1494 break;
37546ff2
EB
1495 case 'i':
1496 printf("injecting invalid write request\n");
1497 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1498 g_free(ctx);
b32d7a39 1499 return 0;
5ceb7765 1500 case 'z':
dc38852a 1501 ctx->zflag = true;
5ceb7765 1502 break;
797ac58c
KW
1503 default:
1504 g_free(ctx);
b444d0e9 1505 qemuio_command_usage(&aio_write_cmd);
b32d7a39 1506 return -EINVAL;
797ac58c
KW
1507 }
1508 }
1509
1510 if (optind > argc - 2) {
1511 g_free(ctx);
b444d0e9 1512 qemuio_command_usage(&aio_write_cmd);
b32d7a39 1513 return -EINVAL;
797ac58c
KW
1514 }
1515
5ceb7765
KW
1516 if (ctx->zflag && optind != argc - 2) {
1517 printf("-z supports only a single length parameter\n");
1518 g_free(ctx);
b32d7a39 1519 return -EINVAL;
5ceb7765
KW
1520 }
1521
c2e001cc
EB
1522 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
1523 printf("-u requires -z to be specified\n");
4ca1d340 1524 g_free(ctx);
b32d7a39 1525 return -EINVAL;
c2e001cc
EB
1526 }
1527
5ceb7765
KW
1528 if (ctx->zflag && ctx->Pflag) {
1529 printf("-z and -P cannot be specified at the same time\n");
1530 g_free(ctx);
b32d7a39 1531 return -EINVAL;
5ceb7765
KW
1532 }
1533
797ac58c
KW
1534 ctx->offset = cvtnum(argv[optind]);
1535 if (ctx->offset < 0) {
b32d7a39
HR
1536 int ret = ctx->offset;
1537 print_cvtnum_err(ret, argv[optind]);
797ac58c 1538 g_free(ctx);
b32d7a39 1539 return ret;
797ac58c
KW
1540 }
1541 optind++;
1542
5ceb7765
KW
1543 if (ctx->zflag) {
1544 int64_t count = cvtnum(argv[optind]);
1545 if (count < 0) {
1546 print_cvtnum_err(count, argv[optind]);
0e01b76e 1547 g_free(ctx);
b32d7a39 1548 return count;
5ceb7765 1549 }
797ac58c 1550
5ceb7765 1551 ctx->qiov.size = count;
d004bd52
EB
1552 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done,
1553 ctx);
5ceb7765
KW
1554 } else {
1555 nr_iov = argc - optind;
1556 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
1557 pattern);
1558 if (ctx->buf == NULL) {
1559 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1560 g_free(ctx);
b32d7a39 1561 return -EINVAL;
5ceb7765
KW
1562 }
1563
1564 gettimeofday(&ctx->t1, NULL);
1565 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1566 BLOCK_ACCT_WRITE);
1567
770e0e0e
EB
1568 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
1569 ctx);
5ceb7765 1570 }
b32d7a39
HR
1571
1572 return 0;
797ac58c
KW
1573}
1574
b32d7a39 1575static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1576{
556c2b60
AG
1577 BlockAcctCookie cookie;
1578 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
4c7b7e9b 1579 blk_drain_all();
556c2b60 1580 block_acct_done(blk_get_stats(blk), &cookie);
b32d7a39 1581 return 0;
797ac58c
KW
1582}
1583
1584static const cmdinfo_t aio_flush_cmd = {
1585 .name = "aio_flush",
1586 .cfunc = aio_flush_f,
1587 .oneline = "completes all outstanding aio requests"
1588};
1589
b32d7a39 1590static int flush_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1591{
b32d7a39 1592 return blk_flush(blk);
797ac58c
KW
1593}
1594
1595static const cmdinfo_t flush_cmd = {
1596 .name = "flush",
1597 .altname = "f",
1598 .cfunc = flush_f,
1599 .oneline = "flush all in-core file state to disk",
1600};
1601
b32d7a39 1602static int truncate_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1603{
ed3d2ec9 1604 Error *local_err = NULL;
797ac58c
KW
1605 int64_t offset;
1606 int ret;
1607
1608 offset = cvtnum(argv[1]);
1609 if (offset < 0) {
a9ecfa00 1610 print_cvtnum_err(offset, argv[1]);
b32d7a39 1611 return offset;
797ac58c
KW
1612 }
1613
3a691c50 1614 ret = blk_truncate(blk, offset, PREALLOC_MODE_OFF, &local_err);
797ac58c 1615 if (ret < 0) {
ed3d2ec9 1616 error_report_err(local_err);
b32d7a39 1617 return ret;
797ac58c 1618 }
b32d7a39
HR
1619
1620 return 0;
797ac58c
KW
1621}
1622
1623static const cmdinfo_t truncate_cmd = {
1624 .name = "truncate",
1625 .altname = "t",
1626 .cfunc = truncate_f,
887354bd 1627 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
797ac58c
KW
1628 .argmin = 1,
1629 .argmax = 1,
1630 .args = "off",
1631 .oneline = "truncates the current file at the given offset",
1632};
1633
b32d7a39 1634static int length_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1635{
1636 int64_t size;
1637 char s1[64];
1638
4c7b7e9b 1639 size = blk_getlength(blk);
797ac58c
KW
1640 if (size < 0) {
1641 printf("getlength: %s\n", strerror(-size));
b32d7a39 1642 return size;
797ac58c
KW
1643 }
1644
1645 cvtstr(size, s1, sizeof(s1));
1646 printf("%s\n", s1);
b32d7a39 1647 return 0;
797ac58c
KW
1648}
1649
1650
1651static const cmdinfo_t length_cmd = {
1652 .name = "length",
1653 .altname = "l",
1654 .cfunc = length_f,
1655 .oneline = "gets the length of the current file",
1656};
1657
1658
b32d7a39 1659static int info_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1660{
4c7b7e9b 1661 BlockDriverState *bs = blk_bs(blk);
797ac58c 1662 BlockDriverInfo bdi;
a8d8ecb7 1663 ImageInfoSpecific *spec_info;
1bf6e9ca 1664 Error *local_err = NULL;
797ac58c
KW
1665 char s1[64], s2[64];
1666 int ret;
1667
1668 if (bs->drv && bs->drv->format_name) {
1669 printf("format name: %s\n", bs->drv->format_name);
1670 }
1671 if (bs->drv && bs->drv->protocol_name) {
1672 printf("format name: %s\n", bs->drv->protocol_name);
1673 }
1674
1675 ret = bdrv_get_info(bs, &bdi);
1676 if (ret) {
b32d7a39 1677 return ret;
797ac58c
KW
1678 }
1679
1680 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1681 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1682
1683 printf("cluster size: %s\n", s1);
1684 printf("vm state offset: %s\n", s2);
1685
1bf6e9ca
AS
1686 spec_info = bdrv_get_specific_info(bs, &local_err);
1687 if (local_err) {
1688 error_report_err(local_err);
1689 return -EIO;
1690 }
a8d8ecb7
HR
1691 if (spec_info) {
1692 printf("Format specific information:\n");
1693 bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
1694 qapi_free_ImageInfoSpecific(spec_info);
1695 }
b32d7a39
HR
1696
1697 return 0;
797ac58c
KW
1698}
1699
1700
1701
1702static const cmdinfo_t info_cmd = {
1703 .name = "info",
1704 .altname = "i",
1705 .cfunc = info_f,
1706 .oneline = "prints information about the current file",
1707};
1708
1709static void discard_help(void)
1710{
1711 printf(
1712"\n"
1713" discards a range of bytes from the given offset\n"
1714"\n"
1715" Example:\n"
1716" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1717"\n"
1718" Discards a segment of the currently open file.\n"
1719" -C, -- report statistics in a machine parsable format\n"
1720" -q, -- quiet mode, do not show I/O statistics\n"
1721"\n");
1722}
1723
b32d7a39 1724static int discard_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1725
1726static const cmdinfo_t discard_cmd = {
1727 .name = "discard",
1728 .altname = "d",
1729 .cfunc = discard_f,
887354bd 1730 .perm = BLK_PERM_WRITE,
797ac58c
KW
1731 .argmin = 2,
1732 .argmax = -1,
1733 .args = "[-Cq] off len",
1734 .oneline = "discards a number of bytes at a specified offset",
1735 .help = discard_help,
1736};
1737
b32d7a39 1738static int discard_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1739{
1740 struct timeval t1, t2;
dc38852a 1741 bool Cflag = false, qflag = false;
797ac58c 1742 int c, ret;
f5a5ca79 1743 int64_t offset, bytes;
797ac58c 1744
b062ad86 1745 while ((c = getopt(argc, argv, "Cq")) != -1) {
797ac58c
KW
1746 switch (c) {
1747 case 'C':
dc38852a 1748 Cflag = true;
797ac58c
KW
1749 break;
1750 case 'q':
dc38852a 1751 qflag = true;
797ac58c
KW
1752 break;
1753 default:
b444d0e9 1754 qemuio_command_usage(&discard_cmd);
b32d7a39 1755 return -EINVAL;
797ac58c
KW
1756 }
1757 }
1758
1759 if (optind != argc - 2) {
b444d0e9 1760 qemuio_command_usage(&discard_cmd);
b32d7a39 1761 return -EINVAL;
797ac58c
KW
1762 }
1763
1764 offset = cvtnum(argv[optind]);
1765 if (offset < 0) {
a9ecfa00 1766 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1767 return offset;
797ac58c
KW
1768 }
1769
1770 optind++;
f5a5ca79
MP
1771 bytes = cvtnum(argv[optind]);
1772 if (bytes < 0) {
1773 print_cvtnum_err(bytes, argv[optind]);
b32d7a39 1774 return bytes;
f5a5ca79 1775 } else if (bytes >> BDRV_SECTOR_BITS > BDRV_REQUEST_MAX_SECTORS) {
9b0beaf3 1776 printf("length cannot exceed %"PRIu64", given %s\n",
a3674679 1777 (uint64_t)BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS,
9b0beaf3 1778 argv[optind]);
b32d7a39 1779 return -EINVAL;
797ac58c
KW
1780 }
1781
1782 gettimeofday(&t1, NULL);
f5a5ca79 1783 ret = blk_pdiscard(blk, offset, bytes);
797ac58c
KW
1784 gettimeofday(&t2, NULL);
1785
1786 if (ret < 0) {
1787 printf("discard failed: %s\n", strerror(-ret));
b32d7a39 1788 return ret;
797ac58c
KW
1789 }
1790
1791 /* Finally, report back -- -C gives a parsable format */
1792 if (!qflag) {
1793 t2 = tsub(t2, t1);
f5a5ca79 1794 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
797ac58c 1795 }
b32d7a39
HR
1796
1797 return 0;
797ac58c
KW
1798}
1799
b32d7a39 1800static int alloc_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1801{
4c7b7e9b 1802 BlockDriverState *bs = blk_bs(blk);
d6a644bb 1803 int64_t offset, start, remaining, count;
797ac58c 1804 char s1[64];
d6a644bb
EB
1805 int ret;
1806 int64_t num, sum_alloc;
797ac58c 1807
d6a644bb 1808 start = offset = cvtnum(argv[1]);
797ac58c 1809 if (offset < 0) {
a9ecfa00 1810 print_cvtnum_err(offset, argv[1]);
b32d7a39 1811 return offset;
797ac58c
KW
1812 }
1813
1814 if (argc == 3) {
4401fdc7
EB
1815 count = cvtnum(argv[2]);
1816 if (count < 0) {
1817 print_cvtnum_err(count, argv[2]);
b32d7a39 1818 return count;
797ac58c
KW
1819 }
1820 } else {
4401fdc7
EB
1821 count = BDRV_SECTOR_SIZE;
1822 }
797ac58c 1823
d6a644bb 1824 remaining = count;
797ac58c 1825 sum_alloc = 0;
797ac58c 1826 while (remaining) {
d6a644bb 1827 ret = bdrv_is_allocated(bs, offset, remaining, &num);
d663640c
PB
1828 if (ret < 0) {
1829 printf("is_allocated failed: %s\n", strerror(-ret));
b32d7a39 1830 return ret;
d663640c 1831 }
d6a644bb 1832 offset += num;
797ac58c
KW
1833 remaining -= num;
1834 if (ret) {
1835 sum_alloc += num;
1836 }
1837 if (num == 0) {
d6a644bb 1838 count -= remaining;
797ac58c
KW
1839 remaining = 0;
1840 }
1841 }
1842
d6a644bb 1843 cvtstr(start, s1, sizeof(s1));
797ac58c 1844
4401fdc7 1845 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
d6a644bb 1846 sum_alloc, count, s1);
b32d7a39 1847 return 0;
797ac58c
KW
1848}
1849
1850static const cmdinfo_t alloc_cmd = {
1851 .name = "alloc",
1852 .altname = "a",
1853 .argmin = 1,
1854 .argmax = 2,
1855 .cfunc = alloc_f,
4401fdc7
EB
1856 .args = "offset [count]",
1857 .oneline = "checks if offset is allocated in the file",
797ac58c
KW
1858};
1859
1860
d6a644bb
EB
1861static int map_is_allocated(BlockDriverState *bs, int64_t offset,
1862 int64_t bytes, int64_t *pnum)
797ac58c 1863{
d6a644bb
EB
1864 int64_t num;
1865 int num_checked;
797ac58c
KW
1866 int ret, firstret;
1867
d6a644bb
EB
1868 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1869 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
797ac58c
KW
1870 if (ret < 0) {
1871 return ret;
1872 }
1873
1874 firstret = ret;
1875 *pnum = num;
1876
d6a644bb
EB
1877 while (bytes > 0 && ret == firstret) {
1878 offset += num;
1879 bytes -= num;
797ac58c 1880
d6a644bb
EB
1881 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1882 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
4b25bbc4 1883 if (ret == firstret && num) {
797ac58c
KW
1884 *pnum += num;
1885 } else {
1886 break;
1887 }
1888 }
1889
1890 return firstret;
1891}
1892
b32d7a39 1893static int map_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1894{
d6a644bb 1895 int64_t offset, bytes;
6f3c90af 1896 char s1[64], s2[64];
797ac58c
KW
1897 int64_t num;
1898 int ret;
1899 const char *retstr;
1900
1901 offset = 0;
d6a644bb
EB
1902 bytes = blk_getlength(blk);
1903 if (bytes < 0) {
1904 error_report("Failed to query image length: %s", strerror(-bytes));
b32d7a39 1905 return bytes;
4c7b7e9b
HR
1906 }
1907
d6a644bb
EB
1908 while (bytes) {
1909 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
797ac58c
KW
1910 if (ret < 0) {
1911 error_report("Failed to get allocation status: %s", strerror(-ret));
b32d7a39 1912 return ret;
4b25bbc4
HR
1913 } else if (!num) {
1914 error_report("Unexpected end of image");
b32d7a39 1915 return -EIO;
797ac58c
KW
1916 }
1917
1918 retstr = ret ? " allocated" : "not allocated";
d6a644bb
EB
1919 cvtstr(num, s1, sizeof(s1));
1920 cvtstr(offset, s2, sizeof(s2));
6f3c90af 1921 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
d6a644bb 1922 s1, num, retstr, s2, offset);
797ac58c
KW
1923
1924 offset += num;
d6a644bb
EB
1925 bytes -= num;
1926 }
b32d7a39
HR
1927
1928 return 0;
797ac58c
KW
1929}
1930
1931static const cmdinfo_t map_cmd = {
1932 .name = "map",
1933 .argmin = 0,
1934 .argmax = 0,
1935 .cfunc = map_f,
1936 .args = "",
1937 .oneline = "prints the allocated areas of a file",
1938};
1939
5bbd2e59
KW
1940static void reopen_help(void)
1941{
1942 printf(
1943"\n"
1944" Changes the open options of an already opened image\n"
1945"\n"
1946" Example:\n"
1947" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
1948"\n"
1949" -r, -- Reopen the image read-only\n"
ea92203c 1950" -w, -- Reopen the image read-write\n"
5bbd2e59
KW
1951" -c, -- Change the cache mode to the given value\n"
1952" -o, -- Changes block driver options (cf. 'open' command)\n"
1953"\n");
1954}
1955
b32d7a39 1956static int reopen_f(BlockBackend *blk, int argc, char **argv);
5bbd2e59
KW
1957
1958static QemuOptsList reopen_opts = {
1959 .name = "reopen",
1960 .merge_lists = true,
1961 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
1962 .desc = {
1963 /* no elements => accept any params */
1964 { /* end of list */ }
1965 },
1966};
1967
1968static const cmdinfo_t reopen_cmd = {
1969 .name = "reopen",
1970 .argmin = 0,
1971 .argmax = -1,
1972 .cfunc = reopen_f,
ea92203c 1973 .args = "[(-r|-w)] [-c cache] [-o options]",
5bbd2e59
KW
1974 .oneline = "reopens an image with new options",
1975 .help = reopen_help,
1976};
1977
b32d7a39 1978static int reopen_f(BlockBackend *blk, int argc, char **argv)
5bbd2e59
KW
1979{
1980 BlockDriverState *bs = blk_bs(blk);
1981 QemuOpts *qopts;
1982 QDict *opts;
1983 int c;
1984 int flags = bs->open_flags;
19dbecdc 1985 bool writethrough = !blk_enable_write_cache(blk);
ea92203c 1986 bool has_rw_option = false;
dc900c35 1987 bool has_cache_option = false;
5bbd2e59
KW
1988
1989 BlockReopenQueue *brq;
1990 Error *local_err = NULL;
1991
ea92203c 1992 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
5bbd2e59
KW
1993 switch (c) {
1994 case 'c':
19dbecdc 1995 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
5bbd2e59 1996 error_report("Invalid cache option: %s", optarg);
b32d7a39 1997 return -EINVAL;
5bbd2e59 1998 }
dc900c35 1999 has_cache_option = true;
5bbd2e59
KW
2000 break;
2001 case 'o':
2002 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2003 qemu_opts_reset(&reopen_opts);
b32d7a39 2004 return -EINVAL;
5bbd2e59
KW
2005 }
2006 break;
2007 case 'r':
ea92203c
KW
2008 if (has_rw_option) {
2009 error_report("Only one -r/-w option may be given");
b32d7a39 2010 return -EINVAL;
ea92203c 2011 }
5bbd2e59 2012 flags &= ~BDRV_O_RDWR;
ea92203c
KW
2013 has_rw_option = true;
2014 break;
2015 case 'w':
2016 if (has_rw_option) {
2017 error_report("Only one -r/-w option may be given");
b32d7a39 2018 return -EINVAL;
ea92203c
KW
2019 }
2020 flags |= BDRV_O_RDWR;
2021 has_rw_option = true;
5bbd2e59
KW
2022 break;
2023 default:
2024 qemu_opts_reset(&reopen_opts);
b444d0e9 2025 qemuio_command_usage(&reopen_cmd);
b32d7a39 2026 return -EINVAL;
5bbd2e59
KW
2027 }
2028 }
2029
2030 if (optind != argc) {
2031 qemu_opts_reset(&reopen_opts);
b444d0e9 2032 qemuio_command_usage(&reopen_cmd);
b32d7a39 2033 return -EINVAL;
5bbd2e59
KW
2034 }
2035
a8003ec4 2036 if (!writethrough != blk_enable_write_cache(blk) &&
19dbecdc
KW
2037 blk_get_attached_dev(blk))
2038 {
2039 error_report("Cannot change cache.writeback: Device attached");
2040 qemu_opts_reset(&reopen_opts);
b32d7a39 2041 return -EBUSY;
19dbecdc
KW
2042 }
2043
f3adefb2
KW
2044 if (!(flags & BDRV_O_RDWR)) {
2045 uint64_t orig_perm, orig_shared_perm;
2046
2047 bdrv_drain(bs);
2048
2049 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2050 blk_set_perm(blk,
2051 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2052 orig_shared_perm,
2053 &error_abort);
2054 }
2055
5bbd2e59 2056 qopts = qemu_opts_find(&reopen_opts, NULL);
dc900c35 2057 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
5bbd2e59
KW
2058 qemu_opts_reset(&reopen_opts);
2059
dc900c35
AG
2060 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2061 if (has_rw_option) {
2062 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2063 qobject_unref(opts);
2064 return -EINVAL;
2065 }
2066 } else {
2067 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2068 }
2069
2070 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2071 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2072 if (has_cache_option) {
2073 error_report("Cannot set both -c and the cache options");
2074 qobject_unref(opts);
2075 return -EINVAL;
2076 }
2077 } else {
2078 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2079 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2080 }
2081
1a63a907 2082 bdrv_subtree_drained_begin(bs);
2e891722 2083 brq = bdrv_reopen_queue(NULL, bs, opts);
720150f3 2084 bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
1a63a907
KW
2085 bdrv_subtree_drained_end(bs);
2086
5bbd2e59
KW
2087 if (local_err) {
2088 error_report_err(local_err);
b32d7a39 2089 return -EINVAL;
5bbd2e59 2090 }
b32d7a39
HR
2091
2092 blk_set_enable_write_cache(blk, !writethrough);
2093 return 0;
5bbd2e59
KW
2094}
2095
b32d7a39 2096static int break_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2097{
2098 int ret;
2099
4c7b7e9b 2100 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
797ac58c
KW
2101 if (ret < 0) {
2102 printf("Could not set breakpoint: %s\n", strerror(-ret));
b32d7a39 2103 return ret;
797ac58c 2104 }
b32d7a39
HR
2105
2106 return 0;
797ac58c
KW
2107}
2108
b32d7a39 2109static int remove_break_f(BlockBackend *blk, int argc, char **argv)
4cc70e93
FZ
2110{
2111 int ret;
2112
4c7b7e9b 2113 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
4cc70e93
FZ
2114 if (ret < 0) {
2115 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
b32d7a39 2116 return ret;
4cc70e93 2117 }
b32d7a39
HR
2118
2119 return 0;
4cc70e93
FZ
2120}
2121
797ac58c
KW
2122static const cmdinfo_t break_cmd = {
2123 .name = "break",
2124 .argmin = 2,
2125 .argmax = 2,
2126 .cfunc = break_f,
2127 .args = "event tag",
2128 .oneline = "sets a breakpoint on event and tags the stopped "
2129 "request as tag",
2130};
2131
4cc70e93
FZ
2132static const cmdinfo_t remove_break_cmd = {
2133 .name = "remove_break",
2134 .argmin = 1,
2135 .argmax = 1,
2136 .cfunc = remove_break_f,
2137 .args = "tag",
2138 .oneline = "remove a breakpoint by tag",
2139};
2140
b32d7a39 2141static int resume_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2142{
2143 int ret;
2144
4c7b7e9b 2145 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
797ac58c
KW
2146 if (ret < 0) {
2147 printf("Could not resume request: %s\n", strerror(-ret));
b32d7a39 2148 return ret;
797ac58c 2149 }
b32d7a39
HR
2150
2151 return 0;
797ac58c
KW
2152}
2153
2154static const cmdinfo_t resume_cmd = {
2155 .name = "resume",
2156 .argmin = 1,
2157 .argmax = 1,
2158 .cfunc = resume_f,
2159 .args = "tag",
2160 .oneline = "resumes the request tagged as tag",
2161};
2162
b32d7a39 2163static int wait_break_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2164{
4c7b7e9b
HR
2165 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2166 aio_poll(blk_get_aio_context(blk), true);
797ac58c 2167 }
b32d7a39 2168 return 0;
797ac58c
KW
2169}
2170
2171static const cmdinfo_t wait_break_cmd = {
2172 .name = "wait_break",
2173 .argmin = 1,
2174 .argmax = 1,
2175 .cfunc = wait_break_f,
2176 .args = "tag",
2177 .oneline = "waits for the suspension of a request",
2178};
2179
b32d7a39 2180static int abort_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2181{
2182 abort();
2183}
2184
2185static const cmdinfo_t abort_cmd = {
2186 .name = "abort",
2187 .cfunc = abort_f,
2188 .flags = CMD_NOFILE_OK,
2189 .oneline = "simulate a program crash using abort(3)",
2190};
2191
0e82dc7b
HR
2192static void sigraise_help(void)
2193{
2194 printf(
2195"\n"
2196" raises the given signal\n"
2197"\n"
2198" Example:\n"
2199" 'sigraise %i' - raises SIGTERM\n"
2200"\n"
2201" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2202" given to sigraise.\n"
2203"\n", SIGTERM);
2204}
2205
b32d7a39 2206static int sigraise_f(BlockBackend *blk, int argc, char **argv);
0e82dc7b
HR
2207
2208static const cmdinfo_t sigraise_cmd = {
2209 .name = "sigraise",
2210 .cfunc = sigraise_f,
2211 .argmin = 1,
2212 .argmax = 1,
2213 .flags = CMD_NOFILE_OK,
2214 .args = "signal",
2215 .oneline = "raises a signal",
2216 .help = sigraise_help,
2217};
2218
b32d7a39 2219static int sigraise_f(BlockBackend *blk, int argc, char **argv)
0e82dc7b 2220{
9b0beaf3 2221 int64_t sig = cvtnum(argv[1]);
0e82dc7b 2222 if (sig < 0) {
a9ecfa00 2223 print_cvtnum_err(sig, argv[1]);
b32d7a39 2224 return sig;
9b0beaf3
JS
2225 } else if (sig > NSIG) {
2226 printf("signal argument '%s' is too large to be a valid signal\n",
2227 argv[1]);
b32d7a39 2228 return -EINVAL;
0e82dc7b
HR
2229 }
2230
2231 /* Using raise() to kill this process does not necessarily flush all open
2232 * streams. At least stdout and stderr (although the latter should be
2233 * non-buffered anyway) should be flushed, though. */
2234 fflush(stdout);
2235 fflush(stderr);
2236
2237 raise(sig);
b32d7a39
HR
2238
2239 return 0;
0e82dc7b
HR
2240}
2241
cd33d02a
KW
2242static void sleep_cb(void *opaque)
2243{
2244 bool *expired = opaque;
2245 *expired = true;
2246}
2247
b32d7a39 2248static int sleep_f(BlockBackend *blk, int argc, char **argv)
cd33d02a
KW
2249{
2250 char *endptr;
2251 long ms;
2252 struct QEMUTimer *timer;
2253 bool expired = false;
2254
2255 ms = strtol(argv[1], &endptr, 0);
2256 if (ms < 0 || *endptr != '\0') {
2257 printf("%s is not a valid number\n", argv[1]);
b32d7a39 2258 return -EINVAL;
cd33d02a
KW
2259 }
2260
2261 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2262 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2263
2264 while (!expired) {
2265 main_loop_wait(false);
2266 }
2267
2268 timer_free(timer);
b32d7a39 2269 return 0;
cd33d02a
KW
2270}
2271
2272static const cmdinfo_t sleep_cmd = {
2273 .name = "sleep",
2274 .argmin = 1,
2275 .argmax = 1,
2276 .cfunc = sleep_f,
2277 .flags = CMD_NOFILE_OK,
2278 .oneline = "waits for the given value in milliseconds",
2279};
2280
f18a834a
KW
2281static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2282{
2283 if (cmd) {
2284 printf("%s ", cmd);
2285 } else {
2286 printf("%s ", ct->name);
2287 if (ct->altname) {
2288 printf("(or %s) ", ct->altname);
2289 }
2290 }
2291
2292 if (ct->args) {
2293 printf("%s ", ct->args);
2294 }
2295 printf("-- %s\n", ct->oneline);
2296}
2297
2298static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2299{
2300 help_oneline(cmd, ct);
2301 if (ct->help) {
2302 ct->help();
2303 }
2304}
2305
2306static void help_all(void)
2307{
2308 const cmdinfo_t *ct;
2309
2310 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2311 help_oneline(ct->name, ct);
2312 }
2313 printf("\nUse 'help commandname' for extended help.\n");
2314}
2315
b32d7a39 2316static int help_f(BlockBackend *blk, int argc, char **argv)
f18a834a
KW
2317{
2318 const cmdinfo_t *ct;
2319
2320 if (argc == 1) {
2321 help_all();
b32d7a39 2322 return 0;
f18a834a
KW
2323 }
2324
2325 ct = find_command(argv[1]);
2326 if (ct == NULL) {
2327 printf("command %s not found\n", argv[1]);
b32d7a39 2328 return -EINVAL;
f18a834a
KW
2329 }
2330
2331 help_onecmd(argv[1], ct);
b32d7a39 2332 return 0;
f18a834a
KW
2333}
2334
2335static const cmdinfo_t help_cmd = {
2336 .name = "help",
2337 .altname = "?",
2338 .cfunc = help_f,
2339 .argmin = 0,
2340 .argmax = 1,
2341 .flags = CMD_FLAG_GLOBAL,
2342 .args = "[command]",
2343 .oneline = "help for one or all commands",
2344};
2345
b32d7a39 2346int qemuio_command(BlockBackend *blk, const char *cmd)
dd583296 2347{
15afd94a 2348 AioContext *ctx;
dd583296
KW
2349 char *input;
2350 const cmdinfo_t *ct;
2351 char **v;
2352 int c;
b32d7a39 2353 int ret = 0;
dd583296
KW
2354
2355 input = g_strdup(cmd);
2356 v = breakline(input, &c);
2357 if (c) {
2358 ct = find_command(v[0]);
2359 if (ct) {
15afd94a
PB
2360 ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
2361 aio_context_acquire(ctx);
b32d7a39 2362 ret = command(blk, ct, c, v);
15afd94a 2363 aio_context_release(ctx);
dd583296
KW
2364 } else {
2365 fprintf(stderr, "command \"%s\" not found\n", v[0]);
b32d7a39 2366 ret = -EINVAL;
dd583296
KW
2367 }
2368 }
2369 g_free(input);
2370 g_free(v);
b32d7a39
HR
2371
2372 return ret;
dd583296
KW
2373}
2374
797ac58c
KW
2375static void __attribute((constructor)) init_qemuio_commands(void)
2376{
2377 /* initialize commands */
c2cdf5c5
KW
2378 qemuio_add_command(&help_cmd);
2379 qemuio_add_command(&read_cmd);
2380 qemuio_add_command(&readv_cmd);
2381 qemuio_add_command(&write_cmd);
2382 qemuio_add_command(&writev_cmd);
c2cdf5c5
KW
2383 qemuio_add_command(&aio_read_cmd);
2384 qemuio_add_command(&aio_write_cmd);
2385 qemuio_add_command(&aio_flush_cmd);
2386 qemuio_add_command(&flush_cmd);
2387 qemuio_add_command(&truncate_cmd);
2388 qemuio_add_command(&length_cmd);
2389 qemuio_add_command(&info_cmd);
2390 qemuio_add_command(&discard_cmd);
2391 qemuio_add_command(&alloc_cmd);
2392 qemuio_add_command(&map_cmd);
5bbd2e59 2393 qemuio_add_command(&reopen_cmd);
c2cdf5c5 2394 qemuio_add_command(&break_cmd);
4cc70e93 2395 qemuio_add_command(&remove_break_cmd);
c2cdf5c5
KW
2396 qemuio_add_command(&resume_cmd);
2397 qemuio_add_command(&wait_break_cmd);
2398 qemuio_add_command(&abort_cmd);
cd33d02a 2399 qemuio_add_command(&sleep_cmd);
0e82dc7b 2400 qemuio_add_command(&sigraise_cmd);
797ac58c 2401}