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