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