apic: QOM'ify APIC
[qemu/ar7.git] / qemu-io-cmds.c
blob85e4982bd802c1c7e07ffb9e2522df8d9a4da3e7
1 /*
2 * Command line utility to exercise the QEMU I/O path.
4 * Copyright (C) 2009 Red Hat, Inc.
5 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
9 */
11 #include "qemu-io.h"
12 #include "block/block_int.h"
13 #include "block/qapi.h"
14 #include "qemu/main-loop.h"
16 #define CMD_NOFILE_OK 0x01
18 int qemuio_misalign;
20 static cmdinfo_t *cmdtab;
21 static int ncmds;
23 static int compare_cmdname(const void *a, const void *b)
25 return strcmp(((const cmdinfo_t *)a)->name,
26 ((const cmdinfo_t *)b)->name);
29 void qemuio_add_command(const cmdinfo_t *ci)
31 cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
32 cmdtab[ncmds - 1] = *ci;
33 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
36 int qemuio_command_usage(const cmdinfo_t *ci)
38 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
39 return 0;
42 static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
44 if (ct->flags & CMD_FLAG_GLOBAL) {
45 return 1;
47 if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
48 fprintf(stderr, "no file open, try 'help open'\n");
49 return 0;
51 return 1;
54 static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
55 char **argv)
57 char *cmd = argv[0];
59 if (!init_check_command(bs, ct)) {
60 return 0;
63 if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
64 if (ct->argmax == -1) {
65 fprintf(stderr,
66 "bad argument count %d to %s, expected at least %d arguments\n",
67 argc-1, cmd, ct->argmin);
68 } else if (ct->argmin == ct->argmax) {
69 fprintf(stderr,
70 "bad argument count %d to %s, expected %d arguments\n",
71 argc-1, cmd, ct->argmin);
72 } else {
73 fprintf(stderr,
74 "bad argument count %d to %s, expected between %d and %d arguments\n",
75 argc-1, cmd, ct->argmin, ct->argmax);
77 return 0;
79 optind = 0;
80 return ct->cfunc(bs, argc, argv);
83 static const cmdinfo_t *find_command(const char *cmd)
85 cmdinfo_t *ct;
87 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
88 if (strcmp(ct->name, cmd) == 0 ||
89 (ct->altname && strcmp(ct->altname, cmd) == 0))
91 return (const cmdinfo_t *)ct;
94 return NULL;
97 static char **breakline(char *input, int *count)
99 int c = 0;
100 char *p;
101 char **rval = g_malloc0(sizeof(char *));
102 char **tmp;
104 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
105 if (!*p) {
106 continue;
108 c++;
109 tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
110 if (!tmp) {
111 g_free(rval);
112 rval = NULL;
113 c = 0;
114 break;
115 } else {
116 rval = tmp;
118 rval[c - 1] = p;
119 rval[c] = NULL;
121 *count = c;
122 return rval;
125 static int64_t cvtnum(const char *s)
127 char *end;
128 return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
131 #define EXABYTES(x) ((long long)(x) << 60)
132 #define PETABYTES(x) ((long long)(x) << 50)
133 #define TERABYTES(x) ((long long)(x) << 40)
134 #define GIGABYTES(x) ((long long)(x) << 30)
135 #define MEGABYTES(x) ((long long)(x) << 20)
136 #define KILOBYTES(x) ((long long)(x) << 10)
138 #define TO_EXABYTES(x) ((x) / EXABYTES(1))
139 #define TO_PETABYTES(x) ((x) / PETABYTES(1))
140 #define TO_TERABYTES(x) ((x) / TERABYTES(1))
141 #define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
142 #define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
143 #define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
145 static void cvtstr(double value, char *str, size_t size)
147 char *trim;
148 const char *suffix;
150 if (value >= EXABYTES(1)) {
151 suffix = " EiB";
152 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
153 } else if (value >= PETABYTES(1)) {
154 suffix = " PiB";
155 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
156 } else if (value >= TERABYTES(1)) {
157 suffix = " TiB";
158 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
159 } else if (value >= GIGABYTES(1)) {
160 suffix = " GiB";
161 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
162 } else if (value >= MEGABYTES(1)) {
163 suffix = " MiB";
164 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
165 } else if (value >= KILOBYTES(1)) {
166 suffix = " KiB";
167 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
168 } else {
169 suffix = " bytes";
170 snprintf(str, size - 6, "%f", value);
173 trim = strstr(str, ".000");
174 if (trim) {
175 strcpy(trim, suffix);
176 } else {
177 strcat(str, suffix);
183 static struct timeval tsub(struct timeval t1, struct timeval t2)
185 t1.tv_usec -= t2.tv_usec;
186 if (t1.tv_usec < 0) {
187 t1.tv_usec += 1000000;
188 t1.tv_sec--;
190 t1.tv_sec -= t2.tv_sec;
191 return t1;
194 static double tdiv(double value, struct timeval tv)
196 return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
199 #define HOURS(sec) ((sec) / (60 * 60))
200 #define MINUTES(sec) (((sec) % (60 * 60)) / 60)
201 #define SECONDS(sec) ((sec) % 60)
203 enum {
204 DEFAULT_TIME = 0x0,
205 TERSE_FIXED_TIME = 0x1,
206 VERBOSE_FIXED_TIME = 0x2,
209 static void timestr(struct timeval *tv, char *ts, size_t size, int format)
211 double usec = (double)tv->tv_usec / 1000000.0;
213 if (format & TERSE_FIXED_TIME) {
214 if (!HOURS(tv->tv_sec)) {
215 snprintf(ts, size, "%u:%02u.%02u",
216 (unsigned int) MINUTES(tv->tv_sec),
217 (unsigned int) SECONDS(tv->tv_sec),
218 (unsigned int) (usec * 100));
219 return;
221 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
224 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
225 snprintf(ts, size, "%u:%02u:%02u.%02u",
226 (unsigned int) HOURS(tv->tv_sec),
227 (unsigned int) MINUTES(tv->tv_sec),
228 (unsigned int) SECONDS(tv->tv_sec),
229 (unsigned int) (usec * 100));
230 } else {
231 snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
236 * Parse the pattern argument to various sub-commands.
238 * Because the pattern is used as an argument to memset it must evaluate
239 * to an unsigned integer that fits into a single byte.
241 static int parse_pattern(const char *arg)
243 char *endptr = NULL;
244 long pattern;
246 pattern = strtol(arg, &endptr, 0);
247 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
248 printf("%s is not a valid pattern byte\n", arg);
249 return -1;
252 return pattern;
256 * Memory allocation helpers.
258 * Make sure memory is aligned by default, or purposefully misaligned if
259 * that is specified on the command line.
262 #define MISALIGN_OFFSET 16
263 static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
265 void *buf;
267 if (qemuio_misalign) {
268 len += MISALIGN_OFFSET;
270 buf = qemu_blockalign(bs, len);
271 memset(buf, pattern, len);
272 if (qemuio_misalign) {
273 buf += MISALIGN_OFFSET;
275 return buf;
278 static void qemu_io_free(void *p)
280 if (qemuio_misalign) {
281 p -= MISALIGN_OFFSET;
283 qemu_vfree(p);
286 static void dump_buffer(const void *buffer, int64_t offset, int len)
288 int i, j;
289 const uint8_t *p;
291 for (i = 0, p = buffer; i < len; i += 16) {
292 const uint8_t *s = p;
294 printf("%08" PRIx64 ": ", offset + i);
295 for (j = 0; j < 16 && i + j < len; j++, p++) {
296 printf("%02x ", *p);
298 printf(" ");
299 for (j = 0; j < 16 && i + j < len; j++, s++) {
300 if (isalnum(*s)) {
301 printf("%c", *s);
302 } else {
303 printf(".");
306 printf("\n");
310 static void print_report(const char *op, struct timeval *t, int64_t offset,
311 int count, int total, int cnt, int Cflag)
313 char s1[64], s2[64], ts[64];
315 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
316 if (!Cflag) {
317 cvtstr((double)total, s1, sizeof(s1));
318 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
319 printf("%s %d/%d bytes at offset %" PRId64 "\n",
320 op, total, count, offset);
321 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
322 s1, cnt, ts, s2, tdiv((double)cnt, *t));
323 } else {/* bytes,ops,time,bytes/sec,ops/sec */
324 printf("%d,%d,%s,%.3f,%.3f\n",
325 total, cnt, ts,
326 tdiv((double)total, *t),
327 tdiv((double)cnt, *t));
332 * Parse multiple length statements for vectored I/O, and construct an I/O
333 * vector matching it.
335 static void *
336 create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
337 int pattern)
339 size_t *sizes = g_new0(size_t, nr_iov);
340 size_t count = 0;
341 void *buf = NULL;
342 void *p;
343 int i;
345 for (i = 0; i < nr_iov; i++) {
346 char *arg = argv[i];
347 int64_t len;
349 len = cvtnum(arg);
350 if (len < 0) {
351 printf("non-numeric length argument -- %s\n", arg);
352 goto fail;
355 /* should be SIZE_T_MAX, but that doesn't exist */
356 if (len > INT_MAX) {
357 printf("too large length argument -- %s\n", arg);
358 goto fail;
361 if (len & 0x1ff) {
362 printf("length argument %" PRId64
363 " is not sector aligned\n", len);
364 goto fail;
367 sizes[i] = len;
368 count += len;
371 qemu_iovec_init(qiov, nr_iov);
373 buf = p = qemu_io_alloc(bs, count, pattern);
375 for (i = 0; i < nr_iov; i++) {
376 qemu_iovec_add(qiov, p, sizes[i]);
377 p += sizes[i];
380 fail:
381 g_free(sizes);
382 return buf;
385 static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
386 int *total)
388 int ret;
390 ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
391 if (ret < 0) {
392 return ret;
394 *total = count;
395 return 1;
398 static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
399 int *total)
401 int ret;
403 ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
404 if (ret < 0) {
405 return ret;
407 *total = count;
408 return 1;
411 static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
412 int *total)
414 *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
415 if (*total < 0) {
416 return *total;
418 return 1;
421 static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
422 int *total)
424 *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
425 if (*total < 0) {
426 return *total;
428 return 1;
431 typedef struct {
432 BlockDriverState *bs;
433 int64_t offset;
434 int count;
435 int *total;
436 int ret;
437 bool done;
438 } CoWriteZeroes;
440 static void coroutine_fn co_write_zeroes_entry(void *opaque)
442 CoWriteZeroes *data = opaque;
444 data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
445 data->count / BDRV_SECTOR_SIZE, 0);
446 data->done = true;
447 if (data->ret < 0) {
448 *data->total = data->ret;
449 return;
452 *data->total = data->count;
455 static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
456 int *total)
458 Coroutine *co;
459 CoWriteZeroes data = {
460 .bs = bs,
461 .offset = offset,
462 .count = count,
463 .total = total,
464 .done = false,
467 co = qemu_coroutine_create(co_write_zeroes_entry);
468 qemu_coroutine_enter(co, &data);
469 while (!data.done) {
470 qemu_aio_wait();
472 if (data.ret < 0) {
473 return data.ret;
474 } else {
475 return 1;
479 static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
480 int count, int *total)
482 int ret;
484 ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
485 if (ret < 0) {
486 return ret;
488 *total = count;
489 return 1;
492 static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
493 int count, int *total)
495 *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
496 if (*total < 0) {
497 return *total;
499 return 1;
502 static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
503 int count, int *total)
505 *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
506 if (*total < 0) {
507 return *total;
509 return 1;
512 #define NOT_DONE 0x7fffffff
513 static void aio_rw_done(void *opaque, int ret)
515 *(int *)opaque = ret;
518 static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
519 int64_t offset, int *total)
521 int async_ret = NOT_DONE;
523 bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
524 aio_rw_done, &async_ret);
525 while (async_ret == NOT_DONE) {
526 main_loop_wait(false);
529 *total = qiov->size;
530 return async_ret < 0 ? async_ret : 1;
533 static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
534 int64_t offset, int *total)
536 int async_ret = NOT_DONE;
538 bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
539 aio_rw_done, &async_ret);
540 while (async_ret == NOT_DONE) {
541 main_loop_wait(false);
544 *total = qiov->size;
545 return async_ret < 0 ? async_ret : 1;
548 struct multiwrite_async_ret {
549 int num_done;
550 int error;
553 static void multiwrite_cb(void *opaque, int ret)
555 struct multiwrite_async_ret *async_ret = opaque;
557 async_ret->num_done++;
558 if (ret < 0) {
559 async_ret->error = ret;
563 static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
564 int num_reqs, int *total)
566 int i, ret;
567 struct multiwrite_async_ret async_ret = {
568 .num_done = 0,
569 .error = 0,
572 *total = 0;
573 for (i = 0; i < num_reqs; i++) {
574 reqs[i].cb = multiwrite_cb;
575 reqs[i].opaque = &async_ret;
576 *total += reqs[i].qiov->size;
579 ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
580 if (ret < 0) {
581 return ret;
584 while (async_ret.num_done < num_reqs) {
585 main_loop_wait(false);
588 return async_ret.error < 0 ? async_ret.error : 1;
591 static void read_help(void)
593 printf(
594 "\n"
595 " reads a range of bytes from the given offset\n"
596 "\n"
597 " Example:\n"
598 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
599 "\n"
600 " Reads a segment of the currently open file, optionally dumping it to the\n"
601 " standard output stream (with -v option) for subsequent inspection.\n"
602 " -b, -- read from the VM state rather than the virtual disk\n"
603 " -C, -- report statistics in a machine parsable format\n"
604 " -l, -- length for pattern verification (only with -P)\n"
605 " -p, -- use bdrv_pread to read the file\n"
606 " -P, -- use a pattern to verify read data\n"
607 " -q, -- quiet mode, do not show I/O statistics\n"
608 " -s, -- start offset for pattern verification (only with -P)\n"
609 " -v, -- dump buffer to standard output\n"
610 "\n");
613 static int read_f(BlockDriverState *bs, int argc, char **argv);
615 static const cmdinfo_t read_cmd = {
616 .name = "read",
617 .altname = "r",
618 .cfunc = read_f,
619 .argmin = 2,
620 .argmax = -1,
621 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
622 .oneline = "reads a number of bytes at a specified offset",
623 .help = read_help,
626 static int read_f(BlockDriverState *bs, int argc, char **argv)
628 struct timeval t1, t2;
629 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
630 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
631 int c, cnt;
632 char *buf;
633 int64_t offset;
634 int count;
635 /* Some compilers get confused and warn if this is not initialized. */
636 int total = 0;
637 int pattern = 0, pattern_offset = 0, pattern_count = 0;
639 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
640 switch (c) {
641 case 'b':
642 bflag = 1;
643 break;
644 case 'C':
645 Cflag = 1;
646 break;
647 case 'l':
648 lflag = 1;
649 pattern_count = cvtnum(optarg);
650 if (pattern_count < 0) {
651 printf("non-numeric length argument -- %s\n", optarg);
652 return 0;
654 break;
655 case 'p':
656 pflag = 1;
657 break;
658 case 'P':
659 Pflag = 1;
660 pattern = parse_pattern(optarg);
661 if (pattern < 0) {
662 return 0;
664 break;
665 case 'q':
666 qflag = 1;
667 break;
668 case 's':
669 sflag = 1;
670 pattern_offset = cvtnum(optarg);
671 if (pattern_offset < 0) {
672 printf("non-numeric length argument -- %s\n", optarg);
673 return 0;
675 break;
676 case 'v':
677 vflag = 1;
678 break;
679 default:
680 return qemuio_command_usage(&read_cmd);
684 if (optind != argc - 2) {
685 return qemuio_command_usage(&read_cmd);
688 if (bflag && pflag) {
689 printf("-b and -p cannot be specified at the same time\n");
690 return 0;
693 offset = cvtnum(argv[optind]);
694 if (offset < 0) {
695 printf("non-numeric length argument -- %s\n", argv[optind]);
696 return 0;
699 optind++;
700 count = cvtnum(argv[optind]);
701 if (count < 0) {
702 printf("non-numeric length argument -- %s\n", argv[optind]);
703 return 0;
706 if (!Pflag && (lflag || sflag)) {
707 return qemuio_command_usage(&read_cmd);
710 if (!lflag) {
711 pattern_count = count - pattern_offset;
714 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
715 printf("pattern verification range exceeds end of read data\n");
716 return 0;
719 if (!pflag) {
720 if (offset & 0x1ff) {
721 printf("offset %" PRId64 " is not sector aligned\n",
722 offset);
723 return 0;
725 if (count & 0x1ff) {
726 printf("count %d is not sector aligned\n",
727 count);
728 return 0;
732 buf = qemu_io_alloc(bs, count, 0xab);
734 gettimeofday(&t1, NULL);
735 if (pflag) {
736 cnt = do_pread(bs, buf, offset, count, &total);
737 } else if (bflag) {
738 cnt = do_load_vmstate(bs, buf, offset, count, &total);
739 } else {
740 cnt = do_read(bs, buf, offset, count, &total);
742 gettimeofday(&t2, NULL);
744 if (cnt < 0) {
745 printf("read failed: %s\n", strerror(-cnt));
746 goto out;
749 if (Pflag) {
750 void *cmp_buf = g_malloc(pattern_count);
751 memset(cmp_buf, pattern, pattern_count);
752 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
753 printf("Pattern verification failed at offset %"
754 PRId64 ", %d bytes\n",
755 offset + pattern_offset, pattern_count);
757 g_free(cmp_buf);
760 if (qflag) {
761 goto out;
764 if (vflag) {
765 dump_buffer(buf, offset, count);
768 /* Finally, report back -- -C gives a parsable format */
769 t2 = tsub(t2, t1);
770 print_report("read", &t2, offset, count, total, cnt, Cflag);
772 out:
773 qemu_io_free(buf);
775 return 0;
778 static void readv_help(void)
780 printf(
781 "\n"
782 " reads a range of bytes from the given offset into multiple buffers\n"
783 "\n"
784 " Example:\n"
785 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
786 "\n"
787 " Reads a segment of the currently open file, optionally dumping it to the\n"
788 " standard output stream (with -v option) for subsequent inspection.\n"
789 " Uses multiple iovec buffers if more than one byte range is specified.\n"
790 " -C, -- report statistics in a machine parsable format\n"
791 " -P, -- use a pattern to verify read data\n"
792 " -v, -- dump buffer to standard output\n"
793 " -q, -- quiet mode, do not show I/O statistics\n"
794 "\n");
797 static int readv_f(BlockDriverState *bs, int argc, char **argv);
799 static const cmdinfo_t readv_cmd = {
800 .name = "readv",
801 .cfunc = readv_f,
802 .argmin = 2,
803 .argmax = -1,
804 .args = "[-Cqv] [-P pattern ] off len [len..]",
805 .oneline = "reads a number of bytes at a specified offset",
806 .help = readv_help,
809 static int readv_f(BlockDriverState *bs, int argc, char **argv)
811 struct timeval t1, t2;
812 int Cflag = 0, qflag = 0, vflag = 0;
813 int c, cnt;
814 char *buf;
815 int64_t offset;
816 /* Some compilers get confused and warn if this is not initialized. */
817 int total = 0;
818 int nr_iov;
819 QEMUIOVector qiov;
820 int pattern = 0;
821 int Pflag = 0;
823 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
824 switch (c) {
825 case 'C':
826 Cflag = 1;
827 break;
828 case 'P':
829 Pflag = 1;
830 pattern = parse_pattern(optarg);
831 if (pattern < 0) {
832 return 0;
834 break;
835 case 'q':
836 qflag = 1;
837 break;
838 case 'v':
839 vflag = 1;
840 break;
841 default:
842 return qemuio_command_usage(&readv_cmd);
846 if (optind > argc - 2) {
847 return qemuio_command_usage(&readv_cmd);
851 offset = cvtnum(argv[optind]);
852 if (offset < 0) {
853 printf("non-numeric length argument -- %s\n", argv[optind]);
854 return 0;
856 optind++;
858 if (offset & 0x1ff) {
859 printf("offset %" PRId64 " is not sector aligned\n",
860 offset);
861 return 0;
864 nr_iov = argc - optind;
865 buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
866 if (buf == NULL) {
867 return 0;
870 gettimeofday(&t1, NULL);
871 cnt = do_aio_readv(bs, &qiov, offset, &total);
872 gettimeofday(&t2, NULL);
874 if (cnt < 0) {
875 printf("readv failed: %s\n", strerror(-cnt));
876 goto out;
879 if (Pflag) {
880 void *cmp_buf = g_malloc(qiov.size);
881 memset(cmp_buf, pattern, qiov.size);
882 if (memcmp(buf, cmp_buf, qiov.size)) {
883 printf("Pattern verification failed at offset %"
884 PRId64 ", %zd bytes\n", offset, qiov.size);
886 g_free(cmp_buf);
889 if (qflag) {
890 goto out;
893 if (vflag) {
894 dump_buffer(buf, offset, qiov.size);
897 /* Finally, report back -- -C gives a parsable format */
898 t2 = tsub(t2, t1);
899 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
901 out:
902 qemu_iovec_destroy(&qiov);
903 qemu_io_free(buf);
904 return 0;
907 static void write_help(void)
909 printf(
910 "\n"
911 " writes a range of bytes from the given offset\n"
912 "\n"
913 " Example:\n"
914 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
915 "\n"
916 " Writes into a segment of the currently open file, using a buffer\n"
917 " filled with a set pattern (0xcdcdcdcd).\n"
918 " -b, -- write to the VM state rather than the virtual disk\n"
919 " -c, -- write compressed data with bdrv_write_compressed\n"
920 " -p, -- use bdrv_pwrite to write the file\n"
921 " -P, -- use different pattern to fill file\n"
922 " -C, -- report statistics in a machine parsable format\n"
923 " -q, -- quiet mode, do not show I/O statistics\n"
924 " -z, -- write zeroes using bdrv_co_write_zeroes\n"
925 "\n");
928 static int write_f(BlockDriverState *bs, int argc, char **argv);
930 static const cmdinfo_t write_cmd = {
931 .name = "write",
932 .altname = "w",
933 .cfunc = write_f,
934 .argmin = 2,
935 .argmax = -1,
936 .args = "[-bcCpqz] [-P pattern ] off len",
937 .oneline = "writes a number of bytes at a specified offset",
938 .help = write_help,
941 static int write_f(BlockDriverState *bs, int argc, char **argv)
943 struct timeval t1, t2;
944 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
945 int cflag = 0;
946 int c, cnt;
947 char *buf = NULL;
948 int64_t offset;
949 int count;
950 /* Some compilers get confused and warn if this is not initialized. */
951 int total = 0;
952 int pattern = 0xcd;
954 while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
955 switch (c) {
956 case 'b':
957 bflag = 1;
958 break;
959 case 'c':
960 cflag = 1;
961 break;
962 case 'C':
963 Cflag = 1;
964 break;
965 case 'p':
966 pflag = 1;
967 break;
968 case 'P':
969 Pflag = 1;
970 pattern = parse_pattern(optarg);
971 if (pattern < 0) {
972 return 0;
974 break;
975 case 'q':
976 qflag = 1;
977 break;
978 case 'z':
979 zflag = 1;
980 break;
981 default:
982 return qemuio_command_usage(&write_cmd);
986 if (optind != argc - 2) {
987 return qemuio_command_usage(&write_cmd);
990 if (bflag + pflag + zflag > 1) {
991 printf("-b, -p, or -z cannot be specified at the same time\n");
992 return 0;
995 if (zflag && Pflag) {
996 printf("-z and -P cannot be specified at the same time\n");
997 return 0;
1000 offset = cvtnum(argv[optind]);
1001 if (offset < 0) {
1002 printf("non-numeric length argument -- %s\n", argv[optind]);
1003 return 0;
1006 optind++;
1007 count = cvtnum(argv[optind]);
1008 if (count < 0) {
1009 printf("non-numeric length argument -- %s\n", argv[optind]);
1010 return 0;
1013 if (!pflag) {
1014 if (offset & 0x1ff) {
1015 printf("offset %" PRId64 " is not sector aligned\n",
1016 offset);
1017 return 0;
1020 if (count & 0x1ff) {
1021 printf("count %d is not sector aligned\n",
1022 count);
1023 return 0;
1027 if (!zflag) {
1028 buf = qemu_io_alloc(bs, count, pattern);
1031 gettimeofday(&t1, NULL);
1032 if (pflag) {
1033 cnt = do_pwrite(bs, buf, offset, count, &total);
1034 } else if (bflag) {
1035 cnt = do_save_vmstate(bs, buf, offset, count, &total);
1036 } else if (zflag) {
1037 cnt = do_co_write_zeroes(bs, offset, count, &total);
1038 } else if (cflag) {
1039 cnt = do_write_compressed(bs, buf, offset, count, &total);
1040 } else {
1041 cnt = do_write(bs, buf, offset, count, &total);
1043 gettimeofday(&t2, NULL);
1045 if (cnt < 0) {
1046 printf("write failed: %s\n", strerror(-cnt));
1047 goto out;
1050 if (qflag) {
1051 goto out;
1054 /* Finally, report back -- -C gives a parsable format */
1055 t2 = tsub(t2, t1);
1056 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1058 out:
1059 if (!zflag) {
1060 qemu_io_free(buf);
1063 return 0;
1066 static void
1067 writev_help(void)
1069 printf(
1070 "\n"
1071 " writes a range of bytes from the given offset source from multiple buffers\n"
1072 "\n"
1073 " Example:\n"
1074 " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1075 "\n"
1076 " Writes into a segment of the currently open file, using a buffer\n"
1077 " filled with a set pattern (0xcdcdcdcd).\n"
1078 " -P, -- use different pattern to fill file\n"
1079 " -C, -- report statistics in a machine parsable format\n"
1080 " -q, -- quiet mode, do not show I/O statistics\n"
1081 "\n");
1084 static int writev_f(BlockDriverState *bs, int argc, char **argv);
1086 static const cmdinfo_t writev_cmd = {
1087 .name = "writev",
1088 .cfunc = writev_f,
1089 .argmin = 2,
1090 .argmax = -1,
1091 .args = "[-Cq] [-P pattern ] off len [len..]",
1092 .oneline = "writes a number of bytes at a specified offset",
1093 .help = writev_help,
1096 static int writev_f(BlockDriverState *bs, int argc, char **argv)
1098 struct timeval t1, t2;
1099 int Cflag = 0, qflag = 0;
1100 int c, cnt;
1101 char *buf;
1102 int64_t offset;
1103 /* Some compilers get confused and warn if this is not initialized. */
1104 int total = 0;
1105 int nr_iov;
1106 int pattern = 0xcd;
1107 QEMUIOVector qiov;
1109 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1110 switch (c) {
1111 case 'C':
1112 Cflag = 1;
1113 break;
1114 case 'q':
1115 qflag = 1;
1116 break;
1117 case 'P':
1118 pattern = parse_pattern(optarg);
1119 if (pattern < 0) {
1120 return 0;
1122 break;
1123 default:
1124 return qemuio_command_usage(&writev_cmd);
1128 if (optind > argc - 2) {
1129 return qemuio_command_usage(&writev_cmd);
1132 offset = cvtnum(argv[optind]);
1133 if (offset < 0) {
1134 printf("non-numeric length argument -- %s\n", argv[optind]);
1135 return 0;
1137 optind++;
1139 if (offset & 0x1ff) {
1140 printf("offset %" PRId64 " is not sector aligned\n",
1141 offset);
1142 return 0;
1145 nr_iov = argc - optind;
1146 buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
1147 if (buf == NULL) {
1148 return 0;
1151 gettimeofday(&t1, NULL);
1152 cnt = do_aio_writev(bs, &qiov, offset, &total);
1153 gettimeofday(&t2, NULL);
1155 if (cnt < 0) {
1156 printf("writev failed: %s\n", strerror(-cnt));
1157 goto out;
1160 if (qflag) {
1161 goto out;
1164 /* Finally, report back -- -C gives a parsable format */
1165 t2 = tsub(t2, t1);
1166 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1167 out:
1168 qemu_iovec_destroy(&qiov);
1169 qemu_io_free(buf);
1170 return 0;
1173 static void multiwrite_help(void)
1175 printf(
1176 "\n"
1177 " writes a range of bytes from the given offset source from multiple buffers,\n"
1178 " in a batch of requests that may be merged by qemu\n"
1179 "\n"
1180 " Example:\n"
1181 " 'multiwrite 512 1k 1k ; 4k 1k'\n"
1182 " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
1183 "\n"
1184 " Writes into a segment of the currently open file, using a buffer\n"
1185 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
1186 " by one for each request contained in the multiwrite command.\n"
1187 " -P, -- use different pattern to fill file\n"
1188 " -C, -- report statistics in a machine parsable format\n"
1189 " -q, -- quiet mode, do not show I/O statistics\n"
1190 "\n");
1193 static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
1195 static const cmdinfo_t multiwrite_cmd = {
1196 .name = "multiwrite",
1197 .cfunc = multiwrite_f,
1198 .argmin = 2,
1199 .argmax = -1,
1200 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
1201 .oneline = "issues multiple write requests at once",
1202 .help = multiwrite_help,
1205 static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
1207 struct timeval t1, t2;
1208 int Cflag = 0, qflag = 0;
1209 int c, cnt;
1210 char **buf;
1211 int64_t offset, first_offset = 0;
1212 /* Some compilers get confused and warn if this is not initialized. */
1213 int total = 0;
1214 int nr_iov;
1215 int nr_reqs;
1216 int pattern = 0xcd;
1217 QEMUIOVector *qiovs;
1218 int i;
1219 BlockRequest *reqs;
1221 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1222 switch (c) {
1223 case 'C':
1224 Cflag = 1;
1225 break;
1226 case 'q':
1227 qflag = 1;
1228 break;
1229 case 'P':
1230 pattern = parse_pattern(optarg);
1231 if (pattern < 0) {
1232 return 0;
1234 break;
1235 default:
1236 return qemuio_command_usage(&writev_cmd);
1240 if (optind > argc - 2) {
1241 return qemuio_command_usage(&writev_cmd);
1244 nr_reqs = 1;
1245 for (i = optind; i < argc; i++) {
1246 if (!strcmp(argv[i], ";")) {
1247 nr_reqs++;
1251 reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1252 buf = g_malloc0(nr_reqs * sizeof(*buf));
1253 qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1255 for (i = 0; i < nr_reqs && optind < argc; i++) {
1256 int j;
1258 /* Read the offset of the request */
1259 offset = cvtnum(argv[optind]);
1260 if (offset < 0) {
1261 printf("non-numeric offset argument -- %s\n", argv[optind]);
1262 goto out;
1264 optind++;
1266 if (offset & 0x1ff) {
1267 printf("offset %lld is not sector aligned\n",
1268 (long long)offset);
1269 goto out;
1272 if (i == 0) {
1273 first_offset = offset;
1276 /* Read lengths for qiov entries */
1277 for (j = optind; j < argc; j++) {
1278 if (!strcmp(argv[j], ";")) {
1279 break;
1283 nr_iov = j - optind;
1285 /* Build request */
1286 buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
1287 if (buf[i] == NULL) {
1288 goto out;
1291 reqs[i].qiov = &qiovs[i];
1292 reqs[i].sector = offset >> 9;
1293 reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1295 optind = j + 1;
1297 pattern++;
1300 /* If there were empty requests at the end, ignore them */
1301 nr_reqs = i;
1303 gettimeofday(&t1, NULL);
1304 cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
1305 gettimeofday(&t2, NULL);
1307 if (cnt < 0) {
1308 printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1309 goto out;
1312 if (qflag) {
1313 goto out;
1316 /* Finally, report back -- -C gives a parsable format */
1317 t2 = tsub(t2, t1);
1318 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1319 out:
1320 for (i = 0; i < nr_reqs; i++) {
1321 qemu_io_free(buf[i]);
1322 if (reqs[i].qiov != NULL) {
1323 qemu_iovec_destroy(&qiovs[i]);
1326 g_free(buf);
1327 g_free(reqs);
1328 g_free(qiovs);
1329 return 0;
1332 struct aio_ctx {
1333 QEMUIOVector qiov;
1334 int64_t offset;
1335 char *buf;
1336 int qflag;
1337 int vflag;
1338 int Cflag;
1339 int Pflag;
1340 int pattern;
1341 struct timeval t1;
1344 static void aio_write_done(void *opaque, int ret)
1346 struct aio_ctx *ctx = opaque;
1347 struct timeval t2;
1349 gettimeofday(&t2, NULL);
1352 if (ret < 0) {
1353 printf("aio_write failed: %s\n", strerror(-ret));
1354 goto out;
1357 if (ctx->qflag) {
1358 goto out;
1361 /* Finally, report back -- -C gives a parsable format */
1362 t2 = tsub(t2, ctx->t1);
1363 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1364 ctx->qiov.size, 1, ctx->Cflag);
1365 out:
1366 qemu_io_free(ctx->buf);
1367 qemu_iovec_destroy(&ctx->qiov);
1368 g_free(ctx);
1371 static void aio_read_done(void *opaque, int ret)
1373 struct aio_ctx *ctx = opaque;
1374 struct timeval t2;
1376 gettimeofday(&t2, NULL);
1378 if (ret < 0) {
1379 printf("readv failed: %s\n", strerror(-ret));
1380 goto out;
1383 if (ctx->Pflag) {
1384 void *cmp_buf = g_malloc(ctx->qiov.size);
1386 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1387 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1388 printf("Pattern verification failed at offset %"
1389 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1391 g_free(cmp_buf);
1394 if (ctx->qflag) {
1395 goto out;
1398 if (ctx->vflag) {
1399 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1402 /* Finally, report back -- -C gives a parsable format */
1403 t2 = tsub(t2, ctx->t1);
1404 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1405 ctx->qiov.size, 1, ctx->Cflag);
1406 out:
1407 qemu_io_free(ctx->buf);
1408 qemu_iovec_destroy(&ctx->qiov);
1409 g_free(ctx);
1412 static void aio_read_help(void)
1414 printf(
1415 "\n"
1416 " asynchronously reads a range of bytes from the given offset\n"
1417 "\n"
1418 " Example:\n"
1419 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1420 "\n"
1421 " Reads a segment of the currently open file, optionally dumping it to the\n"
1422 " standard output stream (with -v option) for subsequent inspection.\n"
1423 " The read is performed asynchronously and the aio_flush command must be\n"
1424 " used to ensure all outstanding aio requests have been completed.\n"
1425 " -C, -- report statistics in a machine parsable format\n"
1426 " -P, -- use a pattern to verify read data\n"
1427 " -v, -- dump buffer to standard output\n"
1428 " -q, -- quiet mode, do not show I/O statistics\n"
1429 "\n");
1432 static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1434 static const cmdinfo_t aio_read_cmd = {
1435 .name = "aio_read",
1436 .cfunc = aio_read_f,
1437 .argmin = 2,
1438 .argmax = -1,
1439 .args = "[-Cqv] [-P pattern ] off len [len..]",
1440 .oneline = "asynchronously reads a number of bytes",
1441 .help = aio_read_help,
1444 static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
1446 int nr_iov, c;
1447 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1449 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1450 switch (c) {
1451 case 'C':
1452 ctx->Cflag = 1;
1453 break;
1454 case 'P':
1455 ctx->Pflag = 1;
1456 ctx->pattern = parse_pattern(optarg);
1457 if (ctx->pattern < 0) {
1458 g_free(ctx);
1459 return 0;
1461 break;
1462 case 'q':
1463 ctx->qflag = 1;
1464 break;
1465 case 'v':
1466 ctx->vflag = 1;
1467 break;
1468 default:
1469 g_free(ctx);
1470 return qemuio_command_usage(&aio_read_cmd);
1474 if (optind > argc - 2) {
1475 g_free(ctx);
1476 return qemuio_command_usage(&aio_read_cmd);
1479 ctx->offset = cvtnum(argv[optind]);
1480 if (ctx->offset < 0) {
1481 printf("non-numeric length argument -- %s\n", argv[optind]);
1482 g_free(ctx);
1483 return 0;
1485 optind++;
1487 if (ctx->offset & 0x1ff) {
1488 printf("offset %" PRId64 " is not sector aligned\n",
1489 ctx->offset);
1490 g_free(ctx);
1491 return 0;
1494 nr_iov = argc - optind;
1495 ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1496 if (ctx->buf == NULL) {
1497 g_free(ctx);
1498 return 0;
1501 gettimeofday(&ctx->t1, NULL);
1502 bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1503 ctx->qiov.size >> 9, aio_read_done, ctx);
1504 return 0;
1507 static void aio_write_help(void)
1509 printf(
1510 "\n"
1511 " asynchronously writes a range of bytes from the given offset source\n"
1512 " from multiple buffers\n"
1513 "\n"
1514 " Example:\n"
1515 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1516 "\n"
1517 " Writes into a segment of the currently open file, using a buffer\n"
1518 " filled with a set pattern (0xcdcdcdcd).\n"
1519 " The write is performed asynchronously and the aio_flush command must be\n"
1520 " used to ensure all outstanding aio requests have been completed.\n"
1521 " -P, -- use different pattern to fill file\n"
1522 " -C, -- report statistics in a machine parsable format\n"
1523 " -q, -- quiet mode, do not show I/O statistics\n"
1524 "\n");
1527 static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1529 static const cmdinfo_t aio_write_cmd = {
1530 .name = "aio_write",
1531 .cfunc = aio_write_f,
1532 .argmin = 2,
1533 .argmax = -1,
1534 .args = "[-Cq] [-P pattern ] off len [len..]",
1535 .oneline = "asynchronously writes a number of bytes",
1536 .help = aio_write_help,
1539 static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
1541 int nr_iov, c;
1542 int pattern = 0xcd;
1543 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1545 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1546 switch (c) {
1547 case 'C':
1548 ctx->Cflag = 1;
1549 break;
1550 case 'q':
1551 ctx->qflag = 1;
1552 break;
1553 case 'P':
1554 pattern = parse_pattern(optarg);
1555 if (pattern < 0) {
1556 g_free(ctx);
1557 return 0;
1559 break;
1560 default:
1561 g_free(ctx);
1562 return qemuio_command_usage(&aio_write_cmd);
1566 if (optind > argc - 2) {
1567 g_free(ctx);
1568 return qemuio_command_usage(&aio_write_cmd);
1571 ctx->offset = cvtnum(argv[optind]);
1572 if (ctx->offset < 0) {
1573 printf("non-numeric length argument -- %s\n", argv[optind]);
1574 g_free(ctx);
1575 return 0;
1577 optind++;
1579 if (ctx->offset & 0x1ff) {
1580 printf("offset %" PRId64 " is not sector aligned\n",
1581 ctx->offset);
1582 g_free(ctx);
1583 return 0;
1586 nr_iov = argc - optind;
1587 ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
1588 if (ctx->buf == NULL) {
1589 g_free(ctx);
1590 return 0;
1593 gettimeofday(&ctx->t1, NULL);
1594 bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1595 ctx->qiov.size >> 9, aio_write_done, ctx);
1596 return 0;
1599 static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1601 bdrv_drain_all();
1602 return 0;
1605 static const cmdinfo_t aio_flush_cmd = {
1606 .name = "aio_flush",
1607 .cfunc = aio_flush_f,
1608 .oneline = "completes all outstanding aio requests"
1611 static int flush_f(BlockDriverState *bs, int argc, char **argv)
1613 bdrv_flush(bs);
1614 return 0;
1617 static const cmdinfo_t flush_cmd = {
1618 .name = "flush",
1619 .altname = "f",
1620 .cfunc = flush_f,
1621 .oneline = "flush all in-core file state to disk",
1624 static int truncate_f(BlockDriverState *bs, int argc, char **argv)
1626 int64_t offset;
1627 int ret;
1629 offset = cvtnum(argv[1]);
1630 if (offset < 0) {
1631 printf("non-numeric truncate argument -- %s\n", argv[1]);
1632 return 0;
1635 ret = bdrv_truncate(bs, offset);
1636 if (ret < 0) {
1637 printf("truncate: %s\n", strerror(-ret));
1638 return 0;
1641 return 0;
1644 static const cmdinfo_t truncate_cmd = {
1645 .name = "truncate",
1646 .altname = "t",
1647 .cfunc = truncate_f,
1648 .argmin = 1,
1649 .argmax = 1,
1650 .args = "off",
1651 .oneline = "truncates the current file at the given offset",
1654 static int length_f(BlockDriverState *bs, int argc, char **argv)
1656 int64_t size;
1657 char s1[64];
1659 size = bdrv_getlength(bs);
1660 if (size < 0) {
1661 printf("getlength: %s\n", strerror(-size));
1662 return 0;
1665 cvtstr(size, s1, sizeof(s1));
1666 printf("%s\n", s1);
1667 return 0;
1671 static const cmdinfo_t length_cmd = {
1672 .name = "length",
1673 .altname = "l",
1674 .cfunc = length_f,
1675 .oneline = "gets the length of the current file",
1679 static int info_f(BlockDriverState *bs, int argc, char **argv)
1681 BlockDriverInfo bdi;
1682 ImageInfoSpecific *spec_info;
1683 char s1[64], s2[64];
1684 int ret;
1686 if (bs->drv && bs->drv->format_name) {
1687 printf("format name: %s\n", bs->drv->format_name);
1689 if (bs->drv && bs->drv->protocol_name) {
1690 printf("format name: %s\n", bs->drv->protocol_name);
1693 ret = bdrv_get_info(bs, &bdi);
1694 if (ret) {
1695 return 0;
1698 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1699 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1701 printf("cluster size: %s\n", s1);
1702 printf("vm state offset: %s\n", s2);
1704 spec_info = bdrv_get_specific_info(bs);
1705 if (spec_info) {
1706 printf("Format specific information:\n");
1707 bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
1708 qapi_free_ImageInfoSpecific(spec_info);
1711 return 0;
1716 static const cmdinfo_t info_cmd = {
1717 .name = "info",
1718 .altname = "i",
1719 .cfunc = info_f,
1720 .oneline = "prints information about the current file",
1723 static void discard_help(void)
1725 printf(
1726 "\n"
1727 " discards a range of bytes from the given offset\n"
1728 "\n"
1729 " Example:\n"
1730 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1731 "\n"
1732 " Discards a segment of the currently open file.\n"
1733 " -C, -- report statistics in a machine parsable format\n"
1734 " -q, -- quiet mode, do not show I/O statistics\n"
1735 "\n");
1738 static int discard_f(BlockDriverState *bs, int argc, char **argv);
1740 static const cmdinfo_t discard_cmd = {
1741 .name = "discard",
1742 .altname = "d",
1743 .cfunc = discard_f,
1744 .argmin = 2,
1745 .argmax = -1,
1746 .args = "[-Cq] off len",
1747 .oneline = "discards a number of bytes at a specified offset",
1748 .help = discard_help,
1751 static int discard_f(BlockDriverState *bs, int argc, char **argv)
1753 struct timeval t1, t2;
1754 int Cflag = 0, qflag = 0;
1755 int c, ret;
1756 int64_t offset;
1757 int count;
1759 while ((c = getopt(argc, argv, "Cq")) != EOF) {
1760 switch (c) {
1761 case 'C':
1762 Cflag = 1;
1763 break;
1764 case 'q':
1765 qflag = 1;
1766 break;
1767 default:
1768 return qemuio_command_usage(&discard_cmd);
1772 if (optind != argc - 2) {
1773 return qemuio_command_usage(&discard_cmd);
1776 offset = cvtnum(argv[optind]);
1777 if (offset < 0) {
1778 printf("non-numeric length argument -- %s\n", argv[optind]);
1779 return 0;
1782 optind++;
1783 count = cvtnum(argv[optind]);
1784 if (count < 0) {
1785 printf("non-numeric length argument -- %s\n", argv[optind]);
1786 return 0;
1789 gettimeofday(&t1, NULL);
1790 ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1791 count >> BDRV_SECTOR_BITS);
1792 gettimeofday(&t2, NULL);
1794 if (ret < 0) {
1795 printf("discard failed: %s\n", strerror(-ret));
1796 goto out;
1799 /* Finally, report back -- -C gives a parsable format */
1800 if (!qflag) {
1801 t2 = tsub(t2, t1);
1802 print_report("discard", &t2, offset, count, count, 1, Cflag);
1805 out:
1806 return 0;
1809 static int alloc_f(BlockDriverState *bs, int argc, char **argv)
1811 int64_t offset, sector_num;
1812 int nb_sectors, remaining;
1813 char s1[64];
1814 int num, sum_alloc;
1815 int ret;
1817 offset = cvtnum(argv[1]);
1818 if (offset < 0) {
1819 printf("non-numeric offset argument -- %s\n", argv[1]);
1820 return 0;
1821 } else if (offset & 0x1ff) {
1822 printf("offset %" PRId64 " is not sector aligned\n",
1823 offset);
1824 return 0;
1827 if (argc == 3) {
1828 nb_sectors = cvtnum(argv[2]);
1829 if (nb_sectors < 0) {
1830 printf("non-numeric length argument -- %s\n", argv[2]);
1831 return 0;
1833 } else {
1834 nb_sectors = 1;
1837 remaining = nb_sectors;
1838 sum_alloc = 0;
1839 sector_num = offset >> 9;
1840 while (remaining) {
1841 ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1842 if (ret < 0) {
1843 printf("is_allocated failed: %s\n", strerror(-ret));
1844 return 0;
1846 sector_num += num;
1847 remaining -= num;
1848 if (ret) {
1849 sum_alloc += num;
1851 if (num == 0) {
1852 nb_sectors -= remaining;
1853 remaining = 0;
1857 cvtstr(offset, s1, sizeof(s1));
1859 printf("%d/%d sectors allocated at offset %s\n",
1860 sum_alloc, nb_sectors, s1);
1861 return 0;
1864 static const cmdinfo_t alloc_cmd = {
1865 .name = "alloc",
1866 .altname = "a",
1867 .argmin = 1,
1868 .argmax = 2,
1869 .cfunc = alloc_f,
1870 .args = "off [sectors]",
1871 .oneline = "checks if a sector is present in the file",
1875 static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
1876 int64_t nb_sectors, int64_t *pnum)
1878 int num, num_checked;
1879 int ret, firstret;
1881 num_checked = MIN(nb_sectors, INT_MAX);
1882 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1883 if (ret < 0) {
1884 return ret;
1887 firstret = ret;
1888 *pnum = num;
1890 while (nb_sectors > 0 && ret == firstret) {
1891 sector_num += num;
1892 nb_sectors -= num;
1894 num_checked = MIN(nb_sectors, INT_MAX);
1895 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1896 if (ret == firstret) {
1897 *pnum += num;
1898 } else {
1899 break;
1903 return firstret;
1906 static int map_f(BlockDriverState *bs, int argc, char **argv)
1908 int64_t offset;
1909 int64_t nb_sectors;
1910 char s1[64];
1911 int64_t num;
1912 int ret;
1913 const char *retstr;
1915 offset = 0;
1916 nb_sectors = bs->total_sectors;
1918 do {
1919 ret = map_is_allocated(bs, offset, nb_sectors, &num);
1920 if (ret < 0) {
1921 error_report("Failed to get allocation status: %s", strerror(-ret));
1922 return 0;
1925 retstr = ret ? " allocated" : "not allocated";
1926 cvtstr(offset << 9ULL, s1, sizeof(s1));
1927 printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
1928 "at offset %s (%d)\n",
1929 offset << 9ULL, num, nb_sectors, retstr, s1, ret);
1931 offset += num;
1932 nb_sectors -= num;
1933 } while (offset < bs->total_sectors);
1935 return 0;
1938 static const cmdinfo_t map_cmd = {
1939 .name = "map",
1940 .argmin = 0,
1941 .argmax = 0,
1942 .cfunc = map_f,
1943 .args = "",
1944 .oneline = "prints the allocated areas of a file",
1947 static int break_f(BlockDriverState *bs, int argc, char **argv)
1949 int ret;
1951 ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1952 if (ret < 0) {
1953 printf("Could not set breakpoint: %s\n", strerror(-ret));
1956 return 0;
1959 static int remove_break_f(BlockDriverState *bs, int argc, char **argv)
1961 int ret;
1963 ret = bdrv_debug_remove_breakpoint(bs, argv[1]);
1964 if (ret < 0) {
1965 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
1968 return 0;
1971 static const cmdinfo_t break_cmd = {
1972 .name = "break",
1973 .argmin = 2,
1974 .argmax = 2,
1975 .cfunc = break_f,
1976 .args = "event tag",
1977 .oneline = "sets a breakpoint on event and tags the stopped "
1978 "request as tag",
1981 static const cmdinfo_t remove_break_cmd = {
1982 .name = "remove_break",
1983 .argmin = 1,
1984 .argmax = 1,
1985 .cfunc = remove_break_f,
1986 .args = "tag",
1987 .oneline = "remove a breakpoint by tag",
1990 static int resume_f(BlockDriverState *bs, int argc, char **argv)
1992 int ret;
1994 ret = bdrv_debug_resume(bs, argv[1]);
1995 if (ret < 0) {
1996 printf("Could not resume request: %s\n", strerror(-ret));
1999 return 0;
2002 static const cmdinfo_t resume_cmd = {
2003 .name = "resume",
2004 .argmin = 1,
2005 .argmax = 1,
2006 .cfunc = resume_f,
2007 .args = "tag",
2008 .oneline = "resumes the request tagged as tag",
2011 static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
2013 while (!bdrv_debug_is_suspended(bs, argv[1])) {
2014 qemu_aio_wait();
2017 return 0;
2020 static const cmdinfo_t wait_break_cmd = {
2021 .name = "wait_break",
2022 .argmin = 1,
2023 .argmax = 1,
2024 .cfunc = wait_break_f,
2025 .args = "tag",
2026 .oneline = "waits for the suspension of a request",
2029 static int abort_f(BlockDriverState *bs, int argc, char **argv)
2031 abort();
2034 static const cmdinfo_t abort_cmd = {
2035 .name = "abort",
2036 .cfunc = abort_f,
2037 .flags = CMD_NOFILE_OK,
2038 .oneline = "simulate a program crash using abort(3)",
2041 static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2043 if (cmd) {
2044 printf("%s ", cmd);
2045 } else {
2046 printf("%s ", ct->name);
2047 if (ct->altname) {
2048 printf("(or %s) ", ct->altname);
2052 if (ct->args) {
2053 printf("%s ", ct->args);
2055 printf("-- %s\n", ct->oneline);
2058 static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2060 help_oneline(cmd, ct);
2061 if (ct->help) {
2062 ct->help();
2066 static void help_all(void)
2068 const cmdinfo_t *ct;
2070 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2071 help_oneline(ct->name, ct);
2073 printf("\nUse 'help commandname' for extended help.\n");
2076 static int help_f(BlockDriverState *bs, int argc, char **argv)
2078 const cmdinfo_t *ct;
2080 if (argc == 1) {
2081 help_all();
2082 return 0;
2085 ct = find_command(argv[1]);
2086 if (ct == NULL) {
2087 printf("command %s not found\n", argv[1]);
2088 return 0;
2091 help_onecmd(argv[1], ct);
2092 return 0;
2095 static const cmdinfo_t help_cmd = {
2096 .name = "help",
2097 .altname = "?",
2098 .cfunc = help_f,
2099 .argmin = 0,
2100 .argmax = 1,
2101 .flags = CMD_FLAG_GLOBAL,
2102 .args = "[command]",
2103 .oneline = "help for one or all commands",
2106 bool qemuio_command(BlockDriverState *bs, const char *cmd)
2108 char *input;
2109 const cmdinfo_t *ct;
2110 char **v;
2111 int c;
2112 bool done = false;
2114 input = g_strdup(cmd);
2115 v = breakline(input, &c);
2116 if (c) {
2117 ct = find_command(v[0]);
2118 if (ct) {
2119 done = command(bs, ct, c, v);
2120 } else {
2121 fprintf(stderr, "command \"%s\" not found\n", v[0]);
2124 g_free(input);
2125 g_free(v);
2127 return done;
2130 static void __attribute((constructor)) init_qemuio_commands(void)
2132 /* initialize commands */
2133 qemuio_add_command(&help_cmd);
2134 qemuio_add_command(&read_cmd);
2135 qemuio_add_command(&readv_cmd);
2136 qemuio_add_command(&write_cmd);
2137 qemuio_add_command(&writev_cmd);
2138 qemuio_add_command(&multiwrite_cmd);
2139 qemuio_add_command(&aio_read_cmd);
2140 qemuio_add_command(&aio_write_cmd);
2141 qemuio_add_command(&aio_flush_cmd);
2142 qemuio_add_command(&flush_cmd);
2143 qemuio_add_command(&truncate_cmd);
2144 qemuio_add_command(&length_cmd);
2145 qemuio_add_command(&info_cmd);
2146 qemuio_add_command(&discard_cmd);
2147 qemuio_add_command(&alloc_cmd);
2148 qemuio_add_command(&map_cmd);
2149 qemuio_add_command(&break_cmd);
2150 qemuio_add_command(&remove_break_cmd);
2151 qemuio_add_command(&resume_cmd);
2152 qemuio_add_command(&wait_break_cmd);
2153 qemuio_add_command(&abort_cmd);