Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-migration-20210726a...
[qemu/armbru.git] / qemu-io-cmds.c
blob46593d632d8f8a79640d1fd4b3a2148d5e56fa1e
1 /*
2 * Command line utility to exercise the QEMU I/O path.
4 * Copyright (C) 2009-2016 Red Hat, Inc.
5 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
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 */
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"
25 #define CMD_NOFILE_OK 0x01
27 bool qemuio_misalign;
29 static cmdinfo_t *cmdtab;
30 static int ncmds;
32 static int compare_cmdname(const void *a, const void *b)
34 return strcmp(((const cmdinfo_t *)a)->name,
35 ((const cmdinfo_t *)b)->name);
38 void qemuio_add_command(const cmdinfo_t *ci)
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.
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);
52 void qemuio_command_usage(const cmdinfo_t *ci)
54 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
57 static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
59 if (ct->flags & CMD_FLAG_GLOBAL) {
60 return 1;
62 if (!(ct->flags & CMD_NOFILE_OK) && !blk) {
63 fprintf(stderr, "no file open, try 'help open'\n");
64 return 0;
66 return 1;
69 static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
70 char **argv)
72 char *cmd = argv[0];
74 if (!init_check_command(blk, ct)) {
75 return -EINVAL;
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);
92 return -EINVAL;
96 * Request additional permissions if necessary for this command. The caller
97 * is responsible for restoring the original permissions afterwards if this
98 * is what it wants.
100 * Coverity thinks that blk may be NULL in the following if condition. It's
101 * not so: in init_check_command() we fail if blk is NULL for command with
102 * both CMD_FLAG_GLOBAL and CMD_NOFILE_OK flags unset. And in
103 * qemuio_add_command() we assert that command with non-zero .perm field
104 * doesn't set this flags. So, the following assertion is to silence
105 * Coverity:
107 assert(blk || !ct->perm);
108 if (ct->perm && blk_is_available(blk)) {
109 uint64_t orig_perm, orig_shared_perm;
110 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
112 if (ct->perm & ~orig_perm) {
113 uint64_t new_perm;
114 Error *local_err = NULL;
115 int ret;
117 new_perm = orig_perm | ct->perm;
119 ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
120 if (ret < 0) {
121 error_report_err(local_err);
122 return ret;
127 qemu_reset_optind();
128 return ct->cfunc(blk, argc, argv);
131 static const cmdinfo_t *find_command(const char *cmd)
133 cmdinfo_t *ct;
135 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
136 if (strcmp(ct->name, cmd) == 0 ||
137 (ct->altname && strcmp(ct->altname, cmd) == 0))
139 return (const cmdinfo_t *)ct;
142 return NULL;
145 /* Invoke fn() for commands with a matching prefix */
146 void qemuio_complete_command(const char *input,
147 void (*fn)(const char *cmd, void *opaque),
148 void *opaque)
150 cmdinfo_t *ct;
151 size_t input_len = strlen(input);
153 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
154 if (strncmp(input, ct->name, input_len) == 0) {
155 fn(ct->name, opaque);
160 static char **breakline(char *input, int *count)
162 int c = 0;
163 char *p;
164 char **rval = g_new0(char *, 1);
166 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
167 if (!*p) {
168 continue;
170 c++;
171 rval = g_renew(char *, rval, (c + 1));
172 rval[c - 1] = p;
173 rval[c] = NULL;
175 *count = c;
176 return rval;
179 static int64_t cvtnum(const char *s)
181 int err;
182 uint64_t value;
184 err = qemu_strtosz(s, NULL, &value);
185 if (err < 0) {
186 return err;
188 if (value > INT64_MAX) {
189 return -ERANGE;
191 return value;
194 static void print_cvtnum_err(int64_t rc, const char *arg)
196 switch (rc) {
197 case -EINVAL:
198 printf("Parsing error: non-numeric argument,"
199 " or extraneous/unrecognized suffix -- %s\n", arg);
200 break;
201 case -ERANGE:
202 printf("Parsing error: argument too large -- %s\n", arg);
203 break;
204 default:
205 printf("Parsing error: %s\n", arg);
209 #define EXABYTES(x) ((long long)(x) << 60)
210 #define PETABYTES(x) ((long long)(x) << 50)
211 #define TERABYTES(x) ((long long)(x) << 40)
212 #define GIGABYTES(x) ((long long)(x) << 30)
213 #define MEGABYTES(x) ((long long)(x) << 20)
214 #define KILOBYTES(x) ((long long)(x) << 10)
216 #define TO_EXABYTES(x) ((x) / EXABYTES(1))
217 #define TO_PETABYTES(x) ((x) / PETABYTES(1))
218 #define TO_TERABYTES(x) ((x) / TERABYTES(1))
219 #define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
220 #define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
221 #define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
223 static void cvtstr(double value, char *str, size_t size)
225 char *trim;
226 const char *suffix;
228 if (value >= EXABYTES(1)) {
229 suffix = " EiB";
230 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
231 } else if (value >= PETABYTES(1)) {
232 suffix = " PiB";
233 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
234 } else if (value >= TERABYTES(1)) {
235 suffix = " TiB";
236 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
237 } else if (value >= GIGABYTES(1)) {
238 suffix = " GiB";
239 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
240 } else if (value >= MEGABYTES(1)) {
241 suffix = " MiB";
242 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
243 } else if (value >= KILOBYTES(1)) {
244 suffix = " KiB";
245 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
246 } else {
247 suffix = " bytes";
248 snprintf(str, size - 6, "%f", value);
251 trim = strstr(str, ".000");
252 if (trim) {
253 strcpy(trim, suffix);
254 } else {
255 strcat(str, suffix);
261 static struct timespec tsub(struct timespec t1, struct timespec t2)
263 t1.tv_nsec -= t2.tv_nsec;
264 if (t1.tv_nsec < 0) {
265 t1.tv_nsec += NANOSECONDS_PER_SECOND;
266 t1.tv_sec--;
268 t1.tv_sec -= t2.tv_sec;
269 return t1;
272 static double tdiv(double value, struct timespec tv)
274 double seconds = tv.tv_sec + (tv.tv_nsec / 1e9);
275 return value / seconds;
278 #define HOURS(sec) ((sec) / (60 * 60))
279 #define MINUTES(sec) (((sec) % (60 * 60)) / 60)
280 #define SECONDS(sec) ((sec) % 60)
282 enum {
283 DEFAULT_TIME = 0x0,
284 TERSE_FIXED_TIME = 0x1,
285 VERBOSE_FIXED_TIME = 0x2,
288 static void timestr(struct timespec *tv, char *ts, size_t size, int format)
290 double frac_sec = tv->tv_nsec / 1e9;
292 if (format & TERSE_FIXED_TIME) {
293 if (!HOURS(tv->tv_sec)) {
294 snprintf(ts, size, "%u:%05.2f",
295 (unsigned int) MINUTES(tv->tv_sec),
296 SECONDS(tv->tv_sec) + frac_sec);
297 return;
299 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
302 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
303 snprintf(ts, size, "%u:%02u:%05.2f",
304 (unsigned int) HOURS(tv->tv_sec),
305 (unsigned int) MINUTES(tv->tv_sec),
306 SECONDS(tv->tv_sec) + frac_sec);
307 } else {
308 snprintf(ts, size, "%05.2f sec", frac_sec);
313 * Parse the pattern argument to various sub-commands.
315 * Because the pattern is used as an argument to memset it must evaluate
316 * to an unsigned integer that fits into a single byte.
318 static int parse_pattern(const char *arg)
320 char *endptr = NULL;
321 long pattern;
323 pattern = strtol(arg, &endptr, 0);
324 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
325 printf("%s is not a valid pattern byte\n", arg);
326 return -1;
329 return pattern;
333 * Memory allocation helpers.
335 * Make sure memory is aligned by default, or purposefully misaligned if
336 * that is specified on the command line.
339 #define MISALIGN_OFFSET 16
340 static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern)
342 void *buf;
344 if (qemuio_misalign) {
345 len += MISALIGN_OFFSET;
347 buf = blk_blockalign(blk, len);
348 memset(buf, pattern, len);
349 if (qemuio_misalign) {
350 buf += MISALIGN_OFFSET;
352 return buf;
355 static void qemu_io_free(void *p)
357 if (qemuio_misalign) {
358 p -= MISALIGN_OFFSET;
360 qemu_vfree(p);
364 * qemu_io_alloc_from_file()
366 * Allocates the buffer and populates it with the content of the given file
367 * up to @len bytes. If the file length is less than @len, then the buffer
368 * is populated with the file content cyclically.
370 * @blk - the block backend where the buffer content is going to be written to
371 * @len - the buffer length
372 * @file_name - the file to read the content from
374 * Returns: the buffer pointer on success
375 * NULL on error
377 static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
378 const char *file_name)
380 char *buf, *buf_origin;
381 FILE *f = fopen(file_name, "r");
382 int pattern_len;
384 if (!f) {
385 perror(file_name);
386 return NULL;
389 if (qemuio_misalign) {
390 len += MISALIGN_OFFSET;
393 buf_origin = buf = blk_blockalign(blk, len);
395 if (qemuio_misalign) {
396 buf_origin += MISALIGN_OFFSET;
397 buf += MISALIGN_OFFSET;
398 len -= MISALIGN_OFFSET;
401 pattern_len = fread(buf_origin, 1, len, f);
403 if (ferror(f)) {
404 perror(file_name);
405 goto error;
408 if (pattern_len == 0) {
409 fprintf(stderr, "%s: file is empty\n", file_name);
410 goto error;
413 fclose(f);
414 f = NULL;
416 if (len > pattern_len) {
417 len -= pattern_len;
418 buf += pattern_len;
420 while (len > 0) {
421 size_t len_to_copy = MIN(pattern_len, len);
423 memcpy(buf, buf_origin, len_to_copy);
425 len -= len_to_copy;
426 buf += len_to_copy;
430 return buf_origin;
432 error:
433 qemu_io_free(buf_origin);
434 if (f) {
435 fclose(f);
437 return NULL;
440 static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
442 uint64_t i;
443 int j;
444 const uint8_t *p;
446 for (i = 0, p = buffer; i < len; i += 16) {
447 const uint8_t *s = p;
449 printf("%08" PRIx64 ": ", offset + i);
450 for (j = 0; j < 16 && i + j < len; j++, p++) {
451 printf("%02x ", *p);
453 printf(" ");
454 for (j = 0; j < 16 && i + j < len; j++, s++) {
455 if (isalnum(*s)) {
456 printf("%c", *s);
457 } else {
458 printf(".");
461 printf("\n");
465 static void print_report(const char *op, struct timespec *t, int64_t offset,
466 int64_t count, int64_t total, int cnt, bool Cflag)
468 char s1[64], s2[64], ts[64];
470 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
471 if (!Cflag) {
472 cvtstr((double)total, s1, sizeof(s1));
473 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
474 printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n",
475 op, total, count, offset);
476 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
477 s1, cnt, ts, s2, tdiv((double)cnt, *t));
478 } else {/* bytes,ops,time,bytes/sec,ops/sec */
479 printf("%"PRId64",%d,%s,%.3f,%.3f\n",
480 total, cnt, ts,
481 tdiv((double)total, *t),
482 tdiv((double)cnt, *t));
487 * Parse multiple length statements for vectored I/O, and construct an I/O
488 * vector matching it.
490 static void *
491 create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
492 int pattern)
494 size_t *sizes = g_new0(size_t, nr_iov);
495 size_t count = 0;
496 void *buf = NULL;
497 void *p;
498 int i;
500 for (i = 0; i < nr_iov; i++) {
501 char *arg = argv[i];
502 int64_t len;
504 len = cvtnum(arg);
505 if (len < 0) {
506 print_cvtnum_err(len, arg);
507 goto fail;
510 if (len > BDRV_REQUEST_MAX_BYTES) {
511 printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg,
512 (uint64_t)BDRV_REQUEST_MAX_BYTES);
513 goto fail;
516 if (count > BDRV_REQUEST_MAX_BYTES - len) {
517 printf("The total number of bytes exceed the maximum size %" PRIu64
518 "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES);
519 goto fail;
522 sizes[i] = len;
523 count += len;
526 qemu_iovec_init(qiov, nr_iov);
528 buf = p = qemu_io_alloc(blk, count, pattern);
530 for (i = 0; i < nr_iov; i++) {
531 qemu_iovec_add(qiov, p, sizes[i]);
532 p += sizes[i];
535 fail:
536 g_free(sizes);
537 return buf;
540 static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
541 int64_t bytes, int64_t *total)
543 if (bytes > INT_MAX) {
544 return -ERANGE;
547 *total = blk_pread(blk, offset, (uint8_t *)buf, bytes);
548 if (*total < 0) {
549 return *total;
551 return 1;
554 static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
555 int64_t bytes, int flags, int64_t *total)
557 if (bytes > INT_MAX) {
558 return -ERANGE;
561 *total = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
562 if (*total < 0) {
563 return *total;
565 return 1;
568 typedef struct {
569 BlockBackend *blk;
570 int64_t offset;
571 int64_t bytes;
572 int64_t *total;
573 int flags;
574 int ret;
575 bool done;
576 } CoWriteZeroes;
578 static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
580 CoWriteZeroes *data = opaque;
582 data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
583 data->flags);
584 data->done = true;
585 if (data->ret < 0) {
586 *data->total = data->ret;
587 return;
590 *data->total = data->bytes;
593 static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
594 int64_t bytes, int flags, int64_t *total)
596 Coroutine *co;
597 CoWriteZeroes data = {
598 .blk = blk,
599 .offset = offset,
600 .bytes = bytes,
601 .total = total,
602 .flags = flags,
603 .done = false,
606 if (bytes > INT_MAX) {
607 return -ERANGE;
610 co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
611 bdrv_coroutine_enter(blk_bs(blk), co);
612 while (!data.done) {
613 aio_poll(blk_get_aio_context(blk), true);
615 if (data.ret < 0) {
616 return data.ret;
617 } else {
618 return 1;
622 static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
623 int64_t bytes, int64_t *total)
625 int ret;
627 if (bytes > BDRV_REQUEST_MAX_BYTES) {
628 return -ERANGE;
631 ret = blk_pwrite_compressed(blk, offset, buf, bytes);
632 if (ret < 0) {
633 return ret;
635 *total = bytes;
636 return 1;
639 static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset,
640 int64_t count, int64_t *total)
642 if (count > INT_MAX) {
643 return -ERANGE;
646 *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count);
647 if (*total < 0) {
648 return *total;
650 return 1;
653 static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset,
654 int64_t count, int64_t *total)
656 if (count > INT_MAX) {
657 return -ERANGE;
660 *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count);
661 if (*total < 0) {
662 return *total;
664 return 1;
667 #define NOT_DONE 0x7fffffff
668 static void aio_rw_done(void *opaque, int ret)
670 *(int *)opaque = ret;
673 static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
674 int64_t offset, int *total)
676 int async_ret = NOT_DONE;
678 blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret);
679 while (async_ret == NOT_DONE) {
680 main_loop_wait(false);
683 *total = qiov->size;
684 return async_ret < 0 ? async_ret : 1;
687 static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
688 int64_t offset, int flags, int *total)
690 int async_ret = NOT_DONE;
692 blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret);
693 while (async_ret == NOT_DONE) {
694 main_loop_wait(false);
697 *total = qiov->size;
698 return async_ret < 0 ? async_ret : 1;
701 static void read_help(void)
703 printf(
704 "\n"
705 " reads a range of bytes from the given offset\n"
706 "\n"
707 " Example:\n"
708 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
709 "\n"
710 " Reads a segment of the currently open file, optionally dumping it to the\n"
711 " standard output stream (with -v option) for subsequent inspection.\n"
712 " -b, -- read from the VM state rather than the virtual disk\n"
713 " -C, -- report statistics in a machine parsable format\n"
714 " -l, -- length for pattern verification (only with -P)\n"
715 " -p, -- ignored for backwards compatibility\n"
716 " -P, -- use a pattern to verify read data\n"
717 " -q, -- quiet mode, do not show I/O statistics\n"
718 " -s, -- start offset for pattern verification (only with -P)\n"
719 " -v, -- dump buffer to standard output\n"
720 "\n");
723 static int read_f(BlockBackend *blk, int argc, char **argv);
725 static const cmdinfo_t read_cmd = {
726 .name = "read",
727 .altname = "r",
728 .cfunc = read_f,
729 .argmin = 2,
730 .argmax = -1,
731 .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len",
732 .oneline = "reads a number of bytes at a specified offset",
733 .help = read_help,
736 static int read_f(BlockBackend *blk, int argc, char **argv)
738 struct timespec t1, t2;
739 bool Cflag = false, qflag = false, vflag = false;
740 bool Pflag = false, sflag = false, lflag = false, bflag = false;
741 int c, cnt, ret;
742 char *buf;
743 int64_t offset;
744 int64_t count;
745 /* Some compilers get confused and warn if this is not initialized. */
746 int64_t total = 0;
747 int pattern = 0;
748 int64_t pattern_offset = 0, pattern_count = 0;
750 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
751 switch (c) {
752 case 'b':
753 bflag = true;
754 break;
755 case 'C':
756 Cflag = true;
757 break;
758 case 'l':
759 lflag = true;
760 pattern_count = cvtnum(optarg);
761 if (pattern_count < 0) {
762 print_cvtnum_err(pattern_count, optarg);
763 return pattern_count;
765 break;
766 case 'p':
767 /* Ignored for backwards compatibility */
768 break;
769 case 'P':
770 Pflag = true;
771 pattern = parse_pattern(optarg);
772 if (pattern < 0) {
773 return -EINVAL;
775 break;
776 case 'q':
777 qflag = true;
778 break;
779 case 's':
780 sflag = true;
781 pattern_offset = cvtnum(optarg);
782 if (pattern_offset < 0) {
783 print_cvtnum_err(pattern_offset, optarg);
784 return pattern_offset;
786 break;
787 case 'v':
788 vflag = true;
789 break;
790 default:
791 qemuio_command_usage(&read_cmd);
792 return -EINVAL;
796 if (optind != argc - 2) {
797 qemuio_command_usage(&read_cmd);
798 return -EINVAL;
801 offset = cvtnum(argv[optind]);
802 if (offset < 0) {
803 print_cvtnum_err(offset, argv[optind]);
804 return offset;
807 optind++;
808 count = cvtnum(argv[optind]);
809 if (count < 0) {
810 print_cvtnum_err(count, argv[optind]);
811 return count;
812 } else if (count > BDRV_REQUEST_MAX_BYTES) {
813 printf("length cannot exceed %" PRIu64 ", given %s\n",
814 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
815 return -EINVAL;
818 if (!Pflag && (lflag || sflag)) {
819 qemuio_command_usage(&read_cmd);
820 return -EINVAL;
823 if (!lflag) {
824 pattern_count = count - pattern_offset;
827 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
828 printf("pattern verification range exceeds end of read data\n");
829 return -EINVAL;
832 if (bflag) {
833 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
834 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
835 offset);
836 return -EINVAL;
838 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
839 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
840 count);
841 return -EINVAL;
845 buf = qemu_io_alloc(blk, count, 0xab);
847 clock_gettime(CLOCK_MONOTONIC, &t1);
848 if (bflag) {
849 ret = do_load_vmstate(blk, buf, offset, count, &total);
850 } else {
851 ret = do_pread(blk, buf, offset, count, &total);
853 clock_gettime(CLOCK_MONOTONIC, &t2);
855 if (ret < 0) {
856 printf("read failed: %s\n", strerror(-ret));
857 goto out;
859 cnt = ret;
861 ret = 0;
863 if (Pflag) {
864 void *cmp_buf = g_malloc(pattern_count);
865 memset(cmp_buf, pattern, pattern_count);
866 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
867 printf("Pattern verification failed at offset %"
868 PRId64 ", %"PRId64" bytes\n",
869 offset + pattern_offset, pattern_count);
870 ret = -EINVAL;
872 g_free(cmp_buf);
875 if (qflag) {
876 goto out;
879 if (vflag) {
880 dump_buffer(buf, offset, count);
883 /* Finally, report back -- -C gives a parsable format */
884 t2 = tsub(t2, t1);
885 print_report("read", &t2, offset, count, total, cnt, Cflag);
887 out:
888 qemu_io_free(buf);
889 return ret;
892 static void readv_help(void)
894 printf(
895 "\n"
896 " reads a range of bytes from the given offset into multiple buffers\n"
897 "\n"
898 " Example:\n"
899 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
900 "\n"
901 " Reads a segment of the currently open file, optionally dumping it to the\n"
902 " standard output stream (with -v option) for subsequent inspection.\n"
903 " Uses multiple iovec buffers if more than one byte range is specified.\n"
904 " -C, -- report statistics in a machine parsable format\n"
905 " -P, -- use a pattern to verify read data\n"
906 " -v, -- dump buffer to standard output\n"
907 " -q, -- quiet mode, do not show I/O statistics\n"
908 "\n");
911 static int readv_f(BlockBackend *blk, int argc, char **argv);
913 static const cmdinfo_t readv_cmd = {
914 .name = "readv",
915 .cfunc = readv_f,
916 .argmin = 2,
917 .argmax = -1,
918 .args = "[-Cqv] [-P pattern] off len [len..]",
919 .oneline = "reads a number of bytes at a specified offset",
920 .help = readv_help,
923 static int readv_f(BlockBackend *blk, int argc, char **argv)
925 struct timespec t1, t2;
926 bool Cflag = false, qflag = false, vflag = false;
927 int c, cnt, ret;
928 char *buf;
929 int64_t offset;
930 /* Some compilers get confused and warn if this is not initialized. */
931 int total = 0;
932 int nr_iov;
933 QEMUIOVector qiov;
934 int pattern = 0;
935 bool Pflag = false;
937 while ((c = getopt(argc, argv, "CP:qv")) != -1) {
938 switch (c) {
939 case 'C':
940 Cflag = true;
941 break;
942 case 'P':
943 Pflag = true;
944 pattern = parse_pattern(optarg);
945 if (pattern < 0) {
946 return -EINVAL;
948 break;
949 case 'q':
950 qflag = true;
951 break;
952 case 'v':
953 vflag = true;
954 break;
955 default:
956 qemuio_command_usage(&readv_cmd);
957 return -EINVAL;
961 if (optind > argc - 2) {
962 qemuio_command_usage(&readv_cmd);
963 return -EINVAL;
967 offset = cvtnum(argv[optind]);
968 if (offset < 0) {
969 print_cvtnum_err(offset, argv[optind]);
970 return offset;
972 optind++;
974 nr_iov = argc - optind;
975 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
976 if (buf == NULL) {
977 return -EINVAL;
980 clock_gettime(CLOCK_MONOTONIC, &t1);
981 ret = do_aio_readv(blk, &qiov, offset, &total);
982 clock_gettime(CLOCK_MONOTONIC, &t2);
984 if (ret < 0) {
985 printf("readv failed: %s\n", strerror(-ret));
986 goto out;
988 cnt = ret;
990 ret = 0;
992 if (Pflag) {
993 void *cmp_buf = g_malloc(qiov.size);
994 memset(cmp_buf, pattern, qiov.size);
995 if (memcmp(buf, cmp_buf, qiov.size)) {
996 printf("Pattern verification failed at offset %"
997 PRId64 ", %zu bytes\n", offset, qiov.size);
998 ret = -EINVAL;
1000 g_free(cmp_buf);
1003 if (qflag) {
1004 goto out;
1007 if (vflag) {
1008 dump_buffer(buf, offset, qiov.size);
1011 /* Finally, report back -- -C gives a parsable format */
1012 t2 = tsub(t2, t1);
1013 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
1015 out:
1016 qemu_iovec_destroy(&qiov);
1017 qemu_io_free(buf);
1018 return ret;
1021 static void write_help(void)
1023 printf(
1024 "\n"
1025 " writes a range of bytes from the given offset\n"
1026 "\n"
1027 " Example:\n"
1028 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
1029 "\n"
1030 " Writes into a segment of the currently open file, using a buffer\n"
1031 " filled with a set pattern (0xcdcdcdcd).\n"
1032 " -b, -- write to the VM state rather than the virtual disk\n"
1033 " -c, -- write compressed data with blk_write_compressed\n"
1034 " -f, -- use Force Unit Access semantics\n"
1035 " -n, -- with -z, don't allow slow fallback\n"
1036 " -p, -- ignored for backwards compatibility\n"
1037 " -P, -- use different pattern to fill file\n"
1038 " -s, -- use a pattern file to fill the write buffer\n"
1039 " -C, -- report statistics in a machine parsable format\n"
1040 " -q, -- quiet mode, do not show I/O statistics\n"
1041 " -u, -- with -z, allow unmapping\n"
1042 " -z, -- write zeroes using blk_co_pwrite_zeroes\n"
1043 "\n");
1046 static int write_f(BlockBackend *blk, int argc, char **argv);
1048 static const cmdinfo_t write_cmd = {
1049 .name = "write",
1050 .altname = "w",
1051 .cfunc = write_f,
1052 .perm = BLK_PERM_WRITE,
1053 .argmin = 2,
1054 .argmax = -1,
1055 .args = "[-bcCfnquz] [-P pattern | -s source_file] off len",
1056 .oneline = "writes a number of bytes at a specified offset",
1057 .help = write_help,
1060 static int write_f(BlockBackend *blk, int argc, char **argv)
1062 struct timespec t1, t2;
1063 bool Cflag = false, qflag = false, bflag = false;
1064 bool Pflag = false, zflag = false, cflag = false, sflag = false;
1065 int flags = 0;
1066 int c, cnt, ret;
1067 char *buf = NULL;
1068 int64_t offset;
1069 int64_t count;
1070 /* Some compilers get confused and warn if this is not initialized. */
1071 int64_t total = 0;
1072 int pattern = 0xcd;
1073 const char *file_name = NULL;
1075 while ((c = getopt(argc, argv, "bcCfnpP:qs:uz")) != -1) {
1076 switch (c) {
1077 case 'b':
1078 bflag = true;
1079 break;
1080 case 'c':
1081 cflag = true;
1082 break;
1083 case 'C':
1084 Cflag = true;
1085 break;
1086 case 'f':
1087 flags |= BDRV_REQ_FUA;
1088 break;
1089 case 'n':
1090 flags |= BDRV_REQ_NO_FALLBACK;
1091 break;
1092 case 'p':
1093 /* Ignored for backwards compatibility */
1094 break;
1095 case 'P':
1096 Pflag = true;
1097 pattern = parse_pattern(optarg);
1098 if (pattern < 0) {
1099 return -EINVAL;
1101 break;
1102 case 'q':
1103 qflag = true;
1104 break;
1105 case 's':
1106 sflag = true;
1107 file_name = optarg;
1108 break;
1109 case 'u':
1110 flags |= BDRV_REQ_MAY_UNMAP;
1111 break;
1112 case 'z':
1113 zflag = true;
1114 break;
1115 default:
1116 qemuio_command_usage(&write_cmd);
1117 return -EINVAL;
1121 if (optind != argc - 2) {
1122 qemuio_command_usage(&write_cmd);
1123 return -EINVAL;
1126 if (bflag && zflag) {
1127 printf("-b and -z cannot be specified at the same time\n");
1128 return -EINVAL;
1131 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
1132 printf("-f and -b or -c cannot be specified at the same time\n");
1133 return -EINVAL;
1136 if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
1137 printf("-n requires -z to be specified\n");
1138 return -EINVAL;
1141 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
1142 printf("-u requires -z to be specified\n");
1143 return -EINVAL;
1146 if (zflag + Pflag + sflag > 1) {
1147 printf("Only one of -z, -P, and -s "
1148 "can be specified at the same time\n");
1149 return -EINVAL;
1152 offset = cvtnum(argv[optind]);
1153 if (offset < 0) {
1154 print_cvtnum_err(offset, argv[optind]);
1155 return offset;
1158 optind++;
1159 count = cvtnum(argv[optind]);
1160 if (count < 0) {
1161 print_cvtnum_err(count, argv[optind]);
1162 return count;
1163 } else if (count > BDRV_REQUEST_MAX_BYTES) {
1164 printf("length cannot exceed %" PRIu64 ", given %s\n",
1165 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
1166 return -EINVAL;
1169 if (bflag || cflag) {
1170 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
1171 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
1172 offset);
1173 return -EINVAL;
1176 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
1177 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
1178 count);
1179 return -EINVAL;
1183 if (!zflag) {
1184 if (sflag) {
1185 buf = qemu_io_alloc_from_file(blk, count, file_name);
1186 if (!buf) {
1187 return -EINVAL;
1189 } else {
1190 buf = qemu_io_alloc(blk, count, pattern);
1194 clock_gettime(CLOCK_MONOTONIC, &t1);
1195 if (bflag) {
1196 ret = do_save_vmstate(blk, buf, offset, count, &total);
1197 } else if (zflag) {
1198 ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
1199 } else if (cflag) {
1200 ret = do_write_compressed(blk, buf, offset, count, &total);
1201 } else {
1202 ret = do_pwrite(blk, buf, offset, count, flags, &total);
1204 clock_gettime(CLOCK_MONOTONIC, &t2);
1206 if (ret < 0) {
1207 printf("write failed: %s\n", strerror(-ret));
1208 goto out;
1210 cnt = ret;
1212 ret = 0;
1214 if (qflag) {
1215 goto out;
1218 /* Finally, report back -- -C gives a parsable format */
1219 t2 = tsub(t2, t1);
1220 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1222 out:
1223 if (!zflag) {
1224 qemu_io_free(buf);
1226 return ret;
1229 static void
1230 writev_help(void)
1232 printf(
1233 "\n"
1234 " writes a range of bytes from the given offset source from multiple buffers\n"
1235 "\n"
1236 " Example:\n"
1237 " 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1238 "\n"
1239 " Writes into a segment of the currently open file, using a buffer\n"
1240 " filled with a set pattern (0xcdcdcdcd).\n"
1241 " -P, -- use different pattern to fill file\n"
1242 " -C, -- report statistics in a machine parsable format\n"
1243 " -f, -- use Force Unit Access semantics\n"
1244 " -q, -- quiet mode, do not show I/O statistics\n"
1245 "\n");
1248 static int writev_f(BlockBackend *blk, int argc, char **argv);
1250 static const cmdinfo_t writev_cmd = {
1251 .name = "writev",
1252 .cfunc = writev_f,
1253 .perm = BLK_PERM_WRITE,
1254 .argmin = 2,
1255 .argmax = -1,
1256 .args = "[-Cfq] [-P pattern] off len [len..]",
1257 .oneline = "writes a number of bytes at a specified offset",
1258 .help = writev_help,
1261 static int writev_f(BlockBackend *blk, int argc, char **argv)
1263 struct timespec t1, t2;
1264 bool Cflag = false, qflag = false;
1265 int flags = 0;
1266 int c, cnt, ret;
1267 char *buf;
1268 int64_t offset;
1269 /* Some compilers get confused and warn if this is not initialized. */
1270 int total = 0;
1271 int nr_iov;
1272 int pattern = 0xcd;
1273 QEMUIOVector qiov;
1275 while ((c = getopt(argc, argv, "CfqP:")) != -1) {
1276 switch (c) {
1277 case 'C':
1278 Cflag = true;
1279 break;
1280 case 'f':
1281 flags |= BDRV_REQ_FUA;
1282 break;
1283 case 'q':
1284 qflag = true;
1285 break;
1286 case 'P':
1287 pattern = parse_pattern(optarg);
1288 if (pattern < 0) {
1289 return -EINVAL;
1291 break;
1292 default:
1293 qemuio_command_usage(&writev_cmd);
1294 return -EINVAL;
1298 if (optind > argc - 2) {
1299 qemuio_command_usage(&writev_cmd);
1300 return -EINVAL;
1303 offset = cvtnum(argv[optind]);
1304 if (offset < 0) {
1305 print_cvtnum_err(offset, argv[optind]);
1306 return offset;
1308 optind++;
1310 nr_iov = argc - optind;
1311 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
1312 if (buf == NULL) {
1313 return -EINVAL;
1316 clock_gettime(CLOCK_MONOTONIC, &t1);
1317 ret = do_aio_writev(blk, &qiov, offset, flags, &total);
1318 clock_gettime(CLOCK_MONOTONIC, &t2);
1320 if (ret < 0) {
1321 printf("writev failed: %s\n", strerror(-ret));
1322 goto out;
1324 cnt = ret;
1326 ret = 0;
1328 if (qflag) {
1329 goto out;
1332 /* Finally, report back -- -C gives a parsable format */
1333 t2 = tsub(t2, t1);
1334 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1335 out:
1336 qemu_iovec_destroy(&qiov);
1337 qemu_io_free(buf);
1338 return ret;
1341 struct aio_ctx {
1342 BlockBackend *blk;
1343 QEMUIOVector qiov;
1344 int64_t offset;
1345 char *buf;
1346 bool qflag;
1347 bool vflag;
1348 bool Cflag;
1349 bool Pflag;
1350 bool zflag;
1351 BlockAcctCookie acct;
1352 int pattern;
1353 struct timespec t1;
1356 static void aio_write_done(void *opaque, int ret)
1358 struct aio_ctx *ctx = opaque;
1359 struct timespec t2;
1361 clock_gettime(CLOCK_MONOTONIC, &t2);
1364 if (ret < 0) {
1365 printf("aio_write failed: %s\n", strerror(-ret));
1366 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
1367 goto out;
1370 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
1372 if (ctx->qflag) {
1373 goto out;
1376 /* Finally, report back -- -C gives a parsable format */
1377 t2 = tsub(t2, ctx->t1);
1378 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1379 ctx->qiov.size, 1, ctx->Cflag);
1380 out:
1381 if (!ctx->zflag) {
1382 qemu_io_free(ctx->buf);
1383 qemu_iovec_destroy(&ctx->qiov);
1385 g_free(ctx);
1388 static void aio_read_done(void *opaque, int ret)
1390 struct aio_ctx *ctx = opaque;
1391 struct timespec t2;
1393 clock_gettime(CLOCK_MONOTONIC, &t2);
1395 if (ret < 0) {
1396 printf("readv failed: %s\n", strerror(-ret));
1397 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
1398 goto out;
1401 if (ctx->Pflag) {
1402 void *cmp_buf = g_malloc(ctx->qiov.size);
1404 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1405 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1406 printf("Pattern verification failed at offset %"
1407 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
1409 g_free(cmp_buf);
1412 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
1414 if (ctx->qflag) {
1415 goto out;
1418 if (ctx->vflag) {
1419 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1422 /* Finally, report back -- -C gives a parsable format */
1423 t2 = tsub(t2, ctx->t1);
1424 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1425 ctx->qiov.size, 1, ctx->Cflag);
1426 out:
1427 qemu_io_free(ctx->buf);
1428 qemu_iovec_destroy(&ctx->qiov);
1429 g_free(ctx);
1432 static void aio_read_help(void)
1434 printf(
1435 "\n"
1436 " asynchronously reads a range of bytes from the given offset\n"
1437 "\n"
1438 " Example:\n"
1439 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1440 "\n"
1441 " Reads a segment of the currently open file, optionally dumping it to the\n"
1442 " standard output stream (with -v option) for subsequent inspection.\n"
1443 " The read is performed asynchronously and the aio_flush command must be\n"
1444 " used to ensure all outstanding aio requests have been completed.\n"
1445 " Note that due to its asynchronous nature, this command will be\n"
1446 " considered successful once the request is submitted, independently\n"
1447 " of potential I/O errors or pattern mismatches.\n"
1448 " -C, -- report statistics in a machine parsable format\n"
1449 " -P, -- use a pattern to verify read data\n"
1450 " -i, -- treat request as invalid, for exercising stats\n"
1451 " -v, -- dump buffer to standard output\n"
1452 " -q, -- quiet mode, do not show I/O statistics\n"
1453 "\n");
1456 static int aio_read_f(BlockBackend *blk, int argc, char **argv);
1458 static const cmdinfo_t aio_read_cmd = {
1459 .name = "aio_read",
1460 .cfunc = aio_read_f,
1461 .argmin = 2,
1462 .argmax = -1,
1463 .args = "[-Ciqv] [-P pattern] off len [len..]",
1464 .oneline = "asynchronously reads a number of bytes",
1465 .help = aio_read_help,
1468 static int aio_read_f(BlockBackend *blk, int argc, char **argv)
1470 int nr_iov, c;
1471 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1473 ctx->blk = blk;
1474 while ((c = getopt(argc, argv, "CP:iqv")) != -1) {
1475 switch (c) {
1476 case 'C':
1477 ctx->Cflag = true;
1478 break;
1479 case 'P':
1480 ctx->Pflag = true;
1481 ctx->pattern = parse_pattern(optarg);
1482 if (ctx->pattern < 0) {
1483 g_free(ctx);
1484 return -EINVAL;
1486 break;
1487 case 'i':
1488 printf("injecting invalid read request\n");
1489 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1490 g_free(ctx);
1491 return 0;
1492 case 'q':
1493 ctx->qflag = true;
1494 break;
1495 case 'v':
1496 ctx->vflag = true;
1497 break;
1498 default:
1499 g_free(ctx);
1500 qemuio_command_usage(&aio_read_cmd);
1501 return -EINVAL;
1505 if (optind > argc - 2) {
1506 g_free(ctx);
1507 qemuio_command_usage(&aio_read_cmd);
1508 return -EINVAL;
1511 ctx->offset = cvtnum(argv[optind]);
1512 if (ctx->offset < 0) {
1513 int ret = ctx->offset;
1514 print_cvtnum_err(ret, argv[optind]);
1515 g_free(ctx);
1516 return ret;
1518 optind++;
1520 nr_iov = argc - optind;
1521 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1522 if (ctx->buf == NULL) {
1523 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1524 g_free(ctx);
1525 return -EINVAL;
1528 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
1529 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1530 BLOCK_ACCT_READ);
1531 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
1532 return 0;
1535 static void aio_write_help(void)
1537 printf(
1538 "\n"
1539 " asynchronously writes a range of bytes from the given offset source\n"
1540 " from multiple buffers\n"
1541 "\n"
1542 " Example:\n"
1543 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1544 "\n"
1545 " Writes into a segment of the currently open file, using a buffer\n"
1546 " filled with a set pattern (0xcdcdcdcd).\n"
1547 " The write is performed asynchronously and the aio_flush command must be\n"
1548 " used to ensure all outstanding aio requests have been completed.\n"
1549 " Note that due to its asynchronous nature, this command will be\n"
1550 " considered successful once the request is submitted, independently\n"
1551 " of potential I/O errors or pattern mismatches.\n"
1552 " -P, -- use different pattern to fill file\n"
1553 " -C, -- report statistics in a machine parsable format\n"
1554 " -f, -- use Force Unit Access semantics\n"
1555 " -i, -- treat request as invalid, for exercising stats\n"
1556 " -q, -- quiet mode, do not show I/O statistics\n"
1557 " -u, -- with -z, allow unmapping\n"
1558 " -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
1559 "\n");
1562 static int aio_write_f(BlockBackend *blk, int argc, char **argv);
1564 static const cmdinfo_t aio_write_cmd = {
1565 .name = "aio_write",
1566 .cfunc = aio_write_f,
1567 .perm = BLK_PERM_WRITE,
1568 .argmin = 2,
1569 .argmax = -1,
1570 .args = "[-Cfiquz] [-P pattern] off len [len..]",
1571 .oneline = "asynchronously writes a number of bytes",
1572 .help = aio_write_help,
1575 static int aio_write_f(BlockBackend *blk, int argc, char **argv)
1577 int nr_iov, c;
1578 int pattern = 0xcd;
1579 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1580 int flags = 0;
1582 ctx->blk = blk;
1583 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
1584 switch (c) {
1585 case 'C':
1586 ctx->Cflag = true;
1587 break;
1588 case 'f':
1589 flags |= BDRV_REQ_FUA;
1590 break;
1591 case 'q':
1592 ctx->qflag = true;
1593 break;
1594 case 'u':
1595 flags |= BDRV_REQ_MAY_UNMAP;
1596 break;
1597 case 'P':
1598 pattern = parse_pattern(optarg);
1599 if (pattern < 0) {
1600 g_free(ctx);
1601 return -EINVAL;
1603 break;
1604 case 'i':
1605 printf("injecting invalid write request\n");
1606 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1607 g_free(ctx);
1608 return 0;
1609 case 'z':
1610 ctx->zflag = true;
1611 break;
1612 default:
1613 g_free(ctx);
1614 qemuio_command_usage(&aio_write_cmd);
1615 return -EINVAL;
1619 if (optind > argc - 2) {
1620 g_free(ctx);
1621 qemuio_command_usage(&aio_write_cmd);
1622 return -EINVAL;
1625 if (ctx->zflag && optind != argc - 2) {
1626 printf("-z supports only a single length parameter\n");
1627 g_free(ctx);
1628 return -EINVAL;
1631 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
1632 printf("-u requires -z to be specified\n");
1633 g_free(ctx);
1634 return -EINVAL;
1637 if (ctx->zflag && ctx->Pflag) {
1638 printf("-z and -P cannot be specified at the same time\n");
1639 g_free(ctx);
1640 return -EINVAL;
1643 ctx->offset = cvtnum(argv[optind]);
1644 if (ctx->offset < 0) {
1645 int ret = ctx->offset;
1646 print_cvtnum_err(ret, argv[optind]);
1647 g_free(ctx);
1648 return ret;
1650 optind++;
1652 if (ctx->zflag) {
1653 int64_t count = cvtnum(argv[optind]);
1654 if (count < 0) {
1655 print_cvtnum_err(count, argv[optind]);
1656 g_free(ctx);
1657 return count;
1660 ctx->qiov.size = count;
1661 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done,
1662 ctx);
1663 } else {
1664 nr_iov = argc - optind;
1665 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
1666 pattern);
1667 if (ctx->buf == NULL) {
1668 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1669 g_free(ctx);
1670 return -EINVAL;
1673 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
1674 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1675 BLOCK_ACCT_WRITE);
1677 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
1678 ctx);
1681 return 0;
1684 static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
1686 BlockAcctCookie cookie;
1687 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
1688 blk_drain_all();
1689 block_acct_done(blk_get_stats(blk), &cookie);
1690 return 0;
1693 static const cmdinfo_t aio_flush_cmd = {
1694 .name = "aio_flush",
1695 .cfunc = aio_flush_f,
1696 .oneline = "completes all outstanding aio requests"
1699 static int flush_f(BlockBackend *blk, int argc, char **argv)
1701 return blk_flush(blk);
1704 static const cmdinfo_t flush_cmd = {
1705 .name = "flush",
1706 .altname = "f",
1707 .cfunc = flush_f,
1708 .oneline = "flush all in-core file state to disk",
1711 static int truncate_f(BlockBackend *blk, int argc, char **argv);
1712 static const cmdinfo_t truncate_cmd = {
1713 .name = "truncate",
1714 .altname = "t",
1715 .cfunc = truncate_f,
1716 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
1717 .argmin = 1,
1718 .argmax = 3,
1719 .args = "[-m prealloc_mode] off",
1720 .oneline = "truncates the current file at the given offset",
1723 static int truncate_f(BlockBackend *blk, int argc, char **argv)
1725 Error *local_err = NULL;
1726 int64_t offset;
1727 int c, ret;
1728 PreallocMode prealloc = PREALLOC_MODE_OFF;
1730 while ((c = getopt(argc, argv, "m:")) != -1) {
1731 switch (c) {
1732 case 'm':
1733 prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
1734 PREALLOC_MODE__MAX, NULL);
1735 if (prealloc == PREALLOC_MODE__MAX) {
1736 error_report("Invalid preallocation mode '%s'", optarg);
1737 return -EINVAL;
1739 break;
1740 default:
1741 qemuio_command_usage(&truncate_cmd);
1742 return -EINVAL;
1746 offset = cvtnum(argv[optind]);
1747 if (offset < 0) {
1748 print_cvtnum_err(offset, argv[1]);
1749 return offset;
1753 * qemu-io is a debugging tool, so let us be strict here and pass
1754 * exact=true. It is better to err on the "emit more errors" side
1755 * than to be overly permissive.
1757 ret = blk_truncate(blk, offset, false, prealloc, 0, &local_err);
1758 if (ret < 0) {
1759 error_report_err(local_err);
1760 return ret;
1763 return 0;
1766 static int length_f(BlockBackend *blk, int argc, char **argv)
1768 int64_t size;
1769 char s1[64];
1771 size = blk_getlength(blk);
1772 if (size < 0) {
1773 printf("getlength: %s\n", strerror(-size));
1774 return size;
1777 cvtstr(size, s1, sizeof(s1));
1778 printf("%s\n", s1);
1779 return 0;
1783 static const cmdinfo_t length_cmd = {
1784 .name = "length",
1785 .altname = "l",
1786 .cfunc = length_f,
1787 .oneline = "gets the length of the current file",
1791 static int info_f(BlockBackend *blk, int argc, char **argv)
1793 BlockDriverState *bs = blk_bs(blk);
1794 BlockDriverInfo bdi;
1795 ImageInfoSpecific *spec_info;
1796 Error *local_err = NULL;
1797 char s1[64], s2[64];
1798 int ret;
1800 if (bs->drv && bs->drv->format_name) {
1801 printf("format name: %s\n", bs->drv->format_name);
1803 if (bs->drv && bs->drv->protocol_name) {
1804 printf("format name: %s\n", bs->drv->protocol_name);
1807 ret = bdrv_get_info(bs, &bdi);
1808 if (ret) {
1809 return ret;
1812 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1813 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1815 printf("cluster size: %s\n", s1);
1816 printf("vm state offset: %s\n", s2);
1818 spec_info = bdrv_get_specific_info(bs, &local_err);
1819 if (local_err) {
1820 error_report_err(local_err);
1821 return -EIO;
1823 if (spec_info) {
1824 printf("Format specific information:\n");
1825 bdrv_image_info_specific_dump(spec_info);
1826 qapi_free_ImageInfoSpecific(spec_info);
1829 return 0;
1834 static const cmdinfo_t info_cmd = {
1835 .name = "info",
1836 .altname = "i",
1837 .cfunc = info_f,
1838 .oneline = "prints information about the current file",
1841 static void discard_help(void)
1843 printf(
1844 "\n"
1845 " discards a range of bytes from the given offset\n"
1846 "\n"
1847 " Example:\n"
1848 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1849 "\n"
1850 " Discards a segment of the currently open file.\n"
1851 " -C, -- report statistics in a machine parsable format\n"
1852 " -q, -- quiet mode, do not show I/O statistics\n"
1853 "\n");
1856 static int discard_f(BlockBackend *blk, int argc, char **argv);
1858 static const cmdinfo_t discard_cmd = {
1859 .name = "discard",
1860 .altname = "d",
1861 .cfunc = discard_f,
1862 .perm = BLK_PERM_WRITE,
1863 .argmin = 2,
1864 .argmax = -1,
1865 .args = "[-Cq] off len",
1866 .oneline = "discards a number of bytes at a specified offset",
1867 .help = discard_help,
1870 static int discard_f(BlockBackend *blk, int argc, char **argv)
1872 struct timespec t1, t2;
1873 bool Cflag = false, qflag = false;
1874 int c, ret;
1875 int64_t offset, bytes;
1877 while ((c = getopt(argc, argv, "Cq")) != -1) {
1878 switch (c) {
1879 case 'C':
1880 Cflag = true;
1881 break;
1882 case 'q':
1883 qflag = true;
1884 break;
1885 default:
1886 qemuio_command_usage(&discard_cmd);
1887 return -EINVAL;
1891 if (optind != argc - 2) {
1892 qemuio_command_usage(&discard_cmd);
1893 return -EINVAL;
1896 offset = cvtnum(argv[optind]);
1897 if (offset < 0) {
1898 print_cvtnum_err(offset, argv[optind]);
1899 return offset;
1902 optind++;
1903 bytes = cvtnum(argv[optind]);
1904 if (bytes < 0) {
1905 print_cvtnum_err(bytes, argv[optind]);
1906 return bytes;
1907 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
1908 printf("length cannot exceed %"PRIu64", given %s\n",
1909 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
1910 return -EINVAL;
1913 clock_gettime(CLOCK_MONOTONIC, &t1);
1914 ret = blk_pdiscard(blk, offset, bytes);
1915 clock_gettime(CLOCK_MONOTONIC, &t2);
1917 if (ret < 0) {
1918 printf("discard failed: %s\n", strerror(-ret));
1919 return ret;
1922 /* Finally, report back -- -C gives a parsable format */
1923 if (!qflag) {
1924 t2 = tsub(t2, t1);
1925 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
1928 return 0;
1931 static int alloc_f(BlockBackend *blk, int argc, char **argv)
1933 BlockDriverState *bs = blk_bs(blk);
1934 int64_t offset, start, remaining, count;
1935 char s1[64];
1936 int ret;
1937 int64_t num, sum_alloc;
1939 start = offset = cvtnum(argv[1]);
1940 if (offset < 0) {
1941 print_cvtnum_err(offset, argv[1]);
1942 return offset;
1945 if (argc == 3) {
1946 count = cvtnum(argv[2]);
1947 if (count < 0) {
1948 print_cvtnum_err(count, argv[2]);
1949 return count;
1951 } else {
1952 count = BDRV_SECTOR_SIZE;
1955 remaining = count;
1956 sum_alloc = 0;
1957 while (remaining) {
1958 ret = bdrv_is_allocated(bs, offset, remaining, &num);
1959 if (ret < 0) {
1960 printf("is_allocated failed: %s\n", strerror(-ret));
1961 return ret;
1963 offset += num;
1964 remaining -= num;
1965 if (ret) {
1966 sum_alloc += num;
1968 if (num == 0) {
1969 count -= remaining;
1970 remaining = 0;
1974 cvtstr(start, s1, sizeof(s1));
1976 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
1977 sum_alloc, count, s1);
1978 return 0;
1981 static const cmdinfo_t alloc_cmd = {
1982 .name = "alloc",
1983 .altname = "a",
1984 .argmin = 1,
1985 .argmax = 2,
1986 .cfunc = alloc_f,
1987 .args = "offset [count]",
1988 .oneline = "checks if offset is allocated in the file",
1992 static int map_is_allocated(BlockDriverState *bs, int64_t offset,
1993 int64_t bytes, int64_t *pnum)
1995 int64_t num;
1996 int num_checked;
1997 int ret, firstret;
1999 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
2000 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
2001 if (ret < 0) {
2002 return ret;
2005 firstret = ret;
2006 *pnum = num;
2008 while (bytes > 0 && ret == firstret) {
2009 offset += num;
2010 bytes -= num;
2012 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
2013 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
2014 if (ret == firstret && num) {
2015 *pnum += num;
2016 } else {
2017 break;
2021 return firstret;
2024 static int map_f(BlockBackend *blk, int argc, char **argv)
2026 int64_t offset, bytes;
2027 char s1[64], s2[64];
2028 int64_t num;
2029 int ret;
2030 const char *retstr;
2032 offset = 0;
2033 bytes = blk_getlength(blk);
2034 if (bytes < 0) {
2035 error_report("Failed to query image length: %s", strerror(-bytes));
2036 return bytes;
2039 while (bytes) {
2040 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
2041 if (ret < 0) {
2042 error_report("Failed to get allocation status: %s", strerror(-ret));
2043 return ret;
2044 } else if (!num) {
2045 error_report("Unexpected end of image");
2046 return -EIO;
2049 retstr = ret ? " allocated" : "not allocated";
2050 cvtstr(num, s1, sizeof(s1));
2051 cvtstr(offset, s2, sizeof(s2));
2052 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
2053 s1, num, retstr, s2, offset);
2055 offset += num;
2056 bytes -= num;
2059 return 0;
2062 static const cmdinfo_t map_cmd = {
2063 .name = "map",
2064 .argmin = 0,
2065 .argmax = 0,
2066 .cfunc = map_f,
2067 .args = "",
2068 .oneline = "prints the allocated areas of a file",
2071 static void reopen_help(void)
2073 printf(
2074 "\n"
2075 " Changes the open options of an already opened image\n"
2076 "\n"
2077 " Example:\n"
2078 " 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2079 "\n"
2080 " -r, -- Reopen the image read-only\n"
2081 " -w, -- Reopen the image read-write\n"
2082 " -c, -- Change the cache mode to the given value\n"
2083 " -o, -- Changes block driver options (cf. 'open' command)\n"
2084 "\n");
2087 static int reopen_f(BlockBackend *blk, int argc, char **argv);
2089 static QemuOptsList reopen_opts = {
2090 .name = "reopen",
2091 .merge_lists = true,
2092 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2093 .desc = {
2094 /* no elements => accept any params */
2095 { /* end of list */ }
2099 static const cmdinfo_t reopen_cmd = {
2100 .name = "reopen",
2101 .argmin = 0,
2102 .argmax = -1,
2103 .cfunc = reopen_f,
2104 .args = "[(-r|-w)] [-c cache] [-o options]",
2105 .oneline = "reopens an image with new options",
2106 .help = reopen_help,
2109 static int reopen_f(BlockBackend *blk, int argc, char **argv)
2111 BlockDriverState *bs = blk_bs(blk);
2112 QemuOpts *qopts;
2113 QDict *opts;
2114 int c;
2115 int flags = bs->open_flags;
2116 bool writethrough = !blk_enable_write_cache(blk);
2117 bool has_rw_option = false;
2118 bool has_cache_option = false;
2119 Error *local_err = NULL;
2121 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
2122 switch (c) {
2123 case 'c':
2124 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
2125 error_report("Invalid cache option: %s", optarg);
2126 return -EINVAL;
2128 has_cache_option = true;
2129 break;
2130 case 'o':
2131 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2132 qemu_opts_reset(&reopen_opts);
2133 return -EINVAL;
2135 break;
2136 case 'r':
2137 if (has_rw_option) {
2138 error_report("Only one -r/-w option may be given");
2139 return -EINVAL;
2141 flags &= ~BDRV_O_RDWR;
2142 has_rw_option = true;
2143 break;
2144 case 'w':
2145 if (has_rw_option) {
2146 error_report("Only one -r/-w option may be given");
2147 return -EINVAL;
2149 flags |= BDRV_O_RDWR;
2150 has_rw_option = true;
2151 break;
2152 default:
2153 qemu_opts_reset(&reopen_opts);
2154 qemuio_command_usage(&reopen_cmd);
2155 return -EINVAL;
2159 if (optind != argc) {
2160 qemu_opts_reset(&reopen_opts);
2161 qemuio_command_usage(&reopen_cmd);
2162 return -EINVAL;
2165 if (!writethrough != blk_enable_write_cache(blk) &&
2166 blk_get_attached_dev(blk))
2168 error_report("Cannot change cache.writeback: Device attached");
2169 qemu_opts_reset(&reopen_opts);
2170 return -EBUSY;
2173 if (!(flags & BDRV_O_RDWR)) {
2174 uint64_t orig_perm, orig_shared_perm;
2176 bdrv_drain(bs);
2178 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2179 blk_set_perm(blk,
2180 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2181 orig_shared_perm,
2182 &error_abort);
2185 qopts = qemu_opts_find(&reopen_opts, NULL);
2186 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
2187 qemu_opts_reset(&reopen_opts);
2189 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2190 if (has_rw_option) {
2191 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2192 qobject_unref(opts);
2193 return -EINVAL;
2195 } else {
2196 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2199 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2200 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2201 if (has_cache_option) {
2202 error_report("Cannot set both -c and the cache options");
2203 qobject_unref(opts);
2204 return -EINVAL;
2206 } else {
2207 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2208 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2211 bdrv_reopen(bs, opts, true, &local_err);
2213 if (local_err) {
2214 error_report_err(local_err);
2215 return -EINVAL;
2218 blk_set_enable_write_cache(blk, !writethrough);
2219 return 0;
2222 static int break_f(BlockBackend *blk, int argc, char **argv)
2224 int ret;
2226 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
2227 if (ret < 0) {
2228 printf("Could not set breakpoint: %s\n", strerror(-ret));
2229 return ret;
2232 return 0;
2235 static int remove_break_f(BlockBackend *blk, int argc, char **argv)
2237 int ret;
2239 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
2240 if (ret < 0) {
2241 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
2242 return ret;
2245 return 0;
2248 static const cmdinfo_t break_cmd = {
2249 .name = "break",
2250 .argmin = 2,
2251 .argmax = 2,
2252 .cfunc = break_f,
2253 .args = "event tag",
2254 .oneline = "sets a breakpoint on event and tags the stopped "
2255 "request as tag",
2258 static const cmdinfo_t remove_break_cmd = {
2259 .name = "remove_break",
2260 .argmin = 1,
2261 .argmax = 1,
2262 .cfunc = remove_break_f,
2263 .args = "tag",
2264 .oneline = "remove a breakpoint by tag",
2267 static int resume_f(BlockBackend *blk, int argc, char **argv)
2269 int ret;
2271 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
2272 if (ret < 0) {
2273 printf("Could not resume request: %s\n", strerror(-ret));
2274 return ret;
2277 return 0;
2280 static const cmdinfo_t resume_cmd = {
2281 .name = "resume",
2282 .argmin = 1,
2283 .argmax = 1,
2284 .cfunc = resume_f,
2285 .args = "tag",
2286 .oneline = "resumes the request tagged as tag",
2289 static int wait_break_f(BlockBackend *blk, int argc, char **argv)
2291 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2292 aio_poll(blk_get_aio_context(blk), true);
2294 return 0;
2297 static const cmdinfo_t wait_break_cmd = {
2298 .name = "wait_break",
2299 .argmin = 1,
2300 .argmax = 1,
2301 .cfunc = wait_break_f,
2302 .args = "tag",
2303 .oneline = "waits for the suspension of a request",
2306 static int abort_f(BlockBackend *blk, int argc, char **argv)
2308 abort();
2311 static const cmdinfo_t abort_cmd = {
2312 .name = "abort",
2313 .cfunc = abort_f,
2314 .flags = CMD_NOFILE_OK,
2315 .oneline = "simulate a program crash using abort(3)",
2318 static void sigraise_help(void)
2320 printf(
2321 "\n"
2322 " raises the given signal\n"
2323 "\n"
2324 " Example:\n"
2325 " 'sigraise %i' - raises SIGTERM\n"
2326 "\n"
2327 " Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2328 " given to sigraise.\n"
2329 "\n", SIGTERM);
2332 static int sigraise_f(BlockBackend *blk, int argc, char **argv);
2334 static const cmdinfo_t sigraise_cmd = {
2335 .name = "sigraise",
2336 .cfunc = sigraise_f,
2337 .argmin = 1,
2338 .argmax = 1,
2339 .flags = CMD_NOFILE_OK,
2340 .args = "signal",
2341 .oneline = "raises a signal",
2342 .help = sigraise_help,
2345 static int sigraise_f(BlockBackend *blk, int argc, char **argv)
2347 int64_t sig = cvtnum(argv[1]);
2348 if (sig < 0) {
2349 print_cvtnum_err(sig, argv[1]);
2350 return sig;
2351 } else if (sig > NSIG) {
2352 printf("signal argument '%s' is too large to be a valid signal\n",
2353 argv[1]);
2354 return -EINVAL;
2357 /* Using raise() to kill this process does not necessarily flush all open
2358 * streams. At least stdout and stderr (although the latter should be
2359 * non-buffered anyway) should be flushed, though. */
2360 fflush(stdout);
2361 fflush(stderr);
2363 raise(sig);
2365 return 0;
2368 static void sleep_cb(void *opaque)
2370 bool *expired = opaque;
2371 *expired = true;
2374 static int sleep_f(BlockBackend *blk, int argc, char **argv)
2376 char *endptr;
2377 long ms;
2378 struct QEMUTimer *timer;
2379 bool expired = false;
2381 ms = strtol(argv[1], &endptr, 0);
2382 if (ms < 0 || *endptr != '\0') {
2383 printf("%s is not a valid number\n", argv[1]);
2384 return -EINVAL;
2387 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2388 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2390 while (!expired) {
2391 main_loop_wait(false);
2394 timer_free(timer);
2395 return 0;
2398 static const cmdinfo_t sleep_cmd = {
2399 .name = "sleep",
2400 .argmin = 1,
2401 .argmax = 1,
2402 .cfunc = sleep_f,
2403 .flags = CMD_NOFILE_OK,
2404 .oneline = "waits for the given value in milliseconds",
2407 static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2409 printf("%s ", cmd);
2411 if (ct->args) {
2412 printf("%s ", ct->args);
2414 printf("-- %s\n", ct->oneline);
2417 static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2419 help_oneline(cmd, ct);
2420 if (ct->help) {
2421 ct->help();
2425 static void help_all(void)
2427 const cmdinfo_t *ct;
2429 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2430 help_oneline(ct->name, ct);
2432 printf("\nUse 'help commandname' for extended help.\n");
2435 static int help_f(BlockBackend *blk, int argc, char **argv)
2437 const cmdinfo_t *ct;
2439 if (argc < 2) {
2440 help_all();
2441 return 0;
2444 ct = find_command(argv[1]);
2445 if (ct == NULL) {
2446 printf("command %s not found\n", argv[1]);
2447 return -EINVAL;
2450 help_onecmd(argv[1], ct);
2451 return 0;
2454 static const cmdinfo_t help_cmd = {
2455 .name = "help",
2456 .altname = "?",
2457 .cfunc = help_f,
2458 .argmin = 0,
2459 .argmax = 1,
2460 .flags = CMD_FLAG_GLOBAL,
2461 .args = "[command]",
2462 .oneline = "help for one or all commands",
2466 * Called with aio context of blk acquired. Or with qemu_get_aio_context()
2467 * context acquired if blk is NULL.
2469 int qemuio_command(BlockBackend *blk, const char *cmd)
2471 char *input;
2472 const cmdinfo_t *ct;
2473 char **v;
2474 int c;
2475 int ret = 0;
2477 input = g_strdup(cmd);
2478 v = breakline(input, &c);
2479 if (c) {
2480 ct = find_command(v[0]);
2481 if (ct) {
2482 ret = command(blk, ct, c, v);
2483 } else {
2484 fprintf(stderr, "command \"%s\" not found\n", v[0]);
2485 ret = -EINVAL;
2488 g_free(input);
2489 g_free(v);
2491 return ret;
2494 static void __attribute((constructor)) init_qemuio_commands(void)
2496 /* initialize commands */
2497 qemuio_add_command(&help_cmd);
2498 qemuio_add_command(&read_cmd);
2499 qemuio_add_command(&readv_cmd);
2500 qemuio_add_command(&write_cmd);
2501 qemuio_add_command(&writev_cmd);
2502 qemuio_add_command(&aio_read_cmd);
2503 qemuio_add_command(&aio_write_cmd);
2504 qemuio_add_command(&aio_flush_cmd);
2505 qemuio_add_command(&flush_cmd);
2506 qemuio_add_command(&truncate_cmd);
2507 qemuio_add_command(&length_cmd);
2508 qemuio_add_command(&info_cmd);
2509 qemuio_add_command(&discard_cmd);
2510 qemuio_add_command(&alloc_cmd);
2511 qemuio_add_command(&map_cmd);
2512 qemuio_add_command(&reopen_cmd);
2513 qemuio_add_command(&break_cmd);
2514 qemuio_add_command(&remove_break_cmd);
2515 qemuio_add_command(&resume_cmd);
2516 qemuio_add_command(&wait_break_cmd);
2517 qemuio_add_command(&abort_cmd);
2518 qemuio_add_command(&sleep_cmd);
2519 qemuio_add_command(&sigraise_cmd);