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