]> git.proxmox.com Git - mirror_qemu.git/blame - qemu-io-cmds.c
blkdebug: Make required alignment configurable
[mirror_qemu.git] / qemu-io-cmds.c
CommitLineData
797ac58c
KW
1/*
2 * Command line utility to exercise the QEMU I/O path.
3 *
4 * Copyright (C) 2009 Red Hat, Inc.
5 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
9 */
10
3d21994f 11#include "qemu-io.h"
797ac58c 12#include "block/block_int.h"
a8d8ecb7 13#include "block/qapi.h"
6a1751b7 14#include "qemu/main-loop.h"
797ac58c
KW
15
16#define CMD_NOFILE_OK 0x01
17
18int qemuio_misalign;
19
c2cdf5c5
KW
20static cmdinfo_t *cmdtab;
21static int ncmds;
22
23static int compare_cmdname(const void *a, const void *b)
24{
25 return strcmp(((const cmdinfo_t *)a)->name,
26 ((const cmdinfo_t *)b)->name);
27}
28
29void qemuio_add_command(const cmdinfo_t *ci)
30{
31 cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
32 cmdtab[ncmds - 1] = *ci;
33 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
34}
35
36int qemuio_command_usage(const cmdinfo_t *ci)
37{
38 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
39 return 0;
40}
41
42static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
43{
44 if (ct->flags & CMD_FLAG_GLOBAL) {
45 return 1;
46 }
47 if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
48 fprintf(stderr, "no file open, try 'help open'\n");
49 return 0;
50 }
51 return 1;
52}
53
3d21994f
KW
54static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc,
55 char **argv)
c2cdf5c5
KW
56{
57 char *cmd = argv[0];
58
3d21994f 59 if (!init_check_command(bs, ct)) {
c2cdf5c5
KW
60 return 0;
61 }
62
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);
76 }
77 return 0;
78 }
79 optind = 0;
3d21994f 80 return ct->cfunc(bs, argc, argv);
c2cdf5c5
KW
81}
82
83static const cmdinfo_t *find_command(const char *cmd)
84{
85 cmdinfo_t *ct;
86
87 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
88 if (strcmp(ct->name, cmd) == 0 ||
89 (ct->altname && strcmp(ct->altname, cmd) == 0))
90 {
91 return (const cmdinfo_t *)ct;
92 }
93 }
94 return NULL;
95}
96
4694020d
SH
97/* Invoke fn() for commands with a matching prefix */
98void qemuio_complete_command(const char *input,
99 void (*fn)(const char *cmd, void *opaque),
100 void *opaque)
101{
102 cmdinfo_t *ct;
103 size_t input_len = strlen(input);
104
105 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
106 if (strncmp(input, ct->name, input_len) == 0) {
107 fn(ct->name, opaque);
108 }
109 }
110}
111
c2cdf5c5
KW
112static char **breakline(char *input, int *count)
113{
114 int c = 0;
115 char *p;
116 char **rval = g_malloc0(sizeof(char *));
117 char **tmp;
118
119 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
120 if (!*p) {
121 continue;
122 }
123 c++;
124 tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
125 if (!tmp) {
126 g_free(rval);
127 rval = NULL;
128 c = 0;
129 break;
130 } else {
131 rval = tmp;
132 }
133 rval[c - 1] = p;
134 rval[c] = NULL;
135 }
136 *count = c;
137 return rval;
138}
139
797ac58c
KW
140static int64_t cvtnum(const char *s)
141{
142 char *end;
143 return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
144}
145
0b613881
KW
146#define EXABYTES(x) ((long long)(x) << 60)
147#define PETABYTES(x) ((long long)(x) << 50)
148#define TERABYTES(x) ((long long)(x) << 40)
149#define GIGABYTES(x) ((long long)(x) << 30)
150#define MEGABYTES(x) ((long long)(x) << 20)
151#define KILOBYTES(x) ((long long)(x) << 10)
152
153#define TO_EXABYTES(x) ((x) / EXABYTES(1))
154#define TO_PETABYTES(x) ((x) / PETABYTES(1))
155#define TO_TERABYTES(x) ((x) / TERABYTES(1))
156#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
157#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
158#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
159
160static void cvtstr(double value, char *str, size_t size)
161{
162 char *trim;
163 const char *suffix;
164
165 if (value >= EXABYTES(1)) {
166 suffix = " EiB";
167 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
168 } else if (value >= PETABYTES(1)) {
169 suffix = " PiB";
170 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
171 } else if (value >= TERABYTES(1)) {
172 suffix = " TiB";
173 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
174 } else if (value >= GIGABYTES(1)) {
175 suffix = " GiB";
176 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
177 } else if (value >= MEGABYTES(1)) {
178 suffix = " MiB";
179 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
180 } else if (value >= KILOBYTES(1)) {
181 suffix = " KiB";
182 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
183 } else {
184 suffix = " bytes";
185 snprintf(str, size - 6, "%f", value);
186 }
187
188 trim = strstr(str, ".000");
189 if (trim) {
190 strcpy(trim, suffix);
191 } else {
192 strcat(str, suffix);
193 }
194}
195
196
197
198static struct timeval tsub(struct timeval t1, struct timeval t2)
199{
200 t1.tv_usec -= t2.tv_usec;
201 if (t1.tv_usec < 0) {
202 t1.tv_usec += 1000000;
203 t1.tv_sec--;
204 }
205 t1.tv_sec -= t2.tv_sec;
206 return t1;
207}
208
209static double tdiv(double value, struct timeval tv)
210{
211 return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
212}
213
214#define HOURS(sec) ((sec) / (60 * 60))
215#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
216#define SECONDS(sec) ((sec) % 60)
217
218enum {
219 DEFAULT_TIME = 0x0,
220 TERSE_FIXED_TIME = 0x1,
221 VERBOSE_FIXED_TIME = 0x2,
222};
223
224static void timestr(struct timeval *tv, char *ts, size_t size, int format)
225{
226 double usec = (double)tv->tv_usec / 1000000.0;
227
228 if (format & TERSE_FIXED_TIME) {
229 if (!HOURS(tv->tv_sec)) {
230 snprintf(ts, size, "%u:%02u.%02u",
231 (unsigned int) MINUTES(tv->tv_sec),
232 (unsigned int) SECONDS(tv->tv_sec),
233 (unsigned int) (usec * 100));
234 return;
235 }
236 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
237 }
238
239 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
240 snprintf(ts, size, "%u:%02u:%02u.%02u",
241 (unsigned int) HOURS(tv->tv_sec),
242 (unsigned int) MINUTES(tv->tv_sec),
243 (unsigned int) SECONDS(tv->tv_sec),
244 (unsigned int) (usec * 100));
245 } else {
246 snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
247 }
248}
249
797ac58c
KW
250/*
251 * Parse the pattern argument to various sub-commands.
252 *
253 * Because the pattern is used as an argument to memset it must evaluate
254 * to an unsigned integer that fits into a single byte.
255 */
256static int parse_pattern(const char *arg)
257{
258 char *endptr = NULL;
259 long pattern;
260
261 pattern = strtol(arg, &endptr, 0);
262 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
263 printf("%s is not a valid pattern byte\n", arg);
264 return -1;
265 }
266
267 return pattern;
268}
269
270/*
271 * Memory allocation helpers.
272 *
273 * Make sure memory is aligned by default, or purposefully misaligned if
274 * that is specified on the command line.
275 */
276
277#define MISALIGN_OFFSET 16
278static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
279{
280 void *buf;
281
282 if (qemuio_misalign) {
283 len += MISALIGN_OFFSET;
284 }
285 buf = qemu_blockalign(bs, len);
286 memset(buf, pattern, len);
287 if (qemuio_misalign) {
288 buf += MISALIGN_OFFSET;
289 }
290 return buf;
291}
292
293static void qemu_io_free(void *p)
294{
295 if (qemuio_misalign) {
296 p -= MISALIGN_OFFSET;
297 }
298 qemu_vfree(p);
299}
300
301static void dump_buffer(const void *buffer, int64_t offset, int len)
302{
303 int i, j;
304 const uint8_t *p;
305
306 for (i = 0, p = buffer; i < len; i += 16) {
307 const uint8_t *s = p;
308
309 printf("%08" PRIx64 ": ", offset + i);
310 for (j = 0; j < 16 && i + j < len; j++, p++) {
311 printf("%02x ", *p);
312 }
313 printf(" ");
314 for (j = 0; j < 16 && i + j < len; j++, s++) {
315 if (isalnum(*s)) {
316 printf("%c", *s);
317 } else {
318 printf(".");
319 }
320 }
321 printf("\n");
322 }
323}
324
325static void print_report(const char *op, struct timeval *t, int64_t offset,
326 int count, int total, int cnt, int Cflag)
327{
328 char s1[64], s2[64], ts[64];
329
330 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
331 if (!Cflag) {
332 cvtstr((double)total, s1, sizeof(s1));
333 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
334 printf("%s %d/%d bytes at offset %" PRId64 "\n",
335 op, total, count, offset);
336 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
337 s1, cnt, ts, s2, tdiv((double)cnt, *t));
338 } else {/* bytes,ops,time,bytes/sec,ops/sec */
339 printf("%d,%d,%s,%.3f,%.3f\n",
340 total, cnt, ts,
341 tdiv((double)total, *t),
342 tdiv((double)cnt, *t));
343 }
344}
345
346/*
347 * Parse multiple length statements for vectored I/O, and construct an I/O
348 * vector matching it.
349 */
350static void *
351create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
352 int pattern)
353{
354 size_t *sizes = g_new0(size_t, nr_iov);
355 size_t count = 0;
356 void *buf = NULL;
357 void *p;
358 int i;
359
360 for (i = 0; i < nr_iov; i++) {
361 char *arg = argv[i];
362 int64_t len;
363
364 len = cvtnum(arg);
365 if (len < 0) {
366 printf("non-numeric length argument -- %s\n", arg);
367 goto fail;
368 }
369
370 /* should be SIZE_T_MAX, but that doesn't exist */
371 if (len > INT_MAX) {
372 printf("too large length argument -- %s\n", arg);
373 goto fail;
374 }
375
376 if (len & 0x1ff) {
377 printf("length argument %" PRId64
378 " is not sector aligned\n", len);
379 goto fail;
380 }
381
382 sizes[i] = len;
383 count += len;
384 }
385
386 qemu_iovec_init(qiov, nr_iov);
387
388 buf = p = qemu_io_alloc(bs, count, pattern);
389
390 for (i = 0; i < nr_iov; i++) {
391 qemu_iovec_add(qiov, p, sizes[i]);
392 p += sizes[i];
393 }
394
395fail:
396 g_free(sizes);
397 return buf;
398}
399
400static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
401 int *total)
402{
403 int ret;
404
405 ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
406 if (ret < 0) {
407 return ret;
408 }
409 *total = count;
410 return 1;
411}
412
413static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
414 int *total)
415{
416 int ret;
417
418 ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
419 if (ret < 0) {
420 return ret;
421 }
422 *total = count;
423 return 1;
424}
425
426static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
427 int *total)
428{
429 *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
430 if (*total < 0) {
431 return *total;
432 }
433 return 1;
434}
435
436static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
437 int *total)
438{
439 *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
440 if (*total < 0) {
441 return *total;
442 }
443 return 1;
444}
445
446typedef struct {
447 BlockDriverState *bs;
448 int64_t offset;
449 int count;
450 int *total;
451 int ret;
452 bool done;
453} CoWriteZeroes;
454
455static void coroutine_fn co_write_zeroes_entry(void *opaque)
456{
457 CoWriteZeroes *data = opaque;
458
459 data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
aa7bfbff 460 data->count / BDRV_SECTOR_SIZE, 0);
797ac58c
KW
461 data->done = true;
462 if (data->ret < 0) {
463 *data->total = data->ret;
464 return;
465 }
466
467 *data->total = data->count;
468}
469
470static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
471 int *total)
472{
473 Coroutine *co;
474 CoWriteZeroes data = {
475 .bs = bs,
476 .offset = offset,
477 .count = count,
478 .total = total,
479 .done = false,
480 };
481
482 co = qemu_coroutine_create(co_write_zeroes_entry);
483 qemu_coroutine_enter(co, &data);
484 while (!data.done) {
485 qemu_aio_wait();
486 }
487 if (data.ret < 0) {
488 return data.ret;
489 } else {
490 return 1;
491 }
492}
493
494static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
495 int count, int *total)
496{
497 int ret;
498
499 ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
500 if (ret < 0) {
501 return ret;
502 }
503 *total = count;
504 return 1;
505}
506
507static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
508 int count, int *total)
509{
510 *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
511 if (*total < 0) {
512 return *total;
513 }
514 return 1;
515}
516
517static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
518 int count, int *total)
519{
520 *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
521 if (*total < 0) {
522 return *total;
523 }
524 return 1;
525}
526
527#define NOT_DONE 0x7fffffff
528static void aio_rw_done(void *opaque, int ret)
529{
530 *(int *)opaque = ret;
531}
532
533static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
534 int64_t offset, int *total)
535{
536 int async_ret = NOT_DONE;
537
538 bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
539 aio_rw_done, &async_ret);
540 while (async_ret == NOT_DONE) {
541 main_loop_wait(false);
542 }
543
544 *total = qiov->size;
545 return async_ret < 0 ? async_ret : 1;
546}
547
548static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
549 int64_t offset, int *total)
550{
551 int async_ret = NOT_DONE;
552
553 bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
554 aio_rw_done, &async_ret);
555 while (async_ret == NOT_DONE) {
556 main_loop_wait(false);
557 }
558
559 *total = qiov->size;
560 return async_ret < 0 ? async_ret : 1;
561}
562
563struct multiwrite_async_ret {
564 int num_done;
565 int error;
566};
567
568static void multiwrite_cb(void *opaque, int ret)
569{
570 struct multiwrite_async_ret *async_ret = opaque;
571
572 async_ret->num_done++;
573 if (ret < 0) {
574 async_ret->error = ret;
575 }
576}
577
578static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
579 int num_reqs, int *total)
580{
581 int i, ret;
582 struct multiwrite_async_ret async_ret = {
583 .num_done = 0,
584 .error = 0,
585 };
586
587 *total = 0;
588 for (i = 0; i < num_reqs; i++) {
589 reqs[i].cb = multiwrite_cb;
590 reqs[i].opaque = &async_ret;
591 *total += reqs[i].qiov->size;
592 }
593
594 ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
595 if (ret < 0) {
596 return ret;
597 }
598
599 while (async_ret.num_done < num_reqs) {
600 main_loop_wait(false);
601 }
602
603 return async_ret.error < 0 ? async_ret.error : 1;
604}
605
606static void read_help(void)
607{
608 printf(
609"\n"
610" reads a range of bytes from the given offset\n"
611"\n"
612" Example:\n"
613" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
614"\n"
615" Reads a segment of the currently open file, optionally dumping it to the\n"
616" standard output stream (with -v option) for subsequent inspection.\n"
617" -b, -- read from the VM state rather than the virtual disk\n"
618" -C, -- report statistics in a machine parsable format\n"
619" -l, -- length for pattern verification (only with -P)\n"
620" -p, -- use bdrv_pread to read the file\n"
621" -P, -- use a pattern to verify read data\n"
622" -q, -- quiet mode, do not show I/O statistics\n"
623" -s, -- start offset for pattern verification (only with -P)\n"
624" -v, -- dump buffer to standard output\n"
625"\n");
626}
627
628static int read_f(BlockDriverState *bs, int argc, char **argv);
629
630static const cmdinfo_t read_cmd = {
631 .name = "read",
632 .altname = "r",
633 .cfunc = read_f,
634 .argmin = 2,
635 .argmax = -1,
636 .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
637 .oneline = "reads a number of bytes at a specified offset",
638 .help = read_help,
639};
640
641static int read_f(BlockDriverState *bs, int argc, char **argv)
642{
643 struct timeval t1, t2;
644 int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
645 int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
646 int c, cnt;
647 char *buf;
648 int64_t offset;
649 int count;
650 /* Some compilers get confused and warn if this is not initialized. */
651 int total = 0;
652 int pattern = 0, pattern_offset = 0, pattern_count = 0;
653
654 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
655 switch (c) {
656 case 'b':
657 bflag = 1;
658 break;
659 case 'C':
660 Cflag = 1;
661 break;
662 case 'l':
663 lflag = 1;
664 pattern_count = cvtnum(optarg);
665 if (pattern_count < 0) {
666 printf("non-numeric length argument -- %s\n", optarg);
667 return 0;
668 }
669 break;
670 case 'p':
671 pflag = 1;
672 break;
673 case 'P':
674 Pflag = 1;
675 pattern = parse_pattern(optarg);
676 if (pattern < 0) {
677 return 0;
678 }
679 break;
680 case 'q':
681 qflag = 1;
682 break;
683 case 's':
684 sflag = 1;
685 pattern_offset = cvtnum(optarg);
686 if (pattern_offset < 0) {
687 printf("non-numeric length argument -- %s\n", optarg);
688 return 0;
689 }
690 break;
691 case 'v':
692 vflag = 1;
693 break;
694 default:
c2cdf5c5 695 return qemuio_command_usage(&read_cmd);
797ac58c
KW
696 }
697 }
698
699 if (optind != argc - 2) {
c2cdf5c5 700 return qemuio_command_usage(&read_cmd);
797ac58c
KW
701 }
702
703 if (bflag && pflag) {
704 printf("-b and -p cannot be specified at the same time\n");
705 return 0;
706 }
707
708 offset = cvtnum(argv[optind]);
709 if (offset < 0) {
710 printf("non-numeric length argument -- %s\n", argv[optind]);
711 return 0;
712 }
713
714 optind++;
715 count = cvtnum(argv[optind]);
716 if (count < 0) {
717 printf("non-numeric length argument -- %s\n", argv[optind]);
718 return 0;
719 }
720
721 if (!Pflag && (lflag || sflag)) {
c2cdf5c5 722 return qemuio_command_usage(&read_cmd);
797ac58c
KW
723 }
724
725 if (!lflag) {
726 pattern_count = count - pattern_offset;
727 }
728
729 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
730 printf("pattern verification range exceeds end of read data\n");
731 return 0;
732 }
733
734 if (!pflag) {
735 if (offset & 0x1ff) {
736 printf("offset %" PRId64 " is not sector aligned\n",
737 offset);
738 return 0;
739 }
740 if (count & 0x1ff) {
741 printf("count %d is not sector aligned\n",
742 count);
743 return 0;
744 }
745 }
746
747 buf = qemu_io_alloc(bs, count, 0xab);
748
749 gettimeofday(&t1, NULL);
750 if (pflag) {
751 cnt = do_pread(bs, buf, offset, count, &total);
752 } else if (bflag) {
753 cnt = do_load_vmstate(bs, buf, offset, count, &total);
754 } else {
755 cnt = do_read(bs, buf, offset, count, &total);
756 }
757 gettimeofday(&t2, NULL);
758
759 if (cnt < 0) {
760 printf("read failed: %s\n", strerror(-cnt));
761 goto out;
762 }
763
764 if (Pflag) {
765 void *cmp_buf = g_malloc(pattern_count);
766 memset(cmp_buf, pattern, pattern_count);
767 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
768 printf("Pattern verification failed at offset %"
769 PRId64 ", %d bytes\n",
770 offset + pattern_offset, pattern_count);
771 }
772 g_free(cmp_buf);
773 }
774
775 if (qflag) {
776 goto out;
777 }
778
779 if (vflag) {
780 dump_buffer(buf, offset, count);
781 }
782
783 /* Finally, report back -- -C gives a parsable format */
784 t2 = tsub(t2, t1);
785 print_report("read", &t2, offset, count, total, cnt, Cflag);
786
787out:
788 qemu_io_free(buf);
789
790 return 0;
791}
792
793static void readv_help(void)
794{
795 printf(
796"\n"
797" reads a range of bytes from the given offset into multiple buffers\n"
798"\n"
799" Example:\n"
800" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
801"\n"
802" Reads a segment of the currently open file, optionally dumping it to the\n"
803" standard output stream (with -v option) for subsequent inspection.\n"
804" Uses multiple iovec buffers if more than one byte range is specified.\n"
805" -C, -- report statistics in a machine parsable format\n"
806" -P, -- use a pattern to verify read data\n"
807" -v, -- dump buffer to standard output\n"
808" -q, -- quiet mode, do not show I/O statistics\n"
809"\n");
810}
811
812static int readv_f(BlockDriverState *bs, int argc, char **argv);
813
814static const cmdinfo_t readv_cmd = {
815 .name = "readv",
816 .cfunc = readv_f,
817 .argmin = 2,
818 .argmax = -1,
819 .args = "[-Cqv] [-P pattern ] off len [len..]",
820 .oneline = "reads a number of bytes at a specified offset",
821 .help = readv_help,
822};
823
824static int readv_f(BlockDriverState *bs, int argc, char **argv)
825{
826 struct timeval t1, t2;
827 int Cflag = 0, qflag = 0, vflag = 0;
828 int c, cnt;
829 char *buf;
830 int64_t offset;
831 /* Some compilers get confused and warn if this is not initialized. */
832 int total = 0;
833 int nr_iov;
834 QEMUIOVector qiov;
835 int pattern = 0;
836 int Pflag = 0;
837
838 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
839 switch (c) {
840 case 'C':
841 Cflag = 1;
842 break;
843 case 'P':
844 Pflag = 1;
845 pattern = parse_pattern(optarg);
846 if (pattern < 0) {
847 return 0;
848 }
849 break;
850 case 'q':
851 qflag = 1;
852 break;
853 case 'v':
854 vflag = 1;
855 break;
856 default:
c2cdf5c5 857 return qemuio_command_usage(&readv_cmd);
797ac58c
KW
858 }
859 }
860
861 if (optind > argc - 2) {
c2cdf5c5 862 return qemuio_command_usage(&readv_cmd);
797ac58c
KW
863 }
864
865
866 offset = cvtnum(argv[optind]);
867 if (offset < 0) {
868 printf("non-numeric length argument -- %s\n", argv[optind]);
869 return 0;
870 }
871 optind++;
872
873 if (offset & 0x1ff) {
874 printf("offset %" PRId64 " is not sector aligned\n",
875 offset);
876 return 0;
877 }
878
879 nr_iov = argc - optind;
880 buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
881 if (buf == NULL) {
882 return 0;
883 }
884
885 gettimeofday(&t1, NULL);
886 cnt = do_aio_readv(bs, &qiov, offset, &total);
887 gettimeofday(&t2, NULL);
888
889 if (cnt < 0) {
890 printf("readv failed: %s\n", strerror(-cnt));
891 goto out;
892 }
893
894 if (Pflag) {
895 void *cmp_buf = g_malloc(qiov.size);
896 memset(cmp_buf, pattern, qiov.size);
897 if (memcmp(buf, cmp_buf, qiov.size)) {
898 printf("Pattern verification failed at offset %"
899 PRId64 ", %zd bytes\n", offset, qiov.size);
900 }
901 g_free(cmp_buf);
902 }
903
904 if (qflag) {
905 goto out;
906 }
907
908 if (vflag) {
909 dump_buffer(buf, offset, qiov.size);
910 }
911
912 /* Finally, report back -- -C gives a parsable format */
913 t2 = tsub(t2, t1);
914 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
915
916out:
917 qemu_iovec_destroy(&qiov);
918 qemu_io_free(buf);
919 return 0;
920}
921
922static void write_help(void)
923{
924 printf(
925"\n"
926" writes a range of bytes from the given offset\n"
927"\n"
928" Example:\n"
929" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
930"\n"
931" Writes into a segment of the currently open file, using a buffer\n"
932" filled with a set pattern (0xcdcdcdcd).\n"
933" -b, -- write to the VM state rather than the virtual disk\n"
934" -c, -- write compressed data with bdrv_write_compressed\n"
935" -p, -- use bdrv_pwrite to write the file\n"
936" -P, -- use different pattern to fill file\n"
937" -C, -- report statistics in a machine parsable format\n"
938" -q, -- quiet mode, do not show I/O statistics\n"
939" -z, -- write zeroes using bdrv_co_write_zeroes\n"
940"\n");
941}
942
943static int write_f(BlockDriverState *bs, int argc, char **argv);
944
945static const cmdinfo_t write_cmd = {
946 .name = "write",
947 .altname = "w",
948 .cfunc = write_f,
949 .argmin = 2,
950 .argmax = -1,
951 .args = "[-bcCpqz] [-P pattern ] off len",
952 .oneline = "writes a number of bytes at a specified offset",
953 .help = write_help,
954};
955
956static int write_f(BlockDriverState *bs, int argc, char **argv)
957{
958 struct timeval t1, t2;
959 int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
960 int cflag = 0;
961 int c, cnt;
962 char *buf = NULL;
963 int64_t offset;
964 int count;
965 /* Some compilers get confused and warn if this is not initialized. */
966 int total = 0;
967 int pattern = 0xcd;
968
969 while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
970 switch (c) {
971 case 'b':
972 bflag = 1;
973 break;
974 case 'c':
975 cflag = 1;
976 break;
977 case 'C':
978 Cflag = 1;
979 break;
980 case 'p':
981 pflag = 1;
982 break;
983 case 'P':
984 Pflag = 1;
985 pattern = parse_pattern(optarg);
986 if (pattern < 0) {
987 return 0;
988 }
989 break;
990 case 'q':
991 qflag = 1;
992 break;
993 case 'z':
994 zflag = 1;
995 break;
996 default:
c2cdf5c5 997 return qemuio_command_usage(&write_cmd);
797ac58c
KW
998 }
999 }
1000
1001 if (optind != argc - 2) {
c2cdf5c5 1002 return qemuio_command_usage(&write_cmd);
797ac58c
KW
1003 }
1004
1005 if (bflag + pflag + zflag > 1) {
1006 printf("-b, -p, or -z cannot be specified at the same time\n");
1007 return 0;
1008 }
1009
1010 if (zflag && Pflag) {
1011 printf("-z and -P cannot be specified at the same time\n");
1012 return 0;
1013 }
1014
1015 offset = cvtnum(argv[optind]);
1016 if (offset < 0) {
1017 printf("non-numeric length argument -- %s\n", argv[optind]);
1018 return 0;
1019 }
1020
1021 optind++;
1022 count = cvtnum(argv[optind]);
1023 if (count < 0) {
1024 printf("non-numeric length argument -- %s\n", argv[optind]);
1025 return 0;
1026 }
1027
1028 if (!pflag) {
1029 if (offset & 0x1ff) {
1030 printf("offset %" PRId64 " is not sector aligned\n",
1031 offset);
1032 return 0;
1033 }
1034
1035 if (count & 0x1ff) {
1036 printf("count %d is not sector aligned\n",
1037 count);
1038 return 0;
1039 }
1040 }
1041
1042 if (!zflag) {
1043 buf = qemu_io_alloc(bs, count, pattern);
1044 }
1045
1046 gettimeofday(&t1, NULL);
1047 if (pflag) {
1048 cnt = do_pwrite(bs, buf, offset, count, &total);
1049 } else if (bflag) {
1050 cnt = do_save_vmstate(bs, buf, offset, count, &total);
1051 } else if (zflag) {
1052 cnt = do_co_write_zeroes(bs, offset, count, &total);
1053 } else if (cflag) {
1054 cnt = do_write_compressed(bs, buf, offset, count, &total);
1055 } else {
1056 cnt = do_write(bs, buf, offset, count, &total);
1057 }
1058 gettimeofday(&t2, NULL);
1059
1060 if (cnt < 0) {
1061 printf("write failed: %s\n", strerror(-cnt));
1062 goto out;
1063 }
1064
1065 if (qflag) {
1066 goto out;
1067 }
1068
1069 /* Finally, report back -- -C gives a parsable format */
1070 t2 = tsub(t2, t1);
1071 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1072
1073out:
1074 if (!zflag) {
1075 qemu_io_free(buf);
1076 }
1077
1078 return 0;
1079}
1080
1081static void
1082writev_help(void)
1083{
1084 printf(
1085"\n"
1086" writes a range of bytes from the given offset source from multiple buffers\n"
1087"\n"
1088" Example:\n"
1089" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1090"\n"
1091" Writes into a segment of the currently open file, using a buffer\n"
1092" filled with a set pattern (0xcdcdcdcd).\n"
1093" -P, -- use different pattern to fill file\n"
1094" -C, -- report statistics in a machine parsable format\n"
1095" -q, -- quiet mode, do not show I/O statistics\n"
1096"\n");
1097}
1098
1099static int writev_f(BlockDriverState *bs, int argc, char **argv);
1100
1101static const cmdinfo_t writev_cmd = {
1102 .name = "writev",
1103 .cfunc = writev_f,
1104 .argmin = 2,
1105 .argmax = -1,
1106 .args = "[-Cq] [-P pattern ] off len [len..]",
1107 .oneline = "writes a number of bytes at a specified offset",
1108 .help = writev_help,
1109};
1110
1111static int writev_f(BlockDriverState *bs, int argc, char **argv)
1112{
1113 struct timeval t1, t2;
1114 int Cflag = 0, qflag = 0;
1115 int c, cnt;
1116 char *buf;
1117 int64_t offset;
1118 /* Some compilers get confused and warn if this is not initialized. */
1119 int total = 0;
1120 int nr_iov;
1121 int pattern = 0xcd;
1122 QEMUIOVector qiov;
1123
1124 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1125 switch (c) {
1126 case 'C':
1127 Cflag = 1;
1128 break;
1129 case 'q':
1130 qflag = 1;
1131 break;
1132 case 'P':
1133 pattern = parse_pattern(optarg);
1134 if (pattern < 0) {
1135 return 0;
1136 }
1137 break;
1138 default:
c2cdf5c5 1139 return qemuio_command_usage(&writev_cmd);
797ac58c
KW
1140 }
1141 }
1142
1143 if (optind > argc - 2) {
c2cdf5c5 1144 return qemuio_command_usage(&writev_cmd);
797ac58c
KW
1145 }
1146
1147 offset = cvtnum(argv[optind]);
1148 if (offset < 0) {
1149 printf("non-numeric length argument -- %s\n", argv[optind]);
1150 return 0;
1151 }
1152 optind++;
1153
1154 if (offset & 0x1ff) {
1155 printf("offset %" PRId64 " is not sector aligned\n",
1156 offset);
1157 return 0;
1158 }
1159
1160 nr_iov = argc - optind;
1161 buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
1162 if (buf == NULL) {
1163 return 0;
1164 }
1165
1166 gettimeofday(&t1, NULL);
1167 cnt = do_aio_writev(bs, &qiov, offset, &total);
1168 gettimeofday(&t2, NULL);
1169
1170 if (cnt < 0) {
1171 printf("writev failed: %s\n", strerror(-cnt));
1172 goto out;
1173 }
1174
1175 if (qflag) {
1176 goto out;
1177 }
1178
1179 /* Finally, report back -- -C gives a parsable format */
1180 t2 = tsub(t2, t1);
1181 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1182out:
1183 qemu_iovec_destroy(&qiov);
1184 qemu_io_free(buf);
1185 return 0;
1186}
1187
1188static void multiwrite_help(void)
1189{
1190 printf(
1191"\n"
1192" writes a range of bytes from the given offset source from multiple buffers,\n"
1193" in a batch of requests that may be merged by qemu\n"
1194"\n"
1195" Example:\n"
1196" 'multiwrite 512 1k 1k ; 4k 1k'\n"
1197" writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
1198"\n"
1199" Writes into a segment of the currently open file, using a buffer\n"
1200" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
1201" by one for each request contained in the multiwrite command.\n"
1202" -P, -- use different pattern to fill file\n"
1203" -C, -- report statistics in a machine parsable format\n"
1204" -q, -- quiet mode, do not show I/O statistics\n"
1205"\n");
1206}
1207
1208static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
1209
1210static const cmdinfo_t multiwrite_cmd = {
1211 .name = "multiwrite",
1212 .cfunc = multiwrite_f,
1213 .argmin = 2,
1214 .argmax = -1,
1215 .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
1216 .oneline = "issues multiple write requests at once",
1217 .help = multiwrite_help,
1218};
1219
1220static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
1221{
1222 struct timeval t1, t2;
1223 int Cflag = 0, qflag = 0;
1224 int c, cnt;
1225 char **buf;
1226 int64_t offset, first_offset = 0;
1227 /* Some compilers get confused and warn if this is not initialized. */
1228 int total = 0;
1229 int nr_iov;
1230 int nr_reqs;
1231 int pattern = 0xcd;
1232 QEMUIOVector *qiovs;
1233 int i;
1234 BlockRequest *reqs;
1235
1236 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1237 switch (c) {
1238 case 'C':
1239 Cflag = 1;
1240 break;
1241 case 'q':
1242 qflag = 1;
1243 break;
1244 case 'P':
1245 pattern = parse_pattern(optarg);
1246 if (pattern < 0) {
1247 return 0;
1248 }
1249 break;
1250 default:
c2cdf5c5 1251 return qemuio_command_usage(&writev_cmd);
797ac58c
KW
1252 }
1253 }
1254
1255 if (optind > argc - 2) {
c2cdf5c5 1256 return qemuio_command_usage(&writev_cmd);
797ac58c
KW
1257 }
1258
1259 nr_reqs = 1;
1260 for (i = optind; i < argc; i++) {
1261 if (!strcmp(argv[i], ";")) {
1262 nr_reqs++;
1263 }
1264 }
1265
1266 reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1267 buf = g_malloc0(nr_reqs * sizeof(*buf));
1268 qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1269
1270 for (i = 0; i < nr_reqs && optind < argc; i++) {
1271 int j;
1272
1273 /* Read the offset of the request */
1274 offset = cvtnum(argv[optind]);
1275 if (offset < 0) {
1276 printf("non-numeric offset argument -- %s\n", argv[optind]);
1277 goto out;
1278 }
1279 optind++;
1280
1281 if (offset & 0x1ff) {
1282 printf("offset %lld is not sector aligned\n",
1283 (long long)offset);
1284 goto out;
1285 }
1286
1287 if (i == 0) {
1288 first_offset = offset;
1289 }
1290
1291 /* Read lengths for qiov entries */
1292 for (j = optind; j < argc; j++) {
1293 if (!strcmp(argv[j], ";")) {
1294 break;
1295 }
1296 }
1297
1298 nr_iov = j - optind;
1299
1300 /* Build request */
1301 buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
1302 if (buf[i] == NULL) {
1303 goto out;
1304 }
1305
1306 reqs[i].qiov = &qiovs[i];
1307 reqs[i].sector = offset >> 9;
1308 reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1309
1310 optind = j + 1;
1311
1312 pattern++;
1313 }
1314
1315 /* If there were empty requests at the end, ignore them */
1316 nr_reqs = i;
1317
1318 gettimeofday(&t1, NULL);
1319 cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
1320 gettimeofday(&t2, NULL);
1321
1322 if (cnt < 0) {
1323 printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1324 goto out;
1325 }
1326
1327 if (qflag) {
1328 goto out;
1329 }
1330
1331 /* Finally, report back -- -C gives a parsable format */
1332 t2 = tsub(t2, t1);
1333 print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1334out:
1335 for (i = 0; i < nr_reqs; i++) {
1336 qemu_io_free(buf[i]);
1337 if (reqs[i].qiov != NULL) {
1338 qemu_iovec_destroy(&qiovs[i]);
1339 }
1340 }
1341 g_free(buf);
1342 g_free(reqs);
1343 g_free(qiovs);
1344 return 0;
1345}
1346
1347struct aio_ctx {
1348 QEMUIOVector qiov;
1349 int64_t offset;
1350 char *buf;
1351 int qflag;
1352 int vflag;
1353 int Cflag;
1354 int Pflag;
1355 int pattern;
1356 struct timeval t1;
1357};
1358
1359static void aio_write_done(void *opaque, int ret)
1360{
1361 struct aio_ctx *ctx = opaque;
1362 struct timeval t2;
1363
1364 gettimeofday(&t2, NULL);
1365
1366
1367 if (ret < 0) {
1368 printf("aio_write failed: %s\n", strerror(-ret));
1369 goto out;
1370 }
1371
1372 if (ctx->qflag) {
1373 goto out;
1374 }
1375
1376 /* Finally, report back -- -C gives a parsable format */
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 qemu_io_free(ctx->buf);
1382 qemu_iovec_destroy(&ctx->qiov);
1383 g_free(ctx);
1384}
1385
1386static void aio_read_done(void *opaque, int ret)
1387{
1388 struct aio_ctx *ctx = opaque;
1389 struct timeval t2;
1390
1391 gettimeofday(&t2, NULL);
1392
1393 if (ret < 0) {
1394 printf("readv failed: %s\n", strerror(-ret));
1395 goto out;
1396 }
1397
1398 if (ctx->Pflag) {
1399 void *cmp_buf = g_malloc(ctx->qiov.size);
1400
1401 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1402 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1403 printf("Pattern verification failed at offset %"
1404 PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1405 }
1406 g_free(cmp_buf);
1407 }
1408
1409 if (ctx->qflag) {
1410 goto out;
1411 }
1412
1413 if (ctx->vflag) {
1414 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1415 }
1416
1417 /* Finally, report back -- -C gives a parsable format */
1418 t2 = tsub(t2, ctx->t1);
1419 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1420 ctx->qiov.size, 1, ctx->Cflag);
1421out:
1422 qemu_io_free(ctx->buf);
1423 qemu_iovec_destroy(&ctx->qiov);
1424 g_free(ctx);
1425}
1426
1427static void aio_read_help(void)
1428{
1429 printf(
1430"\n"
1431" asynchronously reads a range of bytes from the given offset\n"
1432"\n"
1433" Example:\n"
1434" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1435"\n"
1436" Reads a segment of the currently open file, optionally dumping it to the\n"
1437" standard output stream (with -v option) for subsequent inspection.\n"
1438" The read is performed asynchronously and the aio_flush command must be\n"
1439" used to ensure all outstanding aio requests have been completed.\n"
1440" -C, -- report statistics in a machine parsable format\n"
1441" -P, -- use a pattern to verify read data\n"
1442" -v, -- dump buffer to standard output\n"
1443" -q, -- quiet mode, do not show I/O statistics\n"
1444"\n");
1445}
1446
1447static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1448
1449static const cmdinfo_t aio_read_cmd = {
1450 .name = "aio_read",
1451 .cfunc = aio_read_f,
1452 .argmin = 2,
1453 .argmax = -1,
1454 .args = "[-Cqv] [-P pattern ] off len [len..]",
1455 .oneline = "asynchronously reads a number of bytes",
1456 .help = aio_read_help,
1457};
1458
1459static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
1460{
1461 int nr_iov, c;
1462 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1463
1464 while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1465 switch (c) {
1466 case 'C':
1467 ctx->Cflag = 1;
1468 break;
1469 case 'P':
1470 ctx->Pflag = 1;
1471 ctx->pattern = parse_pattern(optarg);
1472 if (ctx->pattern < 0) {
1473 g_free(ctx);
1474 return 0;
1475 }
1476 break;
1477 case 'q':
1478 ctx->qflag = 1;
1479 break;
1480 case 'v':
1481 ctx->vflag = 1;
1482 break;
1483 default:
1484 g_free(ctx);
c2cdf5c5 1485 return qemuio_command_usage(&aio_read_cmd);
797ac58c
KW
1486 }
1487 }
1488
1489 if (optind > argc - 2) {
1490 g_free(ctx);
c2cdf5c5 1491 return qemuio_command_usage(&aio_read_cmd);
797ac58c
KW
1492 }
1493
1494 ctx->offset = cvtnum(argv[optind]);
1495 if (ctx->offset < 0) {
1496 printf("non-numeric length argument -- %s\n", argv[optind]);
1497 g_free(ctx);
1498 return 0;
1499 }
1500 optind++;
1501
1502 if (ctx->offset & 0x1ff) {
1503 printf("offset %" PRId64 " is not sector aligned\n",
1504 ctx->offset);
1505 g_free(ctx);
1506 return 0;
1507 }
1508
1509 nr_iov = argc - optind;
1510 ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1511 if (ctx->buf == NULL) {
1512 g_free(ctx);
1513 return 0;
1514 }
1515
1516 gettimeofday(&ctx->t1, NULL);
1517 bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1518 ctx->qiov.size >> 9, aio_read_done, ctx);
1519 return 0;
1520}
1521
1522static void aio_write_help(void)
1523{
1524 printf(
1525"\n"
1526" asynchronously writes a range of bytes from the given offset source\n"
1527" from multiple buffers\n"
1528"\n"
1529" Example:\n"
1530" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1531"\n"
1532" Writes into a segment of the currently open file, using a buffer\n"
1533" filled with a set pattern (0xcdcdcdcd).\n"
1534" The write is performed asynchronously and the aio_flush command must be\n"
1535" used to ensure all outstanding aio requests have been completed.\n"
1536" -P, -- use different pattern to fill file\n"
1537" -C, -- report statistics in a machine parsable format\n"
1538" -q, -- quiet mode, do not show I/O statistics\n"
1539"\n");
1540}
1541
1542static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1543
1544static const cmdinfo_t aio_write_cmd = {
1545 .name = "aio_write",
1546 .cfunc = aio_write_f,
1547 .argmin = 2,
1548 .argmax = -1,
1549 .args = "[-Cq] [-P pattern ] off len [len..]",
1550 .oneline = "asynchronously writes a number of bytes",
1551 .help = aio_write_help,
1552};
1553
1554static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
1555{
1556 int nr_iov, c;
1557 int pattern = 0xcd;
1558 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1559
1560 while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1561 switch (c) {
1562 case 'C':
1563 ctx->Cflag = 1;
1564 break;
1565 case 'q':
1566 ctx->qflag = 1;
1567 break;
1568 case 'P':
1569 pattern = parse_pattern(optarg);
1570 if (pattern < 0) {
1571 g_free(ctx);
1572 return 0;
1573 }
1574 break;
1575 default:
1576 g_free(ctx);
c2cdf5c5 1577 return qemuio_command_usage(&aio_write_cmd);
797ac58c
KW
1578 }
1579 }
1580
1581 if (optind > argc - 2) {
1582 g_free(ctx);
c2cdf5c5 1583 return qemuio_command_usage(&aio_write_cmd);
797ac58c
KW
1584 }
1585
1586 ctx->offset = cvtnum(argv[optind]);
1587 if (ctx->offset < 0) {
1588 printf("non-numeric length argument -- %s\n", argv[optind]);
1589 g_free(ctx);
1590 return 0;
1591 }
1592 optind++;
1593
1594 if (ctx->offset & 0x1ff) {
1595 printf("offset %" PRId64 " is not sector aligned\n",
1596 ctx->offset);
1597 g_free(ctx);
1598 return 0;
1599 }
1600
1601 nr_iov = argc - optind;
1602 ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
1603 if (ctx->buf == NULL) {
1604 g_free(ctx);
1605 return 0;
1606 }
1607
1608 gettimeofday(&ctx->t1, NULL);
1609 bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1610 ctx->qiov.size >> 9, aio_write_done, ctx);
1611 return 0;
1612}
1613
1614static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1615{
1616 bdrv_drain_all();
1617 return 0;
1618}
1619
1620static const cmdinfo_t aio_flush_cmd = {
1621 .name = "aio_flush",
1622 .cfunc = aio_flush_f,
1623 .oneline = "completes all outstanding aio requests"
1624};
1625
1626static int flush_f(BlockDriverState *bs, int argc, char **argv)
1627{
1628 bdrv_flush(bs);
1629 return 0;
1630}
1631
1632static const cmdinfo_t flush_cmd = {
1633 .name = "flush",
1634 .altname = "f",
1635 .cfunc = flush_f,
1636 .oneline = "flush all in-core file state to disk",
1637};
1638
1639static int truncate_f(BlockDriverState *bs, int argc, char **argv)
1640{
1641 int64_t offset;
1642 int ret;
1643
1644 offset = cvtnum(argv[1]);
1645 if (offset < 0) {
1646 printf("non-numeric truncate argument -- %s\n", argv[1]);
1647 return 0;
1648 }
1649
1650 ret = bdrv_truncate(bs, offset);
1651 if (ret < 0) {
1652 printf("truncate: %s\n", strerror(-ret));
1653 return 0;
1654 }
1655
1656 return 0;
1657}
1658
1659static const cmdinfo_t truncate_cmd = {
1660 .name = "truncate",
1661 .altname = "t",
1662 .cfunc = truncate_f,
1663 .argmin = 1,
1664 .argmax = 1,
1665 .args = "off",
1666 .oneline = "truncates the current file at the given offset",
1667};
1668
1669static int length_f(BlockDriverState *bs, int argc, char **argv)
1670{
1671 int64_t size;
1672 char s1[64];
1673
1674 size = bdrv_getlength(bs);
1675 if (size < 0) {
1676 printf("getlength: %s\n", strerror(-size));
1677 return 0;
1678 }
1679
1680 cvtstr(size, s1, sizeof(s1));
1681 printf("%s\n", s1);
1682 return 0;
1683}
1684
1685
1686static const cmdinfo_t length_cmd = {
1687 .name = "length",
1688 .altname = "l",
1689 .cfunc = length_f,
1690 .oneline = "gets the length of the current file",
1691};
1692
1693
1694static int info_f(BlockDriverState *bs, int argc, char **argv)
1695{
1696 BlockDriverInfo bdi;
a8d8ecb7 1697 ImageInfoSpecific *spec_info;
797ac58c
KW
1698 char s1[64], s2[64];
1699 int ret;
1700
1701 if (bs->drv && bs->drv->format_name) {
1702 printf("format name: %s\n", bs->drv->format_name);
1703 }
1704 if (bs->drv && bs->drv->protocol_name) {
1705 printf("format name: %s\n", bs->drv->protocol_name);
1706 }
1707
1708 ret = bdrv_get_info(bs, &bdi);
1709 if (ret) {
1710 return 0;
1711 }
1712
1713 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1714 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1715
1716 printf("cluster size: %s\n", s1);
1717 printf("vm state offset: %s\n", s2);
1718
a8d8ecb7
HR
1719 spec_info = bdrv_get_specific_info(bs);
1720 if (spec_info) {
1721 printf("Format specific information:\n");
1722 bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
1723 qapi_free_ImageInfoSpecific(spec_info);
1724 }
1725
797ac58c
KW
1726 return 0;
1727}
1728
1729
1730
1731static const cmdinfo_t info_cmd = {
1732 .name = "info",
1733 .altname = "i",
1734 .cfunc = info_f,
1735 .oneline = "prints information about the current file",
1736};
1737
1738static void discard_help(void)
1739{
1740 printf(
1741"\n"
1742" discards a range of bytes from the given offset\n"
1743"\n"
1744" Example:\n"
1745" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1746"\n"
1747" Discards a segment of the currently open file.\n"
1748" -C, -- report statistics in a machine parsable format\n"
1749" -q, -- quiet mode, do not show I/O statistics\n"
1750"\n");
1751}
1752
1753static int discard_f(BlockDriverState *bs, int argc, char **argv);
1754
1755static const cmdinfo_t discard_cmd = {
1756 .name = "discard",
1757 .altname = "d",
1758 .cfunc = discard_f,
1759 .argmin = 2,
1760 .argmax = -1,
1761 .args = "[-Cq] off len",
1762 .oneline = "discards a number of bytes at a specified offset",
1763 .help = discard_help,
1764};
1765
1766static int discard_f(BlockDriverState *bs, int argc, char **argv)
1767{
1768 struct timeval t1, t2;
1769 int Cflag = 0, qflag = 0;
1770 int c, ret;
1771 int64_t offset;
1772 int count;
1773
1774 while ((c = getopt(argc, argv, "Cq")) != EOF) {
1775 switch (c) {
1776 case 'C':
1777 Cflag = 1;
1778 break;
1779 case 'q':
1780 qflag = 1;
1781 break;
1782 default:
c2cdf5c5 1783 return qemuio_command_usage(&discard_cmd);
797ac58c
KW
1784 }
1785 }
1786
1787 if (optind != argc - 2) {
c2cdf5c5 1788 return qemuio_command_usage(&discard_cmd);
797ac58c
KW
1789 }
1790
1791 offset = cvtnum(argv[optind]);
1792 if (offset < 0) {
1793 printf("non-numeric length argument -- %s\n", argv[optind]);
1794 return 0;
1795 }
1796
1797 optind++;
1798 count = cvtnum(argv[optind]);
1799 if (count < 0) {
1800 printf("non-numeric length argument -- %s\n", argv[optind]);
1801 return 0;
1802 }
1803
1804 gettimeofday(&t1, NULL);
1805 ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1806 count >> BDRV_SECTOR_BITS);
1807 gettimeofday(&t2, NULL);
1808
1809 if (ret < 0) {
1810 printf("discard failed: %s\n", strerror(-ret));
1811 goto out;
1812 }
1813
1814 /* Finally, report back -- -C gives a parsable format */
1815 if (!qflag) {
1816 t2 = tsub(t2, t1);
1817 print_report("discard", &t2, offset, count, count, 1, Cflag);
1818 }
1819
1820out:
1821 return 0;
1822}
1823
1824static int alloc_f(BlockDriverState *bs, int argc, char **argv)
1825{
1826 int64_t offset, sector_num;
1827 int nb_sectors, remaining;
1828 char s1[64];
1829 int num, sum_alloc;
1830 int ret;
1831
1832 offset = cvtnum(argv[1]);
1833 if (offset < 0) {
1834 printf("non-numeric offset argument -- %s\n", argv[1]);
1835 return 0;
1836 } else if (offset & 0x1ff) {
1837 printf("offset %" PRId64 " is not sector aligned\n",
1838 offset);
1839 return 0;
1840 }
1841
1842 if (argc == 3) {
1843 nb_sectors = cvtnum(argv[2]);
1844 if (nb_sectors < 0) {
1845 printf("non-numeric length argument -- %s\n", argv[2]);
1846 return 0;
1847 }
1848 } else {
1849 nb_sectors = 1;
1850 }
1851
1852 remaining = nb_sectors;
1853 sum_alloc = 0;
1854 sector_num = offset >> 9;
1855 while (remaining) {
1856 ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
d663640c
PB
1857 if (ret < 0) {
1858 printf("is_allocated failed: %s\n", strerror(-ret));
1859 return 0;
1860 }
797ac58c
KW
1861 sector_num += num;
1862 remaining -= num;
1863 if (ret) {
1864 sum_alloc += num;
1865 }
1866 if (num == 0) {
1867 nb_sectors -= remaining;
1868 remaining = 0;
1869 }
1870 }
1871
1872 cvtstr(offset, s1, sizeof(s1));
1873
1874 printf("%d/%d sectors allocated at offset %s\n",
1875 sum_alloc, nb_sectors, s1);
1876 return 0;
1877}
1878
1879static const cmdinfo_t alloc_cmd = {
1880 .name = "alloc",
1881 .altname = "a",
1882 .argmin = 1,
1883 .argmax = 2,
1884 .cfunc = alloc_f,
1885 .args = "off [sectors]",
1886 .oneline = "checks if a sector is present in the file",
1887};
1888
1889
1890static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
1891 int64_t nb_sectors, int64_t *pnum)
1892{
1893 int num, num_checked;
1894 int ret, firstret;
1895
1896 num_checked = MIN(nb_sectors, INT_MAX);
1897 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1898 if (ret < 0) {
1899 return ret;
1900 }
1901
1902 firstret = ret;
1903 *pnum = num;
1904
1905 while (nb_sectors > 0 && ret == firstret) {
1906 sector_num += num;
1907 nb_sectors -= num;
1908
1909 num_checked = MIN(nb_sectors, INT_MAX);
1910 ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1911 if (ret == firstret) {
1912 *pnum += num;
1913 } else {
1914 break;
1915 }
1916 }
1917
1918 return firstret;
1919}
1920
1921static int map_f(BlockDriverState *bs, int argc, char **argv)
1922{
1923 int64_t offset;
1924 int64_t nb_sectors;
1925 char s1[64];
1926 int64_t num;
1927 int ret;
1928 const char *retstr;
1929
1930 offset = 0;
1931 nb_sectors = bs->total_sectors;
1932
1933 do {
1934 ret = map_is_allocated(bs, offset, nb_sectors, &num);
1935 if (ret < 0) {
1936 error_report("Failed to get allocation status: %s", strerror(-ret));
1937 return 0;
1938 }
1939
1940 retstr = ret ? " allocated" : "not allocated";
1941 cvtstr(offset << 9ULL, s1, sizeof(s1));
1942 printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
1943 "at offset %s (%d)\n",
1944 offset << 9ULL, num, nb_sectors, retstr, s1, ret);
1945
1946 offset += num;
1947 nb_sectors -= num;
1948 } while (offset < bs->total_sectors);
1949
1950 return 0;
1951}
1952
1953static const cmdinfo_t map_cmd = {
1954 .name = "map",
1955 .argmin = 0,
1956 .argmax = 0,
1957 .cfunc = map_f,
1958 .args = "",
1959 .oneline = "prints the allocated areas of a file",
1960};
1961
1962static int break_f(BlockDriverState *bs, int argc, char **argv)
1963{
1964 int ret;
1965
1966 ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1967 if (ret < 0) {
1968 printf("Could not set breakpoint: %s\n", strerror(-ret));
1969 }
1970
1971 return 0;
1972}
1973
4cc70e93
FZ
1974static int remove_break_f(BlockDriverState *bs, int argc, char **argv)
1975{
1976 int ret;
1977
1978 ret = bdrv_debug_remove_breakpoint(bs, argv[1]);
1979 if (ret < 0) {
1980 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
1981 }
1982
1983 return 0;
1984}
1985
797ac58c
KW
1986static const cmdinfo_t break_cmd = {
1987 .name = "break",
1988 .argmin = 2,
1989 .argmax = 2,
1990 .cfunc = break_f,
1991 .args = "event tag",
1992 .oneline = "sets a breakpoint on event and tags the stopped "
1993 "request as tag",
1994};
1995
4cc70e93
FZ
1996static const cmdinfo_t remove_break_cmd = {
1997 .name = "remove_break",
1998 .argmin = 1,
1999 .argmax = 1,
2000 .cfunc = remove_break_f,
2001 .args = "tag",
2002 .oneline = "remove a breakpoint by tag",
2003};
2004
797ac58c
KW
2005static int resume_f(BlockDriverState *bs, int argc, char **argv)
2006{
2007 int ret;
2008
2009 ret = bdrv_debug_resume(bs, argv[1]);
2010 if (ret < 0) {
2011 printf("Could not resume request: %s\n", strerror(-ret));
2012 }
2013
2014 return 0;
2015}
2016
2017static const cmdinfo_t resume_cmd = {
2018 .name = "resume",
2019 .argmin = 1,
2020 .argmax = 1,
2021 .cfunc = resume_f,
2022 .args = "tag",
2023 .oneline = "resumes the request tagged as tag",
2024};
2025
2026static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
2027{
2028 while (!bdrv_debug_is_suspended(bs, argv[1])) {
2029 qemu_aio_wait();
2030 }
2031
2032 return 0;
2033}
2034
2035static const cmdinfo_t wait_break_cmd = {
2036 .name = "wait_break",
2037 .argmin = 1,
2038 .argmax = 1,
2039 .cfunc = wait_break_f,
2040 .args = "tag",
2041 .oneline = "waits for the suspension of a request",
2042};
2043
2044static int abort_f(BlockDriverState *bs, int argc, char **argv)
2045{
2046 abort();
2047}
2048
2049static const cmdinfo_t abort_cmd = {
2050 .name = "abort",
2051 .cfunc = abort_f,
2052 .flags = CMD_NOFILE_OK,
2053 .oneline = "simulate a program crash using abort(3)",
2054};
2055
f18a834a
KW
2056static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2057{
2058 if (cmd) {
2059 printf("%s ", cmd);
2060 } else {
2061 printf("%s ", ct->name);
2062 if (ct->altname) {
2063 printf("(or %s) ", ct->altname);
2064 }
2065 }
2066
2067 if (ct->args) {
2068 printf("%s ", ct->args);
2069 }
2070 printf("-- %s\n", ct->oneline);
2071}
2072
2073static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2074{
2075 help_oneline(cmd, ct);
2076 if (ct->help) {
2077 ct->help();
2078 }
2079}
2080
2081static void help_all(void)
2082{
2083 const cmdinfo_t *ct;
2084
2085 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2086 help_oneline(ct->name, ct);
2087 }
2088 printf("\nUse 'help commandname' for extended help.\n");
2089}
2090
2091static int help_f(BlockDriverState *bs, int argc, char **argv)
2092{
2093 const cmdinfo_t *ct;
2094
2095 if (argc == 1) {
2096 help_all();
2097 return 0;
2098 }
2099
2100 ct = find_command(argv[1]);
2101 if (ct == NULL) {
2102 printf("command %s not found\n", argv[1]);
2103 return 0;
2104 }
2105
2106 help_onecmd(argv[1], ct);
2107 return 0;
2108}
2109
2110static const cmdinfo_t help_cmd = {
2111 .name = "help",
2112 .altname = "?",
2113 .cfunc = help_f,
2114 .argmin = 0,
2115 .argmax = 1,
2116 .flags = CMD_FLAG_GLOBAL,
2117 .args = "[command]",
2118 .oneline = "help for one or all commands",
2119};
2120
3d21994f 2121bool qemuio_command(BlockDriverState *bs, const char *cmd)
dd583296
KW
2122{
2123 char *input;
2124 const cmdinfo_t *ct;
2125 char **v;
2126 int c;
2127 bool done = false;
2128
2129 input = g_strdup(cmd);
2130 v = breakline(input, &c);
2131 if (c) {
2132 ct = find_command(v[0]);
2133 if (ct) {
3d21994f 2134 done = command(bs, ct, c, v);
dd583296
KW
2135 } else {
2136 fprintf(stderr, "command \"%s\" not found\n", v[0]);
2137 }
2138 }
2139 g_free(input);
2140 g_free(v);
2141
2142 return done;
2143}
2144
797ac58c
KW
2145static void __attribute((constructor)) init_qemuio_commands(void)
2146{
2147 /* initialize commands */
c2cdf5c5
KW
2148 qemuio_add_command(&help_cmd);
2149 qemuio_add_command(&read_cmd);
2150 qemuio_add_command(&readv_cmd);
2151 qemuio_add_command(&write_cmd);
2152 qemuio_add_command(&writev_cmd);
2153 qemuio_add_command(&multiwrite_cmd);
2154 qemuio_add_command(&aio_read_cmd);
2155 qemuio_add_command(&aio_write_cmd);
2156 qemuio_add_command(&aio_flush_cmd);
2157 qemuio_add_command(&flush_cmd);
2158 qemuio_add_command(&truncate_cmd);
2159 qemuio_add_command(&length_cmd);
2160 qemuio_add_command(&info_cmd);
2161 qemuio_add_command(&discard_cmd);
2162 qemuio_add_command(&alloc_cmd);
2163 qemuio_add_command(&map_cmd);
2164 qemuio_add_command(&break_cmd);
4cc70e93 2165 qemuio_add_command(&remove_break_cmd);
c2cdf5c5
KW
2166 qemuio_add_command(&resume_cmd);
2167 qemuio_add_command(&wait_break_cmd);
2168 qemuio_add_command(&abort_cmd);
797ac58c 2169}