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