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