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