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