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