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