1
2
3
4
5
6
7
8
9
10
11#include "qemu/osdep.h"
12#include "qapi/error.h"
13#include "qobject/qdict.h"
14#include "qemu-io.h"
15#include "system/block-backend.h"
16#include "block/block.h"
17#include "block/block_int.h"
18#include "block/qapi.h"
19#include "qemu/error-report.h"
20#include "qemu/main-loop.h"
21#include "qemu/option.h"
22#include "qemu/timer.h"
23#include "qemu/cutils.h"
24#include "qemu/memalign.h"
25
26#define CMD_NOFILE_OK 0x01
27
28bool qemuio_misalign;
29
30static cmdinfo_t *cmdtab;
31static int ncmds;
32
33static int compare_cmdname(const void *a, const void *b)
34{
35 return strcmp(((const cmdinfo_t *)a)->name,
36 ((const cmdinfo_t *)b)->name);
37}
38
39void qemuio_add_command(const cmdinfo_t *ci)
40{
41
42
43
44
45
46 assert(ci->perm == 0 ||
47 (ci->flags & (CMD_FLAG_GLOBAL | CMD_NOFILE_OK)) == 0);
48 cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds);
49 cmdtab[ncmds - 1] = *ci;
50 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
51}
52
53void qemuio_command_usage(const cmdinfo_t *ci)
54{
55 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
56}
57
58static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
59{
60 if (ct->flags & CMD_FLAG_GLOBAL) {
61 return 1;
62 }
63 if (!(ct->flags & CMD_NOFILE_OK) && !blk) {
64 fprintf(stderr, "no file open, try 'help open'\n");
65 return 0;
66 }
67 return 1;
68}
69
70static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
71 char **argv)
72{
73 char *cmd = argv[0];
74
75 if (!init_check_command(blk, ct)) {
76 return -EINVAL;
77 }
78
79 if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
80 if (ct->argmax == -1) {
81 fprintf(stderr,
82 "bad argument count %d to %s, expected at least %d arguments\n",
83 argc-1, cmd, ct->argmin);
84 } else if (ct->argmin == ct->argmax) {
85 fprintf(stderr,
86 "bad argument count %d to %s, expected %d arguments\n",
87 argc-1, cmd, ct->argmin);
88 } else {
89 fprintf(stderr,
90 "bad argument count %d to %s, expected between %d and %d arguments\n",
91 argc-1, cmd, ct->argmin, ct->argmax);
92 }
93 return -EINVAL;
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108 assert(blk || !ct->perm);
109 if (ct->perm && blk_is_available(blk)) {
110 uint64_t orig_perm, orig_shared_perm;
111 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
112
113 if (ct->perm & ~orig_perm) {
114 uint64_t new_perm;
115 Error *local_err = NULL;
116 int ret;
117
118 new_perm = orig_perm | ct->perm;
119
120 ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
121 if (ret < 0) {
122 error_report_err(local_err);
123 return ret;
124 }
125 }
126 }
127
128 qemu_reset_optind();
129 return ct->cfunc(blk, argc, argv);
130}
131
132static const cmdinfo_t *find_command(const char *cmd)
133{
134 cmdinfo_t *ct;
135
136 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
137 if (strcmp(ct->name, cmd) == 0 ||
138 (ct->altname && strcmp(ct->altname, cmd) == 0))
139 {
140 return (const cmdinfo_t *)ct;
141 }
142 }
143 return NULL;
144}
145
146
147void qemuio_complete_command(const char *input,
148 void (*fn)(const char *cmd, void *opaque),
149 void *opaque)
150{
151 cmdinfo_t *ct;
152 size_t input_len = strlen(input);
153
154 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
155 if (strncmp(input, ct->name, input_len) == 0) {
156 fn(ct->name, opaque);
157 }
158 }
159}
160
161static char **breakline(char *input, int *count)
162{
163 int c = 0;
164 char *p;
165 char **rval = g_new0(char *, 1);
166
167 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
168 if (!*p) {
169 continue;
170 }
171 c++;
172 rval = g_renew(char *, rval, (c + 1));
173 rval[c - 1] = p;
174 rval[c] = NULL;
175 }
176 *count = c;
177 return rval;
178}
179
180static int64_t cvtnum(const char *s)
181{
182 int err;
183 uint64_t value;
184
185 err = qemu_strtosz(s, NULL, &value);
186 if (err < 0) {
187 return err;
188 }
189 if (value > INT64_MAX) {
190 return -ERANGE;
191 }
192 return value;
193}
194
195static void print_cvtnum_err(int64_t rc, const char *arg)
196{
197 switch (rc) {
198 case -EINVAL:
199 printf("Parsing error: non-numeric argument,"
200 " or extraneous/unrecognized suffix -- %s\n", arg);
201 break;
202 case -ERANGE:
203 printf("Parsing error: argument too large -- %s\n", arg);
204 break;
205 default:
206 printf("Parsing error: %s\n", arg);
207 }
208}
209
210#define EXABYTES(x) ((long long)(x) << 60)
211#define PETABYTES(x) ((long long)(x) << 50)
212#define TERABYTES(x) ((long long)(x) << 40)
213#define GIGABYTES(x) ((long long)(x) << 30)
214#define MEGABYTES(x) ((long long)(x) << 20)
215#define KILOBYTES(x) ((long long)(x) << 10)
216
217#define TO_EXABYTES(x) ((x) / EXABYTES(1))
218#define TO_PETABYTES(x) ((x) / PETABYTES(1))
219#define TO_TERABYTES(x) ((x) / TERABYTES(1))
220#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
221#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
222#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
223
224static void cvtstr(double value, char *str, size_t size)
225{
226 char *trim;
227 const char *suffix;
228
229 if (value >= EXABYTES(1)) {
230 suffix = " EiB";
231 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
232 } else if (value >= PETABYTES(1)) {
233 suffix = " PiB";
234 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
235 } else if (value >= TERABYTES(1)) {
236 suffix = " TiB";
237 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
238 } else if (value >= GIGABYTES(1)) {
239 suffix = " GiB";
240 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
241 } else if (value >= MEGABYTES(1)) {
242 suffix = " MiB";
243 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
244 } else if (value >= KILOBYTES(1)) {
245 suffix = " KiB";
246 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
247 } else {
248 suffix = " bytes";
249 snprintf(str, size - 6, "%f", value);
250 }
251
252 trim = strstr(str, ".000");
253 if (trim) {
254 strcpy(trim, suffix);
255 } else {
256 strcat(str, suffix);
257 }
258}
259
260
261
262static struct timespec tsub(struct timespec t1, struct timespec t2)
263{
264 t1.tv_nsec -= t2.tv_nsec;
265 if (t1.tv_nsec < 0) {
266 t1.tv_nsec += NANOSECONDS_PER_SECOND;
267 t1.tv_sec--;
268 }
269 t1.tv_sec -= t2.tv_sec;
270 return t1;
271}
272
273static double tdiv(double value, struct timespec tv)
274{
275 double seconds = tv.tv_sec + (tv.tv_nsec / 1e9);
276 return value / seconds;
277}
278
279#define HOURS(sec) ((sec) / (60 * 60))
280#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
281#define SECONDS(sec) ((sec) % 60)
282
283enum {
284 DEFAULT_TIME = 0x0,
285 TERSE_FIXED_TIME = 0x1,
286 VERBOSE_FIXED_TIME = 0x2,
287};
288
289static void timestr(struct timespec *tv, char *ts, size_t size, int format)
290{
291 double frac_sec = tv->tv_nsec / 1e9;
292
293 if (format & TERSE_FIXED_TIME) {
294 if (!HOURS(tv->tv_sec)) {
295 snprintf(ts, size, "%u:%05.2f",
296 (unsigned int) MINUTES(tv->tv_sec),
297 SECONDS(tv->tv_sec) + frac_sec);
298 return;
299 }
300 format |= VERBOSE_FIXED_TIME;
301 }
302
303 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
304 snprintf(ts, size, "%u:%02u:%05.2f",
305 (unsigned int) HOURS(tv->tv_sec),
306 (unsigned int) MINUTES(tv->tv_sec),
307 SECONDS(tv->tv_sec) + frac_sec);
308 } else {
309 snprintf(ts, size, "%05.2f sec", frac_sec);
310 }
311}
312
313
314
315
316
317
318
319static int parse_pattern(const char *arg)
320{
321 char *endptr = NULL;
322 long pattern;
323
324 pattern = strtol(arg, &endptr, 0);
325 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
326 printf("%s is not a valid pattern byte\n", arg);
327 return -1;
328 }
329
330 return pattern;
331}
332
333
334
335
336
337
338
339
340#define MISALIGN_OFFSET 16
341static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern,
342 bool register_buf)
343{
344 void *buf;
345
346 if (qemuio_misalign) {
347 len += MISALIGN_OFFSET;
348 }
349 buf = blk_blockalign(blk, len);
350 memset(buf, pattern, len);
351 if (register_buf) {
352 blk_register_buf(blk, buf, len, &error_abort);
353 }
354 if (qemuio_misalign) {
355 buf += MISALIGN_OFFSET;
356 }
357 return buf;
358}
359
360static void qemu_io_free(BlockBackend *blk, void *p, size_t len,
361 bool unregister_buf)
362{
363 if (qemuio_misalign) {
364 p -= MISALIGN_OFFSET;
365 len += MISALIGN_OFFSET;
366 }
367 if (unregister_buf) {
368 blk_unregister_buf(blk, p, len);
369 }
370 qemu_vfree(p);
371}
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
389 const char *file_name, bool register_buf)
390{
391 size_t alloc_len = len + (qemuio_misalign ? MISALIGN_OFFSET : 0);
392 char *alloc_buf, *buf, *end;
393 FILE *f = fopen(file_name, "r");
394 int pattern_len;
395
396 if (!f) {
397 perror(file_name);
398 return NULL;
399 }
400
401 alloc_buf = buf = blk_blockalign(blk, alloc_len);
402
403 if (qemuio_misalign) {
404 buf += MISALIGN_OFFSET;
405 }
406
407 pattern_len = fread(buf, 1, len, f);
408
409 if (ferror(f)) {
410 perror(file_name);
411 goto error;
412 }
413
414 if (pattern_len == 0) {
415 fprintf(stderr, "%s: file is empty\n", file_name);
416 goto error;
417 }
418
419 fclose(f);
420 f = NULL;
421
422 if (register_buf) {
423 blk_register_buf(blk, alloc_buf, alloc_len, &error_abort);
424 }
425
426 end = buf + len;
427 for (char *p = buf + pattern_len; p < end; p += pattern_len) {
428 memcpy(p, buf, MIN(pattern_len, end - p));
429 }
430
431 return buf;
432
433error:
434
435
436
437
438 qemu_io_free(blk, alloc_buf, alloc_len, false);
439 if (f) {
440 fclose(f);
441 }
442 return NULL;
443}
444
445static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
446{
447 uint64_t i;
448 int j;
449 const uint8_t *p;
450
451 for (i = 0, p = buffer; i < len; i += 16) {
452 const uint8_t *s = p;
453
454 printf("%08" PRIx64 ": ", offset + i);
455 for (j = 0; j < 16 && i + j < len; j++, p++) {
456 printf("%02x ", *p);
457 }
458 printf(" ");
459 for (j = 0; j < 16 && i + j < len; j++, s++) {
460 if (isalnum(*s)) {
461 printf("%c", *s);
462 } else {
463 printf(".");
464 }
465 }
466 printf("\n");
467 }
468}
469
470static void print_report(const char *op, struct timespec *t, int64_t offset,
471 int64_t count, int64_t total, int cnt, bool Cflag)
472{
473 char s1[64], s2[64], ts[64];
474
475 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
476 if (!Cflag) {
477 cvtstr((double)total, s1, sizeof(s1));
478 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
479 printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n",
480 op, total, count, offset);
481 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
482 s1, cnt, ts, s2, tdiv((double)cnt, *t));
483 } else {
484 printf("%"PRId64",%d,%s,%.3f,%.3f\n",
485 total, cnt, ts,
486 tdiv((double)total, *t),
487 tdiv((double)cnt, *t));
488 }
489}
490
491
492
493
494
495static void *
496create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
497 int pattern, bool register_buf)
498{
499 size_t *sizes = g_new0(size_t, nr_iov);
500 size_t count = 0;
501 void *buf = NULL;
502 void *p;
503 int i;
504
505 for (i = 0; i < nr_iov; i++) {
506 char *arg = argv[i];
507 int64_t len;
508
509 len = cvtnum(arg);
510 if (len < 0) {
511 print_cvtnum_err(len, arg);
512 goto fail;
513 }
514
515 if (len > BDRV_REQUEST_MAX_BYTES) {
516 printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg,
517 (uint64_t)BDRV_REQUEST_MAX_BYTES);
518 goto fail;
519 }
520
521 if (count > BDRV_REQUEST_MAX_BYTES - len) {
522 printf("The total number of bytes exceed the maximum size %" PRIu64
523 "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES);
524 goto fail;
525 }
526
527 sizes[i] = len;
528 count += len;
529 }
530
531 qemu_iovec_init(qiov, nr_iov);
532
533 buf = p = qemu_io_alloc(blk, count, pattern, register_buf);
534
535 for (i = 0; i < nr_iov; i++) {
536 qemu_iovec_add(qiov, p, sizes[i]);
537 p += sizes[i];
538 }
539
540fail:
541 g_free(sizes);
542 return buf;
543}
544
545static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
546 int64_t bytes, BdrvRequestFlags flags, int64_t *total)
547{
548 int ret;
549
550 if (bytes > INT_MAX) {
551 return -ERANGE;
552 }
553
554 ret = blk_pread(blk, offset, bytes, (uint8_t *)buf, flags);
555 if (ret < 0) {
556 return ret;
557 }
558 *total = bytes;
559 return 1;
560}
561
562static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
563 int64_t bytes, BdrvRequestFlags flags, int64_t *total)
564{
565 int ret;
566
567 if (bytes > INT_MAX) {
568 return -ERANGE;
569 }
570
571 ret = blk_pwrite(blk, offset, bytes, (uint8_t *)buf, flags);
572 if (ret < 0) {
573 return ret;
574 }
575 *total = bytes;
576 return 1;
577}
578
579static int do_pwrite_zeroes(BlockBackend *blk, int64_t offset,
580 int64_t bytes, BdrvRequestFlags flags,
581 int64_t *total)
582{
583 int ret = blk_pwrite_zeroes(blk, offset, bytes,
584 flags | BDRV_REQ_ZERO_WRITE);
585
586 if (ret < 0) {
587 return ret;
588 }
589 *total = bytes;
590 return 1;
591}
592
593static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
594 int64_t bytes, int64_t *total)
595{
596 int ret;
597
598 if (bytes > BDRV_REQUEST_MAX_BYTES) {
599 return -ERANGE;
600 }
601
602 ret = blk_pwrite_compressed(blk, offset, bytes, buf);
603 if (ret < 0) {
604 return ret;
605 }
606 *total = bytes;
607 return 1;
608}
609
610static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset,
611 int64_t count, int64_t *total)
612{
613 if (count > INT_MAX) {
614 return -ERANGE;
615 }
616
617 *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count);
618 if (*total < 0) {
619 return *total;
620 }
621 return 1;
622}
623
624static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset,
625 int64_t count, int64_t *total)
626{
627 if (count > INT_MAX) {
628 return -ERANGE;
629 }
630
631 *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count);
632 if (*total < 0) {
633 return *total;
634 }
635 return 1;
636}
637
638#define NOT_DONE 0x7fffffff
639static void aio_rw_done(void *opaque, int ret)
640{
641 *(int *)opaque = ret;
642}
643
644static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
645 int64_t offset, BdrvRequestFlags flags, int *total)
646{
647 int async_ret = NOT_DONE;
648
649 blk_aio_preadv(blk, offset, qiov, flags, aio_rw_done, &async_ret);
650 while (async_ret == NOT_DONE) {
651 main_loop_wait(false);
652 }
653
654 *total = qiov->size;
655 return async_ret < 0 ? async_ret : 1;
656}
657
658static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
659 int64_t offset, BdrvRequestFlags flags, int *total)
660{
661 int async_ret = NOT_DONE;
662
663 blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret);
664 while (async_ret == NOT_DONE) {
665 main_loop_wait(false);
666 }
667
668 *total = qiov->size;
669 return async_ret < 0 ? async_ret : 1;
670}
671
672static void read_help(void)
673{
674 printf(
675"\n"
676" reads a range of bytes from the given offset\n"
677"\n"
678" Example:\n"
679" 'read -v 512 1k' - dumps 1 kilobyte 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" -b, -- read from the VM state rather than the virtual disk\n"
684" -C, -- report statistics in a machine parsable format\n"
685" -l, -- length for pattern verification (only with -P)\n"
686" -p, -- ignored for backwards compatibility\n"
687" -P, -- use a pattern to verify read data\n"
688" -q, -- quiet mode, do not show I/O statistics\n"
689" -r, -- register I/O buffer\n"
690" -s, -- start offset for pattern verification (only with -P)\n"
691" -v, -- dump buffer to standard output\n"
692"\n");
693}
694
695static int read_f(BlockBackend *blk, int argc, char **argv);
696
697static const cmdinfo_t read_cmd = {
698 .name = "read",
699 .altname = "r",
700 .cfunc = read_f,
701 .argmin = 2,
702 .argmax = -1,
703 .args = "[-abCqrv] [-P pattern [-s off] [-l len]] off len",
704 .oneline = "reads a number of bytes at a specified offset",
705 .help = read_help,
706};
707
708static int read_f(BlockBackend *blk, int argc, char **argv)
709{
710 struct timespec t1, t2;
711 bool Cflag = false, qflag = false, vflag = false;
712 bool Pflag = false, sflag = false, lflag = false, bflag = false;
713 int c, cnt, ret;
714 char *buf;
715 int64_t offset;
716 int64_t count;
717
718 int64_t total = 0;
719 int pattern = 0;
720 int64_t pattern_offset = 0, pattern_count = 0;
721 BdrvRequestFlags flags = 0;
722
723 while ((c = getopt(argc, argv, "bCl:pP:qrs:v")) != -1) {
724 switch (c) {
725 case 'b':
726 bflag = true;
727 break;
728 case 'C':
729 Cflag = true;
730 break;
731 case 'l':
732 lflag = true;
733 pattern_count = cvtnum(optarg);
734 if (pattern_count < 0) {
735 print_cvtnum_err(pattern_count, optarg);
736 return pattern_count;
737 }
738 break;
739 case 'p':
740
741 break;
742 case 'P':
743 Pflag = true;
744 pattern = parse_pattern(optarg);
745 if (pattern < 0) {
746 return -EINVAL;
747 }
748 break;
749 case 'q':
750 qflag = true;
751 break;
752 case 'r':
753 flags |= BDRV_REQ_REGISTERED_BUF;
754 break;
755 case 's':
756 sflag = true;
757 pattern_offset = cvtnum(optarg);
758 if (pattern_offset < 0) {
759 print_cvtnum_err(pattern_offset, optarg);
760 return pattern_offset;
761 }
762 break;
763 case 'v':
764 vflag = true;
765 break;
766 default:
767 qemuio_command_usage(&read_cmd);
768 return -EINVAL;
769 }
770 }
771
772 if (optind != argc - 2) {
773 qemuio_command_usage(&read_cmd);
774 return -EINVAL;
775 }
776
777 offset = cvtnum(argv[optind]);
778 if (offset < 0) {
779 print_cvtnum_err(offset, argv[optind]);
780 return offset;
781 }
782
783 optind++;
784 count = cvtnum(argv[optind]);
785 if (count < 0) {
786 print_cvtnum_err(count, argv[optind]);
787 return count;
788 } else if (count > BDRV_REQUEST_MAX_BYTES) {
789 printf("length cannot exceed %" PRIu64 ", given %s\n",
790 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
791 return -EINVAL;
792 }
793
794 if (!Pflag && (lflag || sflag)) {
795 qemuio_command_usage(&read_cmd);
796 return -EINVAL;
797 }
798
799 if (!lflag) {
800 pattern_count = count - pattern_offset;
801 }
802
803 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
804 printf("pattern verification range exceeds end of read data\n");
805 return -EINVAL;
806 }
807
808 if (bflag) {
809 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
810 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
811 offset);
812 return -EINVAL;
813 }
814 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
815 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
816 count);
817 return -EINVAL;
818 }
819 if (flags & BDRV_REQ_REGISTERED_BUF) {
820 printf("I/O buffer registration is not supported when reading "
821 "from vmstate\n");
822 return -EINVAL;
823 }
824 }
825
826 buf = qemu_io_alloc(blk, count, 0xab, flags & BDRV_REQ_REGISTERED_BUF);
827
828 clock_gettime(CLOCK_MONOTONIC, &t1);
829 if (bflag) {
830 ret = do_load_vmstate(blk, buf, offset, count, &total);
831 } else {
832 ret = do_pread(blk, buf, offset, count, flags, &total);
833 }
834 clock_gettime(CLOCK_MONOTONIC, &t2);
835
836 if (ret < 0) {
837 printf("read failed: %s\n", strerror(-ret));
838 goto out;
839 }
840 cnt = ret;
841
842 ret = 0;
843
844 if (Pflag) {
845 void *cmp_buf = g_malloc(pattern_count);
846 memset(cmp_buf, pattern, pattern_count);
847 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
848 printf("Pattern verification failed at offset %"
849 PRId64 ", %"PRId64" bytes\n",
850 offset + pattern_offset, pattern_count);
851 ret = -EINVAL;
852 }
853 g_free(cmp_buf);
854 }
855
856 if (qflag) {
857 goto out;
858 }
859
860 if (vflag) {
861 dump_buffer(buf, offset, count);
862 }
863
864
865 t2 = tsub(t2, t1);
866 print_report("read", &t2, offset, count, total, cnt, Cflag);
867
868out:
869 qemu_io_free(blk, buf, count, flags & BDRV_REQ_REGISTERED_BUF);
870 return ret;
871}
872
873static void readv_help(void)
874{
875 printf(
876"\n"
877" reads a range of bytes from the given offset into multiple buffers\n"
878"\n"
879" Example:\n"
880" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
881"\n"
882" Reads a segment of the currently open file, optionally dumping it to the\n"
883" standard output stream (with -v option) for subsequent inspection.\n"
884" Uses multiple iovec buffers if more than one byte range is specified.\n"
885" -C, -- report statistics in a machine parsable format\n"
886" -P, -- use a pattern to verify read data\n"
887" -q, -- quiet mode, do not show I/O statistics\n"
888" -r, -- register I/O buffer\n"
889" -v, -- dump buffer to standard output\n"
890"\n");
891}
892
893static int readv_f(BlockBackend *blk, int argc, char **argv);
894
895static const cmdinfo_t readv_cmd = {
896 .name = "readv",
897 .cfunc = readv_f,
898 .argmin = 2,
899 .argmax = -1,
900 .args = "[-Cqrv] [-P pattern] off len [len..]",
901 .oneline = "reads a number of bytes at a specified offset",
902 .help = readv_help,
903};
904
905static int readv_f(BlockBackend *blk, int argc, char **argv)
906{
907 struct timespec t1, t2;
908 bool Cflag = false, qflag = false, vflag = false;
909 int c, cnt, ret;
910 char *buf;
911 int64_t offset;
912
913 int total = 0;
914 int nr_iov;
915 QEMUIOVector qiov;
916 int pattern = 0;
917 bool Pflag = false;
918 BdrvRequestFlags flags = 0;
919
920 while ((c = getopt(argc, argv, "CP:qrv")) != -1) {
921 switch (c) {
922 case 'C':
923 Cflag = true;
924 break;
925 case 'P':
926 Pflag = true;
927 pattern = parse_pattern(optarg);
928 if (pattern < 0) {
929 return -EINVAL;
930 }
931 break;
932 case 'q':
933 qflag = true;
934 break;
935 case 'r':
936 flags |= BDRV_REQ_REGISTERED_BUF;
937 break;
938 case 'v':
939 vflag = true;
940 break;
941 default:
942 qemuio_command_usage(&readv_cmd);
943 return -EINVAL;
944 }
945 }
946
947 if (optind > argc - 2) {
948 qemuio_command_usage(&readv_cmd);
949 return -EINVAL;
950 }
951
952
953 offset = cvtnum(argv[optind]);
954 if (offset < 0) {
955 print_cvtnum_err(offset, argv[optind]);
956 return offset;
957 }
958 optind++;
959
960 nr_iov = argc - optind;
961 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab,
962 flags & BDRV_REQ_REGISTERED_BUF);
963 if (buf == NULL) {
964 return -EINVAL;
965 }
966
967 clock_gettime(CLOCK_MONOTONIC, &t1);
968 ret = do_aio_readv(blk, &qiov, offset, flags, &total);
969 clock_gettime(CLOCK_MONOTONIC, &t2);
970
971 if (ret < 0) {
972 printf("readv failed: %s\n", strerror(-ret));
973 goto out;
974 }
975 cnt = ret;
976
977 ret = 0;
978
979 if (Pflag) {
980 void *cmp_buf = g_malloc(qiov.size);
981 memset(cmp_buf, pattern, qiov.size);
982 if (memcmp(buf, cmp_buf, qiov.size)) {
983 printf("Pattern verification failed at offset %"
984 PRId64 ", %zu bytes\n", offset, qiov.size);
985 ret = -EINVAL;
986 }
987 g_free(cmp_buf);
988 }
989
990 if (qflag) {
991 goto out;
992 }
993
994 if (vflag) {
995 dump_buffer(buf, offset, qiov.size);
996 }
997
998
999 t2 = tsub(t2, t1);
1000 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
1001
1002out:
1003 qemu_io_free(blk, buf, qiov.size, flags & BDRV_REQ_REGISTERED_BUF);
1004 qemu_iovec_destroy(&qiov);
1005 return ret;
1006}
1007
1008static void write_help(void)
1009{
1010 printf(
1011"\n"
1012" writes a range of bytes from the given offset\n"
1013"\n"
1014" Example:\n"
1015" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
1016"\n"
1017" Writes into a segment of the currently open file, using a buffer\n"
1018" filled with a set pattern (0xcdcdcdcd).\n"
1019" -b, -- write to the VM state rather than the virtual disk\n"
1020" -c, -- write compressed data with blk_write_compressed\n"
1021" -C, -- report statistics in a machine parsable format\n"
1022" -f, -- use Force Unit Access semantics\n"
1023" -n, -- with -z, don't allow slow fallback\n"
1024" -p, -- ignored for backwards compatibility\n"
1025" -P, -- use different pattern to fill file\n"
1026" -q, -- quiet mode, do not show I/O statistics\n"
1027" -r, -- register I/O buffer\n"
1028" -s, -- use a pattern file to fill the write buffer\n"
1029" -u, -- with -z, allow unmapping\n"
1030" -z, -- write zeroes using blk_pwrite_zeroes\n"
1031"\n");
1032}
1033
1034static int write_f(BlockBackend *blk, int argc, char **argv);
1035
1036static const cmdinfo_t write_cmd = {
1037 .name = "write",
1038 .altname = "w",
1039 .cfunc = write_f,
1040 .perm = BLK_PERM_WRITE,
1041 .argmin = 2,
1042 .argmax = -1,
1043 .args = "[-bcCfnqruz] [-P pattern | -s source_file] off len",
1044 .oneline = "writes a number of bytes at a specified offset",
1045 .help = write_help,
1046};
1047
1048static int write_f(BlockBackend *blk, int argc, char **argv)
1049{
1050 struct timespec t1, t2;
1051 bool Cflag = false, qflag = false, bflag = false;
1052 bool Pflag = false, zflag = false, cflag = false, sflag = false;
1053 BdrvRequestFlags flags = 0;
1054 int c, cnt, ret;
1055 char *buf = NULL;
1056 int64_t offset;
1057 int64_t count;
1058
1059 int64_t total = 0;
1060 int pattern = 0xcd;
1061 const char *file_name = NULL;
1062
1063 while ((c = getopt(argc, argv, "bcCfnpP:qrs:uz")) != -1) {
1064 switch (c) {
1065 case 'b':
1066 bflag = true;
1067 break;
1068 case 'c':
1069 cflag = true;
1070 break;
1071 case 'C':
1072 Cflag = true;
1073 break;
1074 case 'f':
1075 flags |= BDRV_REQ_FUA;
1076 break;
1077 case 'n':
1078 flags |= BDRV_REQ_NO_FALLBACK;
1079 break;
1080 case 'p':
1081
1082 break;
1083 case 'P':
1084 Pflag = true;
1085 pattern = parse_pattern(optarg);
1086 if (pattern < 0) {
1087 return -EINVAL;
1088 }
1089 break;
1090 case 'q':
1091 qflag = true;
1092 break;
1093 case 'r':
1094 flags |= BDRV_REQ_REGISTERED_BUF;
1095 break;
1096 case 's':
1097 sflag = true;
1098 file_name = optarg;
1099 break;
1100 case 'u':
1101 flags |= BDRV_REQ_MAY_UNMAP;
1102 break;
1103 case 'z':
1104 zflag = true;
1105 break;
1106 default:
1107 qemuio_command_usage(&write_cmd);
1108 return -EINVAL;
1109 }
1110 }
1111
1112 if (optind != argc - 2) {
1113 qemuio_command_usage(&write_cmd);
1114 return -EINVAL;
1115 }
1116
1117 if (bflag && zflag) {
1118 printf("-b and -z cannot be specified at the same time\n");
1119 return -EINVAL;
1120 }
1121
1122 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
1123 printf("-f and -b or -c cannot be specified at the same time\n");
1124 return -EINVAL;
1125 }
1126
1127 if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
1128 printf("-n requires -z to be specified\n");
1129 return -EINVAL;
1130 }
1131
1132 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
1133 printf("-u requires -z to be specified\n");
1134 return -EINVAL;
1135 }
1136
1137 if (zflag + Pflag + sflag > 1) {
1138 printf("Only one of -z, -P, and -s "
1139 "can be specified at the same time\n");
1140 return -EINVAL;
1141 }
1142
1143 offset = cvtnum(argv[optind]);
1144 if (offset < 0) {
1145 print_cvtnum_err(offset, argv[optind]);
1146 return offset;
1147 }
1148
1149 optind++;
1150 count = cvtnum(argv[optind]);
1151 if (count < 0) {
1152 print_cvtnum_err(count, argv[optind]);
1153 return count;
1154 } else if (count > BDRV_REQUEST_MAX_BYTES &&
1155 !(flags & BDRV_REQ_NO_FALLBACK)) {
1156 printf("length cannot exceed %" PRIu64 " without -n, given %s\n",
1157 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
1158 return -EINVAL;
1159 }
1160
1161 if (bflag || cflag) {
1162 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
1163 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
1164 offset);
1165 return -EINVAL;
1166 }
1167
1168 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
1169 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
1170 count);
1171 return -EINVAL;
1172 }
1173 }
1174
1175 if (zflag) {
1176 if (flags & BDRV_REQ_REGISTERED_BUF) {
1177 printf("cannot combine zero write with registered I/O buffer\n");
1178 return -EINVAL;
1179 }
1180 } else {
1181 if (sflag) {
1182 buf = qemu_io_alloc_from_file(blk, count, file_name,
1183 flags & BDRV_REQ_REGISTERED_BUF);
1184 if (!buf) {
1185 return -EINVAL;
1186 }
1187 } else {
1188 buf = qemu_io_alloc(blk, count, pattern,
1189 flags & BDRV_REQ_REGISTERED_BUF);
1190 }
1191 }
1192
1193 clock_gettime(CLOCK_MONOTONIC, &t1);
1194 if (bflag) {
1195 ret = do_save_vmstate(blk, buf, offset, count, &total);
1196 } else if (zflag) {
1197 ret = do_pwrite_zeroes(blk, offset, count, flags, &total);
1198 } else if (cflag) {
1199 ret = do_write_compressed(blk, buf, offset, count, &total);
1200 } else {
1201 ret = do_pwrite(blk, buf, offset, count, flags, &total);
1202 }
1203 clock_gettime(CLOCK_MONOTONIC, &t2);
1204
1205 if (ret < 0) {
1206 printf("write failed: %s\n", strerror(-ret));
1207 goto out;
1208 }
1209 cnt = ret;
1210
1211 ret = 0;
1212
1213 if (qflag) {
1214 goto out;
1215 }
1216
1217
1218 t2 = tsub(t2, t1);
1219 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1220
1221out:
1222 if (!zflag) {
1223 qemu_io_free(blk, buf, count, flags & BDRV_REQ_REGISTERED_BUF);
1224 }
1225 return ret;
1226}
1227
1228static void
1229writev_help(void)
1230{
1231 printf(
1232"\n"
1233" writes a range of bytes from the given offset source from multiple buffers\n"
1234"\n"
1235" Example:\n"
1236" 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1237"\n"
1238" Writes into a segment of the currently open file, using a buffer\n"
1239" filled with a set pattern (0xcdcdcdcd).\n"
1240" -C, -- report statistics in a machine parsable format\n"
1241" -f, -- use Force Unit Access semantics\n"
1242" -P, -- use different pattern to fill file\n"
1243" -q, -- quiet mode, do not show I/O statistics\n"
1244" -r, -- register I/O buffer\n"
1245"\n");
1246}
1247
1248static int writev_f(BlockBackend *blk, int argc, char **argv);
1249
1250static const cmdinfo_t writev_cmd = {
1251 .name = "writev",
1252 .cfunc = writev_f,
1253 .perm = BLK_PERM_WRITE,
1254 .argmin = 2,
1255 .argmax = -1,
1256 .args = "[-Cfqr] [-P pattern] off len [len..]",
1257 .oneline = "writes a number of bytes at a specified offset",
1258 .help = writev_help,
1259};
1260
1261static int writev_f(BlockBackend *blk, int argc, char **argv)
1262{
1263 struct timespec t1, t2;
1264 bool Cflag = false, qflag = false;
1265 BdrvRequestFlags flags = 0;
1266 int c, cnt, ret;
1267 char *buf;
1268 int64_t offset;
1269
1270 int total = 0;
1271 int nr_iov;
1272 int pattern = 0xcd;
1273 QEMUIOVector qiov;
1274
1275 while ((c = getopt(argc, argv, "CfP:qr")) != -1) {
1276 switch (c) {
1277 case 'C':
1278 Cflag = true;
1279 break;
1280 case 'f':
1281 flags |= BDRV_REQ_FUA;
1282 break;
1283 case 'q':
1284 qflag = true;
1285 break;
1286 case 'r':
1287 flags |= BDRV_REQ_REGISTERED_BUF;
1288 break;
1289 case 'P':
1290 pattern = parse_pattern(optarg);
1291 if (pattern < 0) {
1292 return -EINVAL;
1293 }
1294 break;
1295 default:
1296 qemuio_command_usage(&writev_cmd);
1297 return -EINVAL;
1298 }
1299 }
1300
1301 if (optind > argc - 2) {
1302 qemuio_command_usage(&writev_cmd);
1303 return -EINVAL;
1304 }
1305
1306 offset = cvtnum(argv[optind]);
1307 if (offset < 0) {
1308 print_cvtnum_err(offset, argv[optind]);
1309 return offset;
1310 }
1311 optind++;
1312
1313 nr_iov = argc - optind;
1314 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern,
1315 flags & BDRV_REQ_REGISTERED_BUF);
1316 if (buf == NULL) {
1317 return -EINVAL;
1318 }
1319
1320 clock_gettime(CLOCK_MONOTONIC, &t1);
1321 ret = do_aio_writev(blk, &qiov, offset, flags, &total);
1322 clock_gettime(CLOCK_MONOTONIC, &t2);
1323
1324 if (ret < 0) {
1325 printf("writev failed: %s\n", strerror(-ret));
1326 goto out;
1327 }
1328 cnt = ret;
1329
1330 ret = 0;
1331
1332 if (qflag) {
1333 goto out;
1334 }
1335
1336
1337 t2 = tsub(t2, t1);
1338 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1339out:
1340 qemu_io_free(blk, buf, qiov.size, flags & BDRV_REQ_REGISTERED_BUF);
1341 qemu_iovec_destroy(&qiov);
1342 return ret;
1343}
1344
1345struct aio_ctx {
1346 BlockBackend *blk;
1347 QEMUIOVector qiov;
1348 int64_t offset;
1349 char *buf;
1350 bool qflag;
1351 bool vflag;
1352 bool Cflag;
1353 bool Pflag;
1354 bool zflag;
1355 BlockAcctCookie acct;
1356 int pattern;
1357 BdrvRequestFlags flags;
1358 struct timespec t1;
1359};
1360
1361static void aio_write_done(void *opaque, int ret)
1362{
1363 struct aio_ctx *ctx = opaque;
1364 struct timespec t2;
1365
1366 clock_gettime(CLOCK_MONOTONIC, &t2);
1367
1368
1369 if (ret < 0) {
1370 printf("aio_write failed: %s\n", strerror(-ret));
1371 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
1372 goto out;
1373 }
1374
1375 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
1376
1377 if (ctx->qflag) {
1378 goto out;
1379 }
1380
1381
1382 t2 = tsub(t2, ctx->t1);
1383 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1384 ctx->qiov.size, 1, ctx->Cflag);
1385out:
1386 if (!ctx->zflag) {
1387 qemu_io_free(ctx->blk, ctx->buf, ctx->qiov.size,
1388 ctx->flags & BDRV_REQ_REGISTERED_BUF);
1389 qemu_iovec_destroy(&ctx->qiov);
1390 }
1391 g_free(ctx);
1392}
1393
1394static void aio_read_done(void *opaque, int ret)
1395{
1396 struct aio_ctx *ctx = opaque;
1397 struct timespec t2;
1398
1399 clock_gettime(CLOCK_MONOTONIC, &t2);
1400
1401 if (ret < 0) {
1402 printf("readv failed: %s\n", strerror(-ret));
1403 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
1404 goto out;
1405 }
1406
1407 if (ctx->Pflag) {
1408 void *cmp_buf = g_malloc(ctx->qiov.size);
1409
1410 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1411 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1412 printf("Pattern verification failed at offset %"
1413 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
1414 }
1415 g_free(cmp_buf);
1416 }
1417
1418 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
1419
1420 if (ctx->qflag) {
1421 goto out;
1422 }
1423
1424 if (ctx->vflag) {
1425 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1426 }
1427
1428
1429 t2 = tsub(t2, ctx->t1);
1430 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1431 ctx->qiov.size, 1, ctx->Cflag);
1432out:
1433 qemu_io_free(ctx->blk, ctx->buf, ctx->qiov.size,
1434 ctx->flags & BDRV_REQ_REGISTERED_BUF);
1435 qemu_iovec_destroy(&ctx->qiov);
1436 g_free(ctx);
1437}
1438
1439static void aio_read_help(void)
1440{
1441 printf(
1442"\n"
1443" asynchronously reads a range of bytes from the given offset\n"
1444"\n"
1445" Example:\n"
1446" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1447"\n"
1448" Reads a segment of the currently open file, optionally dumping it to the\n"
1449" standard output stream (with -v option) for subsequent inspection.\n"
1450" The read is performed asynchronously and the aio_flush command must be\n"
1451" used to ensure all outstanding aio requests have been completed.\n"
1452" Note that due to its asynchronous nature, this command will be\n"
1453" considered successful once the request is submitted, independently\n"
1454" of potential I/O errors or pattern mismatches.\n"
1455" -C, -- report statistics in a machine parsable format\n"
1456" -i, -- treat request as invalid, for exercising stats\n"
1457" -P, -- use a pattern to verify read data\n"
1458" -q, -- quiet mode, do not show I/O statistics\n"
1459" -r, -- register I/O buffer\n"
1460" -v, -- dump buffer to standard output\n"
1461"\n");
1462}
1463
1464static int aio_read_f(BlockBackend *blk, int argc, char **argv);
1465
1466static const cmdinfo_t aio_read_cmd = {
1467 .name = "aio_read",
1468 .cfunc = aio_read_f,
1469 .argmin = 2,
1470 .argmax = -1,
1471 .args = "[-Ciqrv] [-P pattern] off len [len..]",
1472 .oneline = "asynchronously reads a number of bytes",
1473 .help = aio_read_help,
1474};
1475
1476static int aio_read_f(BlockBackend *blk, int argc, char **argv)
1477{
1478 int nr_iov, c;
1479 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1480
1481 ctx->blk = blk;
1482 while ((c = getopt(argc, argv, "CiP:qrv")) != -1) {
1483 switch (c) {
1484 case 'C':
1485 ctx->Cflag = true;
1486 break;
1487 case 'P':
1488 ctx->Pflag = true;
1489 ctx->pattern = parse_pattern(optarg);
1490 if (ctx->pattern < 0) {
1491 g_free(ctx);
1492 return -EINVAL;
1493 }
1494 break;
1495 case 'i':
1496 printf("injecting invalid read request\n");
1497 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1498 g_free(ctx);
1499 return 0;
1500 case 'q':
1501 ctx->qflag = true;
1502 break;
1503 case 'r':
1504 ctx->flags |= BDRV_REQ_REGISTERED_BUF;
1505 break;
1506 case 'v':
1507 ctx->vflag = true;
1508 break;
1509 default:
1510 g_free(ctx);
1511 qemuio_command_usage(&aio_read_cmd);
1512 return -EINVAL;
1513 }
1514 }
1515
1516 if (optind > argc - 2) {
1517 g_free(ctx);
1518 qemuio_command_usage(&aio_read_cmd);
1519 return -EINVAL;
1520 }
1521
1522 ctx->offset = cvtnum(argv[optind]);
1523 if (ctx->offset < 0) {
1524 int ret = ctx->offset;
1525 print_cvtnum_err(ret, argv[optind]);
1526 g_free(ctx);
1527 return ret;
1528 }
1529 optind++;
1530
1531 nr_iov = argc - optind;
1532 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab,
1533 ctx->flags & BDRV_REQ_REGISTERED_BUF);
1534 if (ctx->buf == NULL) {
1535 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1536 g_free(ctx);
1537 return -EINVAL;
1538 }
1539
1540 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
1541 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1542 BLOCK_ACCT_READ);
1543 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, ctx->flags, aio_read_done,
1544 ctx);
1545 return 0;
1546}
1547
1548static void aio_write_help(void)
1549{
1550 printf(
1551"\n"
1552" asynchronously writes a range of bytes from the given offset source\n"
1553" from multiple buffers\n"
1554"\n"
1555" Example:\n"
1556" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1557"\n"
1558" Writes into a segment of the currently open file, using a buffer\n"
1559" filled with a set pattern (0xcdcdcdcd).\n"
1560" The write is performed asynchronously and the aio_flush command must be\n"
1561" used to ensure all outstanding aio requests have been completed.\n"
1562" Note that due to its asynchronous nature, this command will be\n"
1563" considered successful once the request is submitted, independently\n"
1564" of potential I/O errors or pattern mismatches.\n"
1565" -C, -- report statistics in a machine parsable format\n"
1566" -f, -- use Force Unit Access semantics\n"
1567" -i, -- treat request as invalid, for exercising stats\n"
1568" -P, -- use different pattern to fill file\n"
1569" -q, -- quiet mode, do not show I/O statistics\n"
1570" -r, -- register I/O buffer\n"
1571" -u, -- with -z, allow unmapping\n"
1572" -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
1573"\n");
1574}
1575
1576static int aio_write_f(BlockBackend *blk, int argc, char **argv);
1577
1578static const cmdinfo_t aio_write_cmd = {
1579 .name = "aio_write",
1580 .cfunc = aio_write_f,
1581 .perm = BLK_PERM_WRITE,
1582 .argmin = 2,
1583 .argmax = -1,
1584 .args = "[-Cfiqruz] [-P pattern] off len [len..]",
1585 .oneline = "asynchronously writes a number of bytes",
1586 .help = aio_write_help,
1587};
1588
1589static int aio_write_f(BlockBackend *blk, int argc, char **argv)
1590{
1591 int nr_iov, c;
1592 int pattern = 0xcd;
1593 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1594
1595 ctx->blk = blk;
1596 while ((c = getopt(argc, argv, "CfiP:qruz")) != -1) {
1597 switch (c) {
1598 case 'C':
1599 ctx->Cflag = true;
1600 break;
1601 case 'f':
1602 ctx->flags |= BDRV_REQ_FUA;
1603 break;
1604 case 'q':
1605 ctx->qflag = true;
1606 break;
1607 case 'r':
1608 ctx->flags |= BDRV_REQ_REGISTERED_BUF;
1609 break;
1610 case 'u':
1611 ctx->flags |= BDRV_REQ_MAY_UNMAP;
1612 break;
1613 case 'P':
1614 pattern = parse_pattern(optarg);
1615 if (pattern < 0) {
1616 g_free(ctx);
1617 return -EINVAL;
1618 }
1619 break;
1620 case 'i':
1621 printf("injecting invalid write request\n");
1622 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1623 g_free(ctx);
1624 return 0;
1625 case 'z':
1626 ctx->zflag = true;
1627 break;
1628 default:
1629 g_free(ctx);
1630 qemuio_command_usage(&aio_write_cmd);
1631 return -EINVAL;
1632 }
1633 }
1634
1635 if (optind > argc - 2) {
1636 g_free(ctx);
1637 qemuio_command_usage(&aio_write_cmd);
1638 return -EINVAL;
1639 }
1640
1641 if (ctx->zflag && optind != argc - 2) {
1642 printf("-z supports only a single length parameter\n");
1643 g_free(ctx);
1644 return -EINVAL;
1645 }
1646
1647 if ((ctx->flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
1648 printf("-u requires -z to be specified\n");
1649 g_free(ctx);
1650 return -EINVAL;
1651 }
1652
1653 if (ctx->zflag && ctx->Pflag) {
1654 printf("-z and -P cannot be specified at the same time\n");
1655 g_free(ctx);
1656 return -EINVAL;
1657 }
1658
1659 if (ctx->zflag && (ctx->flags & BDRV_REQ_REGISTERED_BUF)) {
1660 printf("cannot combine zero write with registered I/O buffer\n");
1661 g_free(ctx);
1662 return -EINVAL;
1663 }
1664
1665 ctx->offset = cvtnum(argv[optind]);
1666 if (ctx->offset < 0) {
1667 int ret = ctx->offset;
1668 print_cvtnum_err(ret, argv[optind]);
1669 g_free(ctx);
1670 return ret;
1671 }
1672 optind++;
1673
1674 if (ctx->zflag) {
1675 int64_t count = cvtnum(argv[optind]);
1676 if (count < 0) {
1677 print_cvtnum_err(count, argv[optind]);
1678 g_free(ctx);
1679 return count;
1680 }
1681
1682 ctx->qiov.size = count;
1683 blk_aio_pwrite_zeroes(blk, ctx->offset, count, ctx->flags,
1684 aio_write_done, ctx);
1685 } else {
1686 nr_iov = argc - optind;
1687 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
1688 pattern, ctx->flags & BDRV_REQ_REGISTERED_BUF);
1689 if (ctx->buf == NULL) {
1690 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1691 g_free(ctx);
1692 return -EINVAL;
1693 }
1694
1695 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
1696 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1697 BLOCK_ACCT_WRITE);
1698
1699 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, ctx->flags,
1700 aio_write_done, ctx);
1701 }
1702
1703 return 0;
1704}
1705
1706static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
1707{
1708 BlockAcctCookie cookie;
1709 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
1710 blk_drain_all();
1711 block_acct_done(blk_get_stats(blk), &cookie);
1712 return 0;
1713}
1714
1715static const cmdinfo_t aio_flush_cmd = {
1716 .name = "aio_flush",
1717 .cfunc = aio_flush_f,
1718 .oneline = "completes all outstanding aio requests"
1719};
1720
1721static int flush_f(BlockBackend *blk, int argc, char **argv)
1722{
1723 return blk_flush(blk);
1724}
1725
1726static const cmdinfo_t flush_cmd = {
1727 .name = "flush",
1728 .altname = "f",
1729 .cfunc = flush_f,
1730 .oneline = "flush all in-core file state to disk",
1731};
1732
1733static inline int64_t tosector(int64_t bytes)
1734{
1735 return bytes >> BDRV_SECTOR_BITS;
1736}
1737
1738static int zone_report_f(BlockBackend *blk, int argc, char **argv)
1739{
1740 int ret;
1741 int64_t offset;
1742 int64_t val;
1743 unsigned int nr_zones;
1744
1745 ++optind;
1746 offset = cvtnum(argv[optind]);
1747 if (offset < 0) {
1748 print_cvtnum_err(offset, argv[optind]);
1749 return offset;
1750 }
1751 ++optind;
1752 val = cvtnum(argv[optind]);
1753 if (val < 0) {
1754 print_cvtnum_err(val, argv[optind]);
1755 return val;
1756 }
1757 if (val > UINT_MAX) {
1758 printf("Number of zones must be less than 2^32\n");
1759 return -ERANGE;
1760 }
1761 nr_zones = val;
1762
1763 g_autofree BlockZoneDescriptor *zones = NULL;
1764 zones = g_new(BlockZoneDescriptor, nr_zones);
1765 ret = blk_zone_report(blk, offset, &nr_zones, zones);
1766 if (ret < 0) {
1767 printf("zone report failed: %s\n", strerror(-ret));
1768 } else {
1769 for (int i = 0; i < nr_zones; ++i) {
1770 printf("start: 0x%" PRIx64 ", len 0x%" PRIx64 ", "
1771 "cap"" 0x%" PRIx64 ", wptr 0x%" PRIx64 ", "
1772 "zcond:%u, [type: %u]\n",
1773 tosector(zones[i].start), tosector(zones[i].length),
1774 tosector(zones[i].cap), tosector(zones[i].wp),
1775 zones[i].state, zones[i].type);
1776 }
1777 }
1778 return ret;
1779}
1780
1781static const cmdinfo_t zone_report_cmd = {
1782 .name = "zone_report",
1783 .altname = "zrp",
1784 .cfunc = zone_report_f,
1785 .argmin = 2,
1786 .argmax = 2,
1787 .args = "offset number",
1788 .oneline = "report zone information",
1789};
1790
1791static int zone_open_f(BlockBackend *blk, int argc, char **argv)
1792{
1793 int ret;
1794 int64_t offset, len;
1795 ++optind;
1796 offset = cvtnum(argv[optind]);
1797 if (offset < 0) {
1798 print_cvtnum_err(offset, argv[optind]);
1799 return offset;
1800 }
1801 ++optind;
1802 len = cvtnum(argv[optind]);
1803 if (len < 0) {
1804 print_cvtnum_err(len, argv[optind]);
1805 return len;
1806 }
1807 ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len);
1808 if (ret < 0) {
1809 printf("zone open failed: %s\n", strerror(-ret));
1810 }
1811 return ret;
1812}
1813
1814static const cmdinfo_t zone_open_cmd = {
1815 .name = "zone_open",
1816 .altname = "zo",
1817 .cfunc = zone_open_f,
1818 .argmin = 2,
1819 .argmax = 2,
1820 .args = "offset len",
1821 .oneline = "explicit open a range of zones in zone block device",
1822};
1823
1824static int zone_close_f(BlockBackend *blk, int argc, char **argv)
1825{
1826 int ret;
1827 int64_t offset, len;
1828 ++optind;
1829 offset = cvtnum(argv[optind]);
1830 if (offset < 0) {
1831 print_cvtnum_err(offset, argv[optind]);
1832 return offset;
1833 }
1834 ++optind;
1835 len = cvtnum(argv[optind]);
1836 if (len < 0) {
1837 print_cvtnum_err(len, argv[optind]);
1838 return len;
1839 }
1840 ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len);
1841 if (ret < 0) {
1842 printf("zone close failed: %s\n", strerror(-ret));
1843 }
1844 return ret;
1845}
1846
1847static const cmdinfo_t zone_close_cmd = {
1848 .name = "zone_close",
1849 .altname = "zc",
1850 .cfunc = zone_close_f,
1851 .argmin = 2,
1852 .argmax = 2,
1853 .args = "offset len",
1854 .oneline = "close a range of zones in zone block device",
1855};
1856
1857static int zone_finish_f(BlockBackend *blk, int argc, char **argv)
1858{
1859 int ret;
1860 int64_t offset, len;
1861 ++optind;
1862 offset = cvtnum(argv[optind]);
1863 if (offset < 0) {
1864 print_cvtnum_err(offset, argv[optind]);
1865 return offset;
1866 }
1867 ++optind;
1868 len = cvtnum(argv[optind]);
1869 if (len < 0) {
1870 print_cvtnum_err(len, argv[optind]);
1871 return len;
1872 }
1873 ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len);
1874 if (ret < 0) {
1875 printf("zone finish failed: %s\n", strerror(-ret));
1876 }
1877 return ret;
1878}
1879
1880static const cmdinfo_t zone_finish_cmd = {
1881 .name = "zone_finish",
1882 .altname = "zf",
1883 .cfunc = zone_finish_f,
1884 .argmin = 2,
1885 .argmax = 2,
1886 .args = "offset len",
1887 .oneline = "finish a range of zones in zone block device",
1888};
1889
1890static int zone_reset_f(BlockBackend *blk, int argc, char **argv)
1891{
1892 int ret;
1893 int64_t offset, len;
1894 ++optind;
1895 offset = cvtnum(argv[optind]);
1896 if (offset < 0) {
1897 print_cvtnum_err(offset, argv[optind]);
1898 return offset;
1899 }
1900 ++optind;
1901 len = cvtnum(argv[optind]);
1902 if (len < 0) {
1903 print_cvtnum_err(len, argv[optind]);
1904 return len;
1905 }
1906 ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len);
1907 if (ret < 0) {
1908 printf("zone reset failed: %s\n", strerror(-ret));
1909 }
1910 return ret;
1911}
1912
1913static const cmdinfo_t zone_reset_cmd = {
1914 .name = "zone_reset",
1915 .altname = "zrs",
1916 .cfunc = zone_reset_f,
1917 .argmin = 2,
1918 .argmax = 2,
1919 .args = "offset len",
1920 .oneline = "reset a zone write pointer in zone block device",
1921};
1922
1923static int do_aio_zone_append(BlockBackend *blk, QEMUIOVector *qiov,
1924 int64_t *offset, int flags, int *total)
1925{
1926 int async_ret = NOT_DONE;
1927
1928 blk_aio_zone_append(blk, offset, qiov, flags, aio_rw_done, &async_ret);
1929 while (async_ret == NOT_DONE) {
1930 main_loop_wait(false);
1931 }
1932
1933 *total = qiov->size;
1934 return async_ret < 0 ? async_ret : 1;
1935}
1936
1937static int zone_append_f(BlockBackend *blk, int argc, char **argv)
1938{
1939 int ret;
1940 bool pflag = false;
1941 int flags = 0;
1942 int total = 0;
1943 int64_t offset;
1944 char *buf;
1945 int c, nr_iov;
1946 int pattern = 0xcd;
1947 QEMUIOVector qiov;
1948
1949 if (optind > argc - 3) {
1950 return -EINVAL;
1951 }
1952
1953 if ((c = getopt(argc, argv, "p")) != -1) {
1954 pflag = true;
1955 }
1956
1957 offset = cvtnum(argv[optind]);
1958 if (offset < 0) {
1959 print_cvtnum_err(offset, argv[optind]);
1960 return offset;
1961 }
1962 optind++;
1963 nr_iov = argc - optind;
1964 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern,
1965 flags & BDRV_REQ_REGISTERED_BUF);
1966 if (buf == NULL) {
1967 return -EINVAL;
1968 }
1969 ret = do_aio_zone_append(blk, &qiov, &offset, flags, &total);
1970 if (ret < 0) {
1971 printf("zone append failed: %s\n", strerror(-ret));
1972 goto out;
1973 }
1974
1975 if (pflag) {
1976 printf("After zap done, the append sector is 0x%" PRIx64 "\n",
1977 tosector(offset));
1978 }
1979
1980out:
1981 qemu_io_free(blk, buf, qiov.size,
1982 flags & BDRV_REQ_REGISTERED_BUF);
1983 qemu_iovec_destroy(&qiov);
1984 return ret;
1985}
1986
1987static const cmdinfo_t zone_append_cmd = {
1988 .name = "zone_append",
1989 .altname = "zap",
1990 .cfunc = zone_append_f,
1991 .argmin = 3,
1992 .argmax = 4,
1993 .args = "offset len [len..]",
1994 .oneline = "append write a number of bytes at a specified offset",
1995};
1996
1997static int truncate_f(BlockBackend *blk, int argc, char **argv);
1998static const cmdinfo_t truncate_cmd = {
1999 .name = "truncate",
2000 .altname = "t",
2001 .cfunc = truncate_f,
2002 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
2003 .argmin = 1,
2004 .argmax = 3,
2005 .args = "[-m prealloc_mode] off",
2006 .oneline = "truncates the current file at the given offset",
2007};
2008
2009static int truncate_f(BlockBackend *blk, int argc, char **argv)
2010{
2011 Error *local_err = NULL;
2012 int64_t offset;
2013 int c, ret;
2014 PreallocMode prealloc = PREALLOC_MODE_OFF;
2015
2016 while ((c = getopt(argc, argv, "m:")) != -1) {
2017 switch (c) {
2018 case 'm':
2019 prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
2020 PREALLOC_MODE__MAX, NULL);
2021 if (prealloc == PREALLOC_MODE__MAX) {
2022 error_report("Invalid preallocation mode '%s'", optarg);
2023 return -EINVAL;
2024 }
2025 break;
2026 default:
2027 qemuio_command_usage(&truncate_cmd);
2028 return -EINVAL;
2029 }
2030 }
2031
2032 offset = cvtnum(argv[optind]);
2033 if (offset < 0) {
2034 print_cvtnum_err(offset, argv[1]);
2035 return offset;
2036 }
2037
2038
2039
2040
2041
2042
2043 ret = blk_truncate(blk, offset, false, prealloc, 0, &local_err);
2044 if (ret < 0) {
2045 error_report_err(local_err);
2046 return ret;
2047 }
2048
2049 return 0;
2050}
2051
2052static int length_f(BlockBackend *blk, int argc, char **argv)
2053{
2054 int64_t size;
2055 char s1[64];
2056
2057 size = blk_getlength(blk);
2058 if (size < 0) {
2059 printf("getlength: %s\n", strerror(-size));
2060 return size;
2061 }
2062
2063 cvtstr(size, s1, sizeof(s1));
2064 printf("%s\n", s1);
2065 return 0;
2066}
2067
2068
2069static const cmdinfo_t length_cmd = {
2070 .name = "length",
2071 .altname = "l",
2072 .cfunc = length_f,
2073 .oneline = "gets the length of the current file",
2074};
2075
2076
2077static int info_f(BlockBackend *blk, int argc, char **argv)
2078{
2079 BlockDriverState *bs = blk_bs(blk);
2080 BlockDriverInfo bdi;
2081 ImageInfoSpecific *spec_info;
2082 Error *local_err = NULL;
2083 char s1[64], s2[64];
2084 int ret;
2085
2086 GLOBAL_STATE_CODE();
2087 GRAPH_RDLOCK_GUARD_MAINLOOP();
2088
2089 if (bs->drv && bs->drv->format_name) {
2090 printf("format name: %s\n", bs->drv->format_name);
2091 }
2092 if (bs->drv && bs->drv->protocol_name) {
2093 printf("format name: %s\n", bs->drv->protocol_name);
2094 }
2095
2096 ret = bdrv_get_info(bs, &bdi);
2097 if (ret) {
2098 return ret;
2099 }
2100
2101 cvtstr(bdi.cluster_size, s1, sizeof(s1));
2102 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
2103
2104 printf("cluster size: %s\n", s1);
2105 printf("vm state offset: %s\n", s2);
2106
2107 spec_info = bdrv_get_specific_info(bs, &local_err);
2108 if (local_err) {
2109 error_report_err(local_err);
2110 return -EIO;
2111 }
2112 if (spec_info) {
2113 bdrv_image_info_specific_dump(spec_info,
2114 "Format specific information:\n",
2115 0);
2116 qapi_free_ImageInfoSpecific(spec_info);
2117 }
2118
2119 return 0;
2120}
2121
2122
2123
2124static const cmdinfo_t info_cmd = {
2125 .name = "info",
2126 .altname = "i",
2127 .cfunc = info_f,
2128 .oneline = "prints information about the current file",
2129};
2130
2131static void discard_help(void)
2132{
2133 printf(
2134"\n"
2135" discards a range of bytes from the given offset\n"
2136"\n"
2137" Example:\n"
2138" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
2139"\n"
2140" Discards a segment of the currently open file.\n"
2141" -C, -- report statistics in a machine parsable format\n"
2142" -q, -- quiet mode, do not show I/O statistics\n"
2143"\n");
2144}
2145
2146static int discard_f(BlockBackend *blk, int argc, char **argv);
2147
2148static const cmdinfo_t discard_cmd = {
2149 .name = "discard",
2150 .altname = "d",
2151 .cfunc = discard_f,
2152 .perm = BLK_PERM_WRITE,
2153 .argmin = 2,
2154 .argmax = -1,
2155 .args = "[-Cq] off len",
2156 .oneline = "discards a number of bytes at a specified offset",
2157 .help = discard_help,
2158};
2159
2160static int discard_f(BlockBackend *blk, int argc, char **argv)
2161{
2162 struct timespec t1, t2;
2163 bool Cflag = false, qflag = false;
2164 int c, ret;
2165 int64_t offset, bytes;
2166
2167 while ((c = getopt(argc, argv, "Cq")) != -1) {
2168 switch (c) {
2169 case 'C':
2170 Cflag = true;
2171 break;
2172 case 'q':
2173 qflag = true;
2174 break;
2175 default:
2176 qemuio_command_usage(&discard_cmd);
2177 return -EINVAL;
2178 }
2179 }
2180
2181 if (optind != argc - 2) {
2182 qemuio_command_usage(&discard_cmd);
2183 return -EINVAL;
2184 }
2185
2186 offset = cvtnum(argv[optind]);
2187 if (offset < 0) {
2188 print_cvtnum_err(offset, argv[optind]);
2189 return offset;
2190 }
2191
2192 optind++;
2193 bytes = cvtnum(argv[optind]);
2194 if (bytes < 0) {
2195 print_cvtnum_err(bytes, argv[optind]);
2196 return bytes;
2197 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
2198 printf("length cannot exceed %"PRIu64", given %s\n",
2199 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
2200 return -EINVAL;
2201 }
2202
2203 clock_gettime(CLOCK_MONOTONIC, &t1);
2204 ret = blk_pdiscard(blk, offset, bytes);
2205 clock_gettime(CLOCK_MONOTONIC, &t2);
2206
2207 if (ret < 0) {
2208 printf("discard failed: %s\n", strerror(-ret));
2209 return ret;
2210 }
2211
2212
2213 if (!qflag) {
2214 t2 = tsub(t2, t1);
2215 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
2216 }
2217
2218 return 0;
2219}
2220
2221static int alloc_f(BlockBackend *blk, int argc, char **argv)
2222{
2223 BlockDriverState *bs = blk_bs(blk);
2224 int64_t offset, start, remaining, count;
2225 char s1[64];
2226 int ret;
2227 int64_t num, sum_alloc;
2228
2229 start = offset = cvtnum(argv[1]);
2230 if (offset < 0) {
2231 print_cvtnum_err(offset, argv[1]);
2232 return offset;
2233 }
2234
2235 if (argc == 3) {
2236 count = cvtnum(argv[2]);
2237 if (count < 0) {
2238 print_cvtnum_err(count, argv[2]);
2239 return count;
2240 }
2241 } else {
2242 count = BDRV_SECTOR_SIZE;
2243 }
2244
2245 remaining = count;
2246 sum_alloc = 0;
2247 while (remaining) {
2248 ret = bdrv_is_allocated(bs, offset, remaining, &num);
2249 if (ret < 0) {
2250 printf("is_allocated failed: %s\n", strerror(-ret));
2251 return ret;
2252 }
2253 offset += num;
2254 remaining -= num;
2255 if (ret) {
2256 sum_alloc += num;
2257 }
2258 if (num == 0) {
2259 count -= remaining;
2260 remaining = 0;
2261 }
2262 }
2263
2264 cvtstr(start, s1, sizeof(s1));
2265
2266 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
2267 sum_alloc, count, s1);
2268 return 0;
2269}
2270
2271static const cmdinfo_t alloc_cmd = {
2272 .name = "alloc",
2273 .altname = "a",
2274 .argmin = 1,
2275 .argmax = 2,
2276 .cfunc = alloc_f,
2277 .args = "offset [count]",
2278 .oneline = "checks if offset is allocated in the file",
2279};
2280
2281
2282static int map_is_allocated(BlockDriverState *bs, int64_t offset,
2283 int64_t bytes, int64_t *pnum)
2284{
2285 int64_t num;
2286 int ret, firstret;
2287
2288 ret = bdrv_is_allocated(bs, offset, bytes, &num);
2289 if (ret < 0) {
2290 return ret;
2291 }
2292
2293 firstret = ret;
2294 *pnum = num;
2295
2296 while (bytes > 0 && ret == firstret) {
2297 offset += num;
2298 bytes -= num;
2299
2300 ret = bdrv_is_allocated(bs, offset, bytes, &num);
2301 if (ret == firstret && num) {
2302 *pnum += num;
2303 } else {
2304 break;
2305 }
2306 }
2307
2308 return firstret;
2309}
2310
2311static int map_f(BlockBackend *blk, int argc, char **argv)
2312{
2313 int64_t offset, bytes;
2314 char s1[64], s2[64];
2315 int64_t num;
2316 int ret;
2317 const char *retstr;
2318
2319 offset = 0;
2320 bytes = blk_getlength(blk);
2321 if (bytes < 0) {
2322 error_report("Failed to query image length: %s", strerror(-bytes));
2323 return bytes;
2324 }
2325
2326 while (bytes) {
2327 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
2328 if (ret < 0) {
2329 error_report("Failed to get allocation status: %s", strerror(-ret));
2330 return ret;
2331 } else if (!num) {
2332 error_report("Unexpected end of image");
2333 return -EIO;
2334 }
2335
2336 retstr = ret ? " allocated" : "not allocated";
2337 cvtstr(num, s1, sizeof(s1));
2338 cvtstr(offset, s2, sizeof(s2));
2339 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
2340 s1, num, retstr, s2, offset);
2341
2342 offset += num;
2343 bytes -= num;
2344 }
2345
2346 return 0;
2347}
2348
2349static const cmdinfo_t map_cmd = {
2350 .name = "map",
2351 .argmin = 0,
2352 .argmax = 0,
2353 .cfunc = map_f,
2354 .args = "",
2355 .oneline = "prints the allocated areas of a file",
2356};
2357
2358static void reopen_help(void)
2359{
2360 printf(
2361"\n"
2362" Changes the open options of an already opened image\n"
2363"\n"
2364" Example:\n"
2365" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2366"\n"
2367" -r, -- Reopen the image read-only\n"
2368" -w, -- Reopen the image read-write\n"
2369" -c, -- Change the cache mode to the given value\n"
2370" -o, -- Changes block driver options (cf. 'open' command)\n"
2371"\n");
2372}
2373
2374static int reopen_f(BlockBackend *blk, int argc, char **argv);
2375
2376static QemuOptsList reopen_opts = {
2377 .name = "reopen",
2378 .merge_lists = true,
2379 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2380 .desc = {
2381
2382 { }
2383 },
2384};
2385
2386static const cmdinfo_t reopen_cmd = {
2387 .name = "reopen",
2388 .argmin = 0,
2389 .argmax = -1,
2390 .cfunc = reopen_f,
2391 .args = "[(-r|-w)] [-c cache] [-o options]",
2392 .oneline = "reopens an image with new options",
2393 .help = reopen_help,
2394};
2395
2396static int reopen_f(BlockBackend *blk, int argc, char **argv)
2397{
2398 BlockDriverState *bs = blk_bs(blk);
2399 QemuOpts *qopts;
2400 QDict *opts;
2401 int c;
2402 int flags = bs->open_flags;
2403 bool writethrough = !blk_enable_write_cache(blk);
2404 bool has_rw_option = false;
2405 bool has_cache_option = false;
2406 Error *local_err = NULL;
2407
2408 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
2409 switch (c) {
2410 case 'c':
2411 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
2412 error_report("Invalid cache option: %s", optarg);
2413 return -EINVAL;
2414 }
2415 has_cache_option = true;
2416 break;
2417 case 'o':
2418 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2419 qemu_opts_reset(&reopen_opts);
2420 return -EINVAL;
2421 }
2422 break;
2423 case 'r':
2424 if (has_rw_option) {
2425 error_report("Only one -r/-w option may be given");
2426 return -EINVAL;
2427 }
2428 flags &= ~BDRV_O_RDWR;
2429 has_rw_option = true;
2430 break;
2431 case 'w':
2432 if (has_rw_option) {
2433 error_report("Only one -r/-w option may be given");
2434 return -EINVAL;
2435 }
2436 flags |= BDRV_O_RDWR;
2437 has_rw_option = true;
2438 break;
2439 default:
2440 qemu_opts_reset(&reopen_opts);
2441 qemuio_command_usage(&reopen_cmd);
2442 return -EINVAL;
2443 }
2444 }
2445
2446 if (optind != argc) {
2447 qemu_opts_reset(&reopen_opts);
2448 qemuio_command_usage(&reopen_cmd);
2449 return -EINVAL;
2450 }
2451
2452 if (!writethrough != blk_enable_write_cache(blk) &&
2453 blk_get_attached_dev(blk))
2454 {
2455 error_report("Cannot change cache.writeback: Device attached");
2456 qemu_opts_reset(&reopen_opts);
2457 return -EBUSY;
2458 }
2459
2460 if (!(flags & BDRV_O_RDWR)) {
2461 uint64_t orig_perm, orig_shared_perm;
2462
2463 bdrv_drain(bs);
2464
2465 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2466 blk_set_perm(blk,
2467 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2468 orig_shared_perm,
2469 &error_abort);
2470 }
2471
2472 qopts = qemu_opts_find(&reopen_opts, NULL);
2473 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
2474 qemu_opts_reset(&reopen_opts);
2475
2476 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2477 if (has_rw_option) {
2478 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2479 qobject_unref(opts);
2480 return -EINVAL;
2481 }
2482 } else {
2483 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2484 }
2485
2486 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2487 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2488 if (has_cache_option) {
2489 error_report("Cannot set both -c and the cache options");
2490 qobject_unref(opts);
2491 return -EINVAL;
2492 }
2493 } else {
2494 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2495 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2496 }
2497
2498 bdrv_reopen(bs, opts, true, &local_err);
2499
2500 if (local_err) {
2501 error_report_err(local_err);
2502 return -EINVAL;
2503 }
2504
2505 blk_set_enable_write_cache(blk, !writethrough);
2506 return 0;
2507}
2508
2509static int break_f(BlockBackend *blk, int argc, char **argv)
2510{
2511 int ret;
2512
2513 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
2514 if (ret < 0) {
2515 printf("Could not set breakpoint: %s\n", strerror(-ret));
2516 return ret;
2517 }
2518
2519 return 0;
2520}
2521
2522static int remove_break_f(BlockBackend *blk, int argc, char **argv)
2523{
2524 int ret;
2525
2526 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
2527 if (ret < 0) {
2528 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
2529 return ret;
2530 }
2531
2532 return 0;
2533}
2534
2535static const cmdinfo_t break_cmd = {
2536 .name = "break",
2537 .argmin = 2,
2538 .argmax = 2,
2539 .cfunc = break_f,
2540 .args = "event tag",
2541 .oneline = "sets a breakpoint on event and tags the stopped "
2542 "request as tag",
2543};
2544
2545static const cmdinfo_t remove_break_cmd = {
2546 .name = "remove_break",
2547 .argmin = 1,
2548 .argmax = 1,
2549 .cfunc = remove_break_f,
2550 .args = "tag",
2551 .oneline = "remove a breakpoint by tag",
2552};
2553
2554static int resume_f(BlockBackend *blk, int argc, char **argv)
2555{
2556 int ret;
2557
2558 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
2559 if (ret < 0) {
2560 printf("Could not resume request: %s\n", strerror(-ret));
2561 return ret;
2562 }
2563
2564 return 0;
2565}
2566
2567static const cmdinfo_t resume_cmd = {
2568 .name = "resume",
2569 .argmin = 1,
2570 .argmax = 1,
2571 .cfunc = resume_f,
2572 .args = "tag",
2573 .oneline = "resumes the request tagged as tag",
2574};
2575
2576static int wait_break_f(BlockBackend *blk, int argc, char **argv)
2577{
2578 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2579 aio_poll(blk_get_aio_context(blk), true);
2580 }
2581 return 0;
2582}
2583
2584static const cmdinfo_t wait_break_cmd = {
2585 .name = "wait_break",
2586 .argmin = 1,
2587 .argmax = 1,
2588 .cfunc = wait_break_f,
2589 .args = "tag",
2590 .oneline = "waits for the suspension of a request",
2591};
2592
2593static int abort_f(BlockBackend *blk, int argc, char **argv)
2594{
2595 abort();
2596}
2597
2598static const cmdinfo_t abort_cmd = {
2599 .name = "abort",
2600 .cfunc = abort_f,
2601 .flags = CMD_NOFILE_OK,
2602 .oneline = "simulate a program crash using abort(3)",
2603};
2604
2605static void sigraise_help(void)
2606{
2607 printf(
2608"\n"
2609" raises the given signal\n"
2610"\n"
2611" Example:\n"
2612" 'sigraise %i' - raises SIGTERM\n"
2613"\n"
2614" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2615" given to sigraise.\n"
2616"\n", SIGTERM);
2617}
2618
2619static int sigraise_f(BlockBackend *blk, int argc, char **argv);
2620
2621static const cmdinfo_t sigraise_cmd = {
2622 .name = "sigraise",
2623 .cfunc = sigraise_f,
2624 .argmin = 1,
2625 .argmax = 1,
2626 .flags = CMD_NOFILE_OK,
2627 .args = "signal",
2628 .oneline = "raises a signal",
2629 .help = sigraise_help,
2630};
2631
2632static int sigraise_f(BlockBackend *blk, int argc, char **argv)
2633{
2634 int64_t sig = cvtnum(argv[1]);
2635 if (sig < 0) {
2636 print_cvtnum_err(sig, argv[1]);
2637 return sig;
2638 } else if (sig > NSIG) {
2639 printf("signal argument '%s' is too large to be a valid signal\n",
2640 argv[1]);
2641 return -EINVAL;
2642 }
2643
2644
2645
2646
2647 fflush(stdout);
2648 fflush(stderr);
2649
2650 raise(sig);
2651
2652 return 0;
2653}
2654
2655static void sleep_cb(void *opaque)
2656{
2657 bool *expired = opaque;
2658 *expired = true;
2659}
2660
2661static int sleep_f(BlockBackend *blk, int argc, char **argv)
2662{
2663 char *endptr;
2664 long ms;
2665 struct QEMUTimer *timer;
2666 bool expired = false;
2667
2668 ms = strtol(argv[1], &endptr, 0);
2669 if (ms < 0 || *endptr != '\0') {
2670 printf("%s is not a valid number\n", argv[1]);
2671 return -EINVAL;
2672 }
2673
2674 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2675 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2676
2677 while (!expired) {
2678 main_loop_wait(false);
2679 }
2680
2681 timer_free(timer);
2682 return 0;
2683}
2684
2685static const cmdinfo_t sleep_cmd = {
2686 .name = "sleep",
2687 .argmin = 1,
2688 .argmax = 1,
2689 .cfunc = sleep_f,
2690 .flags = CMD_NOFILE_OK,
2691 .oneline = "waits for the given value in milliseconds",
2692};
2693
2694static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2695{
2696 printf("%s ", cmd);
2697
2698 if (ct->args) {
2699 printf("%s ", ct->args);
2700 }
2701 printf("-- %s\n", ct->oneline);
2702}
2703
2704static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2705{
2706 help_oneline(cmd, ct);
2707 if (ct->help) {
2708 ct->help();
2709 }
2710}
2711
2712static void help_all(void)
2713{
2714 const cmdinfo_t *ct;
2715
2716 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2717 help_oneline(ct->name, ct);
2718 }
2719 printf("\nUse 'help commandname' for extended help.\n");
2720}
2721
2722static int help_f(BlockBackend *blk, int argc, char **argv)
2723{
2724 const cmdinfo_t *ct;
2725
2726 if (argc < 2) {
2727 help_all();
2728 return 0;
2729 }
2730
2731 ct = find_command(argv[1]);
2732 if (ct == NULL) {
2733 printf("command %s not found\n", argv[1]);
2734 return -EINVAL;
2735 }
2736
2737 help_onecmd(argv[1], ct);
2738 return 0;
2739}
2740
2741static const cmdinfo_t help_cmd = {
2742 .name = "help",
2743 .altname = "?",
2744 .cfunc = help_f,
2745 .argmin = 0,
2746 .argmax = 1,
2747 .flags = CMD_FLAG_GLOBAL,
2748 .args = "[command]",
2749 .oneline = "help for one or all commands",
2750};
2751
2752
2753
2754
2755
2756int qemuio_command(BlockBackend *blk, const char *cmd)
2757{
2758 char *input;
2759 const cmdinfo_t *ct;
2760 char **v;
2761 int c;
2762 int ret = 0;
2763
2764 input = g_strdup(cmd);
2765 v = breakline(input, &c);
2766 if (c) {
2767 ct = find_command(v[0]);
2768 if (ct) {
2769 ret = command(blk, ct, c, v);
2770 } else {
2771 fprintf(stderr, "command \"%s\" not found\n", v[0]);
2772 ret = -EINVAL;
2773 }
2774 }
2775 g_free(input);
2776 g_free(v);
2777
2778 return ret;
2779}
2780
2781static void __attribute((constructor)) init_qemuio_commands(void)
2782{
2783
2784 qemuio_add_command(&help_cmd);
2785 qemuio_add_command(&read_cmd);
2786 qemuio_add_command(&readv_cmd);
2787 qemuio_add_command(&write_cmd);
2788 qemuio_add_command(&writev_cmd);
2789 qemuio_add_command(&aio_read_cmd);
2790 qemuio_add_command(&aio_write_cmd);
2791 qemuio_add_command(&aio_flush_cmd);
2792 qemuio_add_command(&flush_cmd);
2793 qemuio_add_command(&zone_report_cmd);
2794 qemuio_add_command(&zone_open_cmd);
2795 qemuio_add_command(&zone_close_cmd);
2796 qemuio_add_command(&zone_finish_cmd);
2797 qemuio_add_command(&zone_reset_cmd);
2798 qemuio_add_command(&zone_append_cmd);
2799 qemuio_add_command(&truncate_cmd);
2800 qemuio_add_command(&length_cmd);
2801 qemuio_add_command(&info_cmd);
2802 qemuio_add_command(&discard_cmd);
2803 qemuio_add_command(&alloc_cmd);
2804 qemuio_add_command(&map_cmd);
2805 qemuio_add_command(&reopen_cmd);
2806 qemuio_add_command(&break_cmd);
2807 qemuio_add_command(&remove_break_cmd);
2808 qemuio_add_command(&resume_cmd);
2809 qemuio_add_command(&wait_break_cmd);
2810 qemuio_add_command(&abort_cmd);
2811 qemuio_add_command(&sleep_cmd);
2812 qemuio_add_command(&sigraise_cmd);
2813}
2814