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