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