]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-io-cmds.c
elf: Add optional function ptr to load_elf() to parse ELF notes
[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;
797ac58c
KW
1664 char s1[64], s2[64];
1665 int ret;
1666
1667 if (bs->drv && bs->drv->format_name) {
1668 printf("format name: %s\n", bs->drv->format_name);
1669 }
1670 if (bs->drv && bs->drv->protocol_name) {
1671 printf("format name: %s\n", bs->drv->protocol_name);
1672 }
1673
1674 ret = bdrv_get_info(bs, &bdi);
1675 if (ret) {
b32d7a39 1676 return ret;
797ac58c
KW
1677 }
1678
1679 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1680 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1681
1682 printf("cluster size: %s\n", s1);
1683 printf("vm state offset: %s\n", s2);
1684
a8d8ecb7
HR
1685 spec_info = bdrv_get_specific_info(bs);
1686 if (spec_info) {
1687 printf("Format specific information:\n");
1688 bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
1689 qapi_free_ImageInfoSpecific(spec_info);
1690 }
b32d7a39
HR
1691
1692 return 0;
797ac58c
KW
1693}
1694
1695
1696
1697static const cmdinfo_t info_cmd = {
1698 .name = "info",
1699 .altname = "i",
1700 .cfunc = info_f,
1701 .oneline = "prints information about the current file",
1702};
1703
1704static void discard_help(void)
1705{
1706 printf(
1707"\n"
1708" discards a range of bytes from the given offset\n"
1709"\n"
1710" Example:\n"
1711" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1712"\n"
1713" Discards a segment of the currently open file.\n"
1714" -C, -- report statistics in a machine parsable format\n"
1715" -q, -- quiet mode, do not show I/O statistics\n"
1716"\n");
1717}
1718
b32d7a39 1719static int discard_f(BlockBackend *blk, int argc, char **argv);
797ac58c
KW
1720
1721static const cmdinfo_t discard_cmd = {
1722 .name = "discard",
1723 .altname = "d",
1724 .cfunc = discard_f,
887354bd 1725 .perm = BLK_PERM_WRITE,
797ac58c
KW
1726 .argmin = 2,
1727 .argmax = -1,
1728 .args = "[-Cq] off len",
1729 .oneline = "discards a number of bytes at a specified offset",
1730 .help = discard_help,
1731};
1732
b32d7a39 1733static int discard_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
1734{
1735 struct timeval t1, t2;
dc38852a 1736 bool Cflag = false, qflag = false;
797ac58c 1737 int c, ret;
f5a5ca79 1738 int64_t offset, bytes;
797ac58c 1739
b062ad86 1740 while ((c = getopt(argc, argv, "Cq")) != -1) {
797ac58c
KW
1741 switch (c) {
1742 case 'C':
dc38852a 1743 Cflag = true;
797ac58c
KW
1744 break;
1745 case 'q':
dc38852a 1746 qflag = true;
797ac58c
KW
1747 break;
1748 default:
b444d0e9 1749 qemuio_command_usage(&discard_cmd);
b32d7a39 1750 return -EINVAL;
797ac58c
KW
1751 }
1752 }
1753
1754 if (optind != argc - 2) {
b444d0e9 1755 qemuio_command_usage(&discard_cmd);
b32d7a39 1756 return -EINVAL;
797ac58c
KW
1757 }
1758
1759 offset = cvtnum(argv[optind]);
1760 if (offset < 0) {
a9ecfa00 1761 print_cvtnum_err(offset, argv[optind]);
b32d7a39 1762 return offset;
797ac58c
KW
1763 }
1764
1765 optind++;
f5a5ca79
MP
1766 bytes = cvtnum(argv[optind]);
1767 if (bytes < 0) {
1768 print_cvtnum_err(bytes, argv[optind]);
b32d7a39 1769 return bytes;
f5a5ca79 1770 } else if (bytes >> BDRV_SECTOR_BITS > BDRV_REQUEST_MAX_SECTORS) {
9b0beaf3 1771 printf("length cannot exceed %"PRIu64", given %s\n",
a3674679 1772 (uint64_t)BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS,
9b0beaf3 1773 argv[optind]);
b32d7a39 1774 return -EINVAL;
797ac58c
KW
1775 }
1776
1777 gettimeofday(&t1, NULL);
f5a5ca79 1778 ret = blk_pdiscard(blk, offset, bytes);
797ac58c
KW
1779 gettimeofday(&t2, NULL);
1780
1781 if (ret < 0) {
1782 printf("discard failed: %s\n", strerror(-ret));
b32d7a39 1783 return ret;
797ac58c
KW
1784 }
1785
1786 /* Finally, report back -- -C gives a parsable format */
1787 if (!qflag) {
1788 t2 = tsub(t2, t1);
f5a5ca79 1789 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
797ac58c 1790 }
b32d7a39
HR
1791
1792 return 0;
797ac58c
KW
1793}
1794
b32d7a39 1795static int alloc_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1796{
4c7b7e9b 1797 BlockDriverState *bs = blk_bs(blk);
d6a644bb 1798 int64_t offset, start, remaining, count;
797ac58c 1799 char s1[64];
d6a644bb
EB
1800 int ret;
1801 int64_t num, sum_alloc;
797ac58c 1802
d6a644bb 1803 start = offset = cvtnum(argv[1]);
797ac58c 1804 if (offset < 0) {
a9ecfa00 1805 print_cvtnum_err(offset, argv[1]);
b32d7a39 1806 return offset;
797ac58c
KW
1807 }
1808
1809 if (argc == 3) {
4401fdc7
EB
1810 count = cvtnum(argv[2]);
1811 if (count < 0) {
1812 print_cvtnum_err(count, argv[2]);
b32d7a39 1813 return count;
797ac58c
KW
1814 }
1815 } else {
4401fdc7
EB
1816 count = BDRV_SECTOR_SIZE;
1817 }
797ac58c 1818
d6a644bb 1819 remaining = count;
797ac58c 1820 sum_alloc = 0;
797ac58c 1821 while (remaining) {
d6a644bb 1822 ret = bdrv_is_allocated(bs, offset, remaining, &num);
d663640c
PB
1823 if (ret < 0) {
1824 printf("is_allocated failed: %s\n", strerror(-ret));
b32d7a39 1825 return ret;
d663640c 1826 }
d6a644bb 1827 offset += num;
797ac58c
KW
1828 remaining -= num;
1829 if (ret) {
1830 sum_alloc += num;
1831 }
1832 if (num == 0) {
d6a644bb 1833 count -= remaining;
797ac58c
KW
1834 remaining = 0;
1835 }
1836 }
1837
d6a644bb 1838 cvtstr(start, s1, sizeof(s1));
797ac58c 1839
4401fdc7 1840 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
d6a644bb 1841 sum_alloc, count, s1);
b32d7a39 1842 return 0;
797ac58c
KW
1843}
1844
1845static const cmdinfo_t alloc_cmd = {
1846 .name = "alloc",
1847 .altname = "a",
1848 .argmin = 1,
1849 .argmax = 2,
1850 .cfunc = alloc_f,
4401fdc7
EB
1851 .args = "offset [count]",
1852 .oneline = "checks if offset is allocated in the file",
797ac58c
KW
1853};
1854
1855
d6a644bb
EB
1856static int map_is_allocated(BlockDriverState *bs, int64_t offset,
1857 int64_t bytes, int64_t *pnum)
797ac58c 1858{
d6a644bb
EB
1859 int64_t num;
1860 int num_checked;
797ac58c
KW
1861 int ret, firstret;
1862
d6a644bb
EB
1863 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1864 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
797ac58c
KW
1865 if (ret < 0) {
1866 return ret;
1867 }
1868
1869 firstret = ret;
1870 *pnum = num;
1871
d6a644bb
EB
1872 while (bytes > 0 && ret == firstret) {
1873 offset += num;
1874 bytes -= num;
797ac58c 1875
d6a644bb
EB
1876 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1877 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
4b25bbc4 1878 if (ret == firstret && num) {
797ac58c
KW
1879 *pnum += num;
1880 } else {
1881 break;
1882 }
1883 }
1884
1885 return firstret;
1886}
1887
b32d7a39 1888static int map_f(BlockBackend *blk, int argc, char **argv)
797ac58c 1889{
d6a644bb 1890 int64_t offset, bytes;
6f3c90af 1891 char s1[64], s2[64];
797ac58c
KW
1892 int64_t num;
1893 int ret;
1894 const char *retstr;
1895
1896 offset = 0;
d6a644bb
EB
1897 bytes = blk_getlength(blk);
1898 if (bytes < 0) {
1899 error_report("Failed to query image length: %s", strerror(-bytes));
b32d7a39 1900 return bytes;
4c7b7e9b
HR
1901 }
1902
d6a644bb
EB
1903 while (bytes) {
1904 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
797ac58c
KW
1905 if (ret < 0) {
1906 error_report("Failed to get allocation status: %s", strerror(-ret));
b32d7a39 1907 return ret;
4b25bbc4
HR
1908 } else if (!num) {
1909 error_report("Unexpected end of image");
b32d7a39 1910 return -EIO;
797ac58c
KW
1911 }
1912
1913 retstr = ret ? " allocated" : "not allocated";
d6a644bb
EB
1914 cvtstr(num, s1, sizeof(s1));
1915 cvtstr(offset, s2, sizeof(s2));
6f3c90af 1916 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
d6a644bb 1917 s1, num, retstr, s2, offset);
797ac58c
KW
1918
1919 offset += num;
d6a644bb
EB
1920 bytes -= num;
1921 }
b32d7a39
HR
1922
1923 return 0;
797ac58c
KW
1924}
1925
1926static const cmdinfo_t map_cmd = {
1927 .name = "map",
1928 .argmin = 0,
1929 .argmax = 0,
1930 .cfunc = map_f,
1931 .args = "",
1932 .oneline = "prints the allocated areas of a file",
1933};
1934
5bbd2e59
KW
1935static void reopen_help(void)
1936{
1937 printf(
1938"\n"
1939" Changes the open options of an already opened image\n"
1940"\n"
1941" Example:\n"
1942" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
1943"\n"
1944" -r, -- Reopen the image read-only\n"
ea92203c 1945" -w, -- Reopen the image read-write\n"
5bbd2e59
KW
1946" -c, -- Change the cache mode to the given value\n"
1947" -o, -- Changes block driver options (cf. 'open' command)\n"
1948"\n");
1949}
1950
b32d7a39 1951static int reopen_f(BlockBackend *blk, int argc, char **argv);
5bbd2e59
KW
1952
1953static QemuOptsList reopen_opts = {
1954 .name = "reopen",
1955 .merge_lists = true,
1956 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
1957 .desc = {
1958 /* no elements => accept any params */
1959 { /* end of list */ }
1960 },
1961};
1962
1963static const cmdinfo_t reopen_cmd = {
1964 .name = "reopen",
1965 .argmin = 0,
1966 .argmax = -1,
1967 .cfunc = reopen_f,
ea92203c 1968 .args = "[(-r|-w)] [-c cache] [-o options]",
5bbd2e59
KW
1969 .oneline = "reopens an image with new options",
1970 .help = reopen_help,
1971};
1972
b32d7a39 1973static int reopen_f(BlockBackend *blk, int argc, char **argv)
5bbd2e59
KW
1974{
1975 BlockDriverState *bs = blk_bs(blk);
1976 QemuOpts *qopts;
1977 QDict *opts;
1978 int c;
1979 int flags = bs->open_flags;
19dbecdc 1980 bool writethrough = !blk_enable_write_cache(blk);
ea92203c 1981 bool has_rw_option = false;
dc900c35 1982 bool has_cache_option = false;
5bbd2e59
KW
1983
1984 BlockReopenQueue *brq;
1985 Error *local_err = NULL;
1986
ea92203c 1987 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
5bbd2e59
KW
1988 switch (c) {
1989 case 'c':
19dbecdc 1990 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
5bbd2e59 1991 error_report("Invalid cache option: %s", optarg);
b32d7a39 1992 return -EINVAL;
5bbd2e59 1993 }
dc900c35 1994 has_cache_option = true;
5bbd2e59
KW
1995 break;
1996 case 'o':
1997 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
1998 qemu_opts_reset(&reopen_opts);
b32d7a39 1999 return -EINVAL;
5bbd2e59
KW
2000 }
2001 break;
2002 case 'r':
ea92203c
KW
2003 if (has_rw_option) {
2004 error_report("Only one -r/-w option may be given");
b32d7a39 2005 return -EINVAL;
ea92203c 2006 }
5bbd2e59 2007 flags &= ~BDRV_O_RDWR;
ea92203c
KW
2008 has_rw_option = true;
2009 break;
2010 case 'w':
2011 if (has_rw_option) {
2012 error_report("Only one -r/-w option may be given");
b32d7a39 2013 return -EINVAL;
ea92203c
KW
2014 }
2015 flags |= BDRV_O_RDWR;
2016 has_rw_option = true;
5bbd2e59
KW
2017 break;
2018 default:
2019 qemu_opts_reset(&reopen_opts);
b444d0e9 2020 qemuio_command_usage(&reopen_cmd);
b32d7a39 2021 return -EINVAL;
5bbd2e59
KW
2022 }
2023 }
2024
2025 if (optind != argc) {
2026 qemu_opts_reset(&reopen_opts);
b444d0e9 2027 qemuio_command_usage(&reopen_cmd);
b32d7a39 2028 return -EINVAL;
5bbd2e59
KW
2029 }
2030
a8003ec4 2031 if (!writethrough != blk_enable_write_cache(blk) &&
19dbecdc
KW
2032 blk_get_attached_dev(blk))
2033 {
2034 error_report("Cannot change cache.writeback: Device attached");
2035 qemu_opts_reset(&reopen_opts);
b32d7a39 2036 return -EBUSY;
19dbecdc
KW
2037 }
2038
f3adefb2
KW
2039 if (!(flags & BDRV_O_RDWR)) {
2040 uint64_t orig_perm, orig_shared_perm;
2041
2042 bdrv_drain(bs);
2043
2044 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2045 blk_set_perm(blk,
2046 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2047 orig_shared_perm,
2048 &error_abort);
2049 }
2050
5bbd2e59 2051 qopts = qemu_opts_find(&reopen_opts, NULL);
dc900c35 2052 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
5bbd2e59
KW
2053 qemu_opts_reset(&reopen_opts);
2054
dc900c35
AG
2055 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2056 if (has_rw_option) {
2057 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2058 qobject_unref(opts);
2059 return -EINVAL;
2060 }
2061 } else {
2062 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2063 }
2064
2065 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2066 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2067 if (has_cache_option) {
2068 error_report("Cannot set both -c and the cache options");
2069 qobject_unref(opts);
2070 return -EINVAL;
2071 }
2072 } else {
2073 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2074 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2075 }
2076
1a63a907 2077 bdrv_subtree_drained_begin(bs);
2e891722 2078 brq = bdrv_reopen_queue(NULL, bs, opts);
720150f3 2079 bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
1a63a907
KW
2080 bdrv_subtree_drained_end(bs);
2081
5bbd2e59
KW
2082 if (local_err) {
2083 error_report_err(local_err);
b32d7a39 2084 return -EINVAL;
5bbd2e59 2085 }
b32d7a39
HR
2086
2087 blk_set_enable_write_cache(blk, !writethrough);
2088 return 0;
5bbd2e59
KW
2089}
2090
b32d7a39 2091static int break_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2092{
2093 int ret;
2094
4c7b7e9b 2095 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
797ac58c
KW
2096 if (ret < 0) {
2097 printf("Could not set breakpoint: %s\n", strerror(-ret));
b32d7a39 2098 return ret;
797ac58c 2099 }
b32d7a39
HR
2100
2101 return 0;
797ac58c
KW
2102}
2103
b32d7a39 2104static int remove_break_f(BlockBackend *blk, int argc, char **argv)
4cc70e93
FZ
2105{
2106 int ret;
2107
4c7b7e9b 2108 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
4cc70e93
FZ
2109 if (ret < 0) {
2110 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
b32d7a39 2111 return ret;
4cc70e93 2112 }
b32d7a39
HR
2113
2114 return 0;
4cc70e93
FZ
2115}
2116
797ac58c
KW
2117static const cmdinfo_t break_cmd = {
2118 .name = "break",
2119 .argmin = 2,
2120 .argmax = 2,
2121 .cfunc = break_f,
2122 .args = "event tag",
2123 .oneline = "sets a breakpoint on event and tags the stopped "
2124 "request as tag",
2125};
2126
4cc70e93
FZ
2127static const cmdinfo_t remove_break_cmd = {
2128 .name = "remove_break",
2129 .argmin = 1,
2130 .argmax = 1,
2131 .cfunc = remove_break_f,
2132 .args = "tag",
2133 .oneline = "remove a breakpoint by tag",
2134};
2135
b32d7a39 2136static int resume_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2137{
2138 int ret;
2139
4c7b7e9b 2140 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
797ac58c
KW
2141 if (ret < 0) {
2142 printf("Could not resume request: %s\n", strerror(-ret));
b32d7a39 2143 return ret;
797ac58c 2144 }
b32d7a39
HR
2145
2146 return 0;
797ac58c
KW
2147}
2148
2149static const cmdinfo_t resume_cmd = {
2150 .name = "resume",
2151 .argmin = 1,
2152 .argmax = 1,
2153 .cfunc = resume_f,
2154 .args = "tag",
2155 .oneline = "resumes the request tagged as tag",
2156};
2157
b32d7a39 2158static int wait_break_f(BlockBackend *blk, int argc, char **argv)
797ac58c 2159{
4c7b7e9b
HR
2160 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2161 aio_poll(blk_get_aio_context(blk), true);
797ac58c 2162 }
b32d7a39 2163 return 0;
797ac58c
KW
2164}
2165
2166static const cmdinfo_t wait_break_cmd = {
2167 .name = "wait_break",
2168 .argmin = 1,
2169 .argmax = 1,
2170 .cfunc = wait_break_f,
2171 .args = "tag",
2172 .oneline = "waits for the suspension of a request",
2173};
2174
b32d7a39 2175static int abort_f(BlockBackend *blk, int argc, char **argv)
797ac58c
KW
2176{
2177 abort();
2178}
2179
2180static const cmdinfo_t abort_cmd = {
2181 .name = "abort",
2182 .cfunc = abort_f,
2183 .flags = CMD_NOFILE_OK,
2184 .oneline = "simulate a program crash using abort(3)",
2185};
2186
0e82dc7b
HR
2187static void sigraise_help(void)
2188{
2189 printf(
2190"\n"
2191" raises the given signal\n"
2192"\n"
2193" Example:\n"
2194" 'sigraise %i' - raises SIGTERM\n"
2195"\n"
2196" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2197" given to sigraise.\n"
2198"\n", SIGTERM);
2199}
2200
b32d7a39 2201static int sigraise_f(BlockBackend *blk, int argc, char **argv);
0e82dc7b
HR
2202
2203static const cmdinfo_t sigraise_cmd = {
2204 .name = "sigraise",
2205 .cfunc = sigraise_f,
2206 .argmin = 1,
2207 .argmax = 1,
2208 .flags = CMD_NOFILE_OK,
2209 .args = "signal",
2210 .oneline = "raises a signal",
2211 .help = sigraise_help,
2212};
2213
b32d7a39 2214static int sigraise_f(BlockBackend *blk, int argc, char **argv)
0e82dc7b 2215{
9b0beaf3 2216 int64_t sig = cvtnum(argv[1]);
0e82dc7b 2217 if (sig < 0) {
a9ecfa00 2218 print_cvtnum_err(sig, argv[1]);
b32d7a39 2219 return sig;
9b0beaf3
JS
2220 } else if (sig > NSIG) {
2221 printf("signal argument '%s' is too large to be a valid signal\n",
2222 argv[1]);
b32d7a39 2223 return -EINVAL;
0e82dc7b
HR
2224 }
2225
2226 /* Using raise() to kill this process does not necessarily flush all open
2227 * streams. At least stdout and stderr (although the latter should be
2228 * non-buffered anyway) should be flushed, though. */
2229 fflush(stdout);
2230 fflush(stderr);
2231
2232 raise(sig);
b32d7a39
HR
2233
2234 return 0;
0e82dc7b
HR
2235}
2236
cd33d02a
KW
2237static void sleep_cb(void *opaque)
2238{
2239 bool *expired = opaque;
2240 *expired = true;
2241}
2242
b32d7a39 2243static int sleep_f(BlockBackend *blk, int argc, char **argv)
cd33d02a
KW
2244{
2245 char *endptr;
2246 long ms;
2247 struct QEMUTimer *timer;
2248 bool expired = false;
2249
2250 ms = strtol(argv[1], &endptr, 0);
2251 if (ms < 0 || *endptr != '\0') {
2252 printf("%s is not a valid number\n", argv[1]);
b32d7a39 2253 return -EINVAL;
cd33d02a
KW
2254 }
2255
2256 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2257 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2258
2259 while (!expired) {
2260 main_loop_wait(false);
2261 }
2262
2263 timer_free(timer);
b32d7a39 2264 return 0;
cd33d02a
KW
2265}
2266
2267static const cmdinfo_t sleep_cmd = {
2268 .name = "sleep",
2269 .argmin = 1,
2270 .argmax = 1,
2271 .cfunc = sleep_f,
2272 .flags = CMD_NOFILE_OK,
2273 .oneline = "waits for the given value in milliseconds",
2274};
2275
f18a834a
KW
2276static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2277{
2278 if (cmd) {
2279 printf("%s ", cmd);
2280 } else {
2281 printf("%s ", ct->name);
2282 if (ct->altname) {
2283 printf("(or %s) ", ct->altname);
2284 }
2285 }
2286
2287 if (ct->args) {
2288 printf("%s ", ct->args);
2289 }
2290 printf("-- %s\n", ct->oneline);
2291}
2292
2293static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2294{
2295 help_oneline(cmd, ct);
2296 if (ct->help) {
2297 ct->help();
2298 }
2299}
2300
2301static void help_all(void)
2302{
2303 const cmdinfo_t *ct;
2304
2305 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2306 help_oneline(ct->name, ct);
2307 }
2308 printf("\nUse 'help commandname' for extended help.\n");
2309}
2310
b32d7a39 2311static int help_f(BlockBackend *blk, int argc, char **argv)
f18a834a
KW
2312{
2313 const cmdinfo_t *ct;
2314
2315 if (argc == 1) {
2316 help_all();
b32d7a39 2317 return 0;
f18a834a
KW
2318 }
2319
2320 ct = find_command(argv[1]);
2321 if (ct == NULL) {
2322 printf("command %s not found\n", argv[1]);
b32d7a39 2323 return -EINVAL;
f18a834a
KW
2324 }
2325
2326 help_onecmd(argv[1], ct);
b32d7a39 2327 return 0;
f18a834a
KW
2328}
2329
2330static const cmdinfo_t help_cmd = {
2331 .name = "help",
2332 .altname = "?",
2333 .cfunc = help_f,
2334 .argmin = 0,
2335 .argmax = 1,
2336 .flags = CMD_FLAG_GLOBAL,
2337 .args = "[command]",
2338 .oneline = "help for one or all commands",
2339};
2340
b32d7a39 2341int qemuio_command(BlockBackend *blk, const char *cmd)
dd583296 2342{
15afd94a 2343 AioContext *ctx;
dd583296
KW
2344 char *input;
2345 const cmdinfo_t *ct;
2346 char **v;
2347 int c;
b32d7a39 2348 int ret = 0;
dd583296
KW
2349
2350 input = g_strdup(cmd);
2351 v = breakline(input, &c);
2352 if (c) {
2353 ct = find_command(v[0]);
2354 if (ct) {
15afd94a
PB
2355 ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
2356 aio_context_acquire(ctx);
b32d7a39 2357 ret = command(blk, ct, c, v);
15afd94a 2358 aio_context_release(ctx);
dd583296
KW
2359 } else {
2360 fprintf(stderr, "command \"%s\" not found\n", v[0]);
b32d7a39 2361 ret = -EINVAL;
dd583296
KW
2362 }
2363 }
2364 g_free(input);
2365 g_free(v);
b32d7a39
HR
2366
2367 return ret;
dd583296
KW
2368}
2369
797ac58c
KW
2370static void __attribute((constructor)) init_qemuio_commands(void)
2371{
2372 /* initialize commands */
c2cdf5c5
KW
2373 qemuio_add_command(&help_cmd);
2374 qemuio_add_command(&read_cmd);
2375 qemuio_add_command(&readv_cmd);
2376 qemuio_add_command(&write_cmd);
2377 qemuio_add_command(&writev_cmd);
c2cdf5c5
KW
2378 qemuio_add_command(&aio_read_cmd);
2379 qemuio_add_command(&aio_write_cmd);
2380 qemuio_add_command(&aio_flush_cmd);
2381 qemuio_add_command(&flush_cmd);
2382 qemuio_add_command(&truncate_cmd);
2383 qemuio_add_command(&length_cmd);
2384 qemuio_add_command(&info_cmd);
2385 qemuio_add_command(&discard_cmd);
2386 qemuio_add_command(&alloc_cmd);
2387 qemuio_add_command(&map_cmd);
5bbd2e59 2388 qemuio_add_command(&reopen_cmd);
c2cdf5c5 2389 qemuio_add_command(&break_cmd);
4cc70e93 2390 qemuio_add_command(&remove_break_cmd);
c2cdf5c5
KW
2391 qemuio_add_command(&resume_cmd);
2392 qemuio_add_command(&wait_break_cmd);
2393 qemuio_add_command(&abort_cmd);
cd33d02a 2394 qemuio_add_command(&sleep_cmd);
0e82dc7b 2395 qemuio_add_command(&sigraise_cmd);
797ac58c 2396}