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