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