]> git.proxmox.com Git - mirror_qemu.git/blame_incremental - qemu-io-cmds.c
bsd-user: Implement fork(2) and vfork(2) system calls.
[mirror_qemu.git] / qemu-io-cmds.c
... / ...
CommitLineData
1/*
2 * Command line utility to exercise the QEMU I/O path.
3 *
4 * Copyright (C) 2009-2016 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/osdep.h"
12#include "qapi/error.h"
13#include "qapi/qmp/qdict.h"
14#include "qemu-io.h"
15#include "sysemu/block-backend.h"
16#include "block/block.h"
17#include "block/block_int.h" /* for info_f() */
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 /* ci->perm assumes a file is open, but the GLOBAL and NOFILE_OK
42 * flags allow it not to be, so that combination is invalid.
43 * Catch it now rather than letting it manifest as a crash if a
44 * particular set of command line options are used.
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 * Request additional permissions if necessary for this command. The caller
98 * is responsible for restoring the original permissions afterwards if this
99 * is what it wants.
100 *
101 * Coverity thinks that blk may be NULL in the following if condition. It's
102 * not so: in init_check_command() we fail if blk is NULL for command with
103 * both CMD_FLAG_GLOBAL and CMD_NOFILE_OK flags unset. And in
104 * qemuio_add_command() we assert that command with non-zero .perm field
105 * doesn't set this flags. So, the following assertion is to silence
106 * Coverity:
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/* Invoke fn() for commands with a matching prefix */
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; /* fallback if hours needed */
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 * Parse the pattern argument to various sub-commands.
315 *
316 * Because the pattern is used as an argument to memset it must evaluate
317 * to an unsigned integer that fits into a single byte.
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 * Memory allocation helpers.
335 *
336 * Make sure memory is aligned by default, or purposefully misaligned if
337 * that is specified on the command line.
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 * qemu_io_alloc_from_file()
375 *
376 * Allocates the buffer and populates it with the content of the given file
377 * up to @len bytes. If the file length is less than @len, then the buffer
378 * is populated with the file content cyclically.
379 *
380 * @blk - the block backend where the buffer content is going to be written to
381 * @len - the buffer length
382 * @file_name - the file to read the content from
383 * @register_buf - call blk_register_buf()
384 *
385 * Returns: the buffer pointer on success
386 * NULL on error
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 * This code path is only taken before blk_register_buf() is called, so
436 * hardcode the qemu_io_free() unregister_buf argument to false.
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 {/* bytes,ops,time,bytes/sec,ops/sec */
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 * Parse multiple length statements for vectored I/O, and construct an I/O
493 * vector matching it.
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 /* Some compilers get confused and warn if this is not initialized. */
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 /* Ignored for backwards compatibility */
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 /* Finally, report back -- -C gives a parsable format */
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 /* Some compilers get confused and warn if this is not initialized. */
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 /* Finally, report back -- -C gives a parsable format */
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 /* Some compilers get confused and warn if this is not initialized. */
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 /* Ignored for backwards compatibility */
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 /* Finally, report back -- -C gives a parsable format */
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 /* Some compilers get confused and warn if this is not initialized. */
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 /* Finally, report back -- -C gives a parsable format */
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 /* Finally, report back -- -C gives a parsable format */
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 /* Finally, report back -- -C gives a parsable format */
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 unsigned int nr_zones;
1743
1744 ++optind;
1745 offset = cvtnum(argv[optind]);
1746 ++optind;
1747 nr_zones = cvtnum(argv[optind]);
1748
1749 g_autofree BlockZoneDescriptor *zones = NULL;
1750 zones = g_new(BlockZoneDescriptor, nr_zones);
1751 ret = blk_zone_report(blk, offset, &nr_zones, zones);
1752 if (ret < 0) {
1753 printf("zone report failed: %s\n", strerror(-ret));
1754 } else {
1755 for (int i = 0; i < nr_zones; ++i) {
1756 printf("start: 0x%" PRIx64 ", len 0x%" PRIx64 ", "
1757 "cap"" 0x%" PRIx64 ", wptr 0x%" PRIx64 ", "
1758 "zcond:%u, [type: %u]\n",
1759 tosector(zones[i].start), tosector(zones[i].length),
1760 tosector(zones[i].cap), tosector(zones[i].wp),
1761 zones[i].state, zones[i].type);
1762 }
1763 }
1764 return ret;
1765}
1766
1767static const cmdinfo_t zone_report_cmd = {
1768 .name = "zone_report",
1769 .altname = "zrp",
1770 .cfunc = zone_report_f,
1771 .argmin = 2,
1772 .argmax = 2,
1773 .args = "offset number",
1774 .oneline = "report zone information",
1775};
1776
1777static int zone_open_f(BlockBackend *blk, int argc, char **argv)
1778{
1779 int ret;
1780 int64_t offset, len;
1781 ++optind;
1782 offset = cvtnum(argv[optind]);
1783 ++optind;
1784 len = cvtnum(argv[optind]);
1785 ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len);
1786 if (ret < 0) {
1787 printf("zone open failed: %s\n", strerror(-ret));
1788 }
1789 return ret;
1790}
1791
1792static const cmdinfo_t zone_open_cmd = {
1793 .name = "zone_open",
1794 .altname = "zo",
1795 .cfunc = zone_open_f,
1796 .argmin = 2,
1797 .argmax = 2,
1798 .args = "offset len",
1799 .oneline = "explicit open a range of zones in zone block device",
1800};
1801
1802static int zone_close_f(BlockBackend *blk, int argc, char **argv)
1803{
1804 int ret;
1805 int64_t offset, len;
1806 ++optind;
1807 offset = cvtnum(argv[optind]);
1808 ++optind;
1809 len = cvtnum(argv[optind]);
1810 ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len);
1811 if (ret < 0) {
1812 printf("zone close failed: %s\n", strerror(-ret));
1813 }
1814 return ret;
1815}
1816
1817static const cmdinfo_t zone_close_cmd = {
1818 .name = "zone_close",
1819 .altname = "zc",
1820 .cfunc = zone_close_f,
1821 .argmin = 2,
1822 .argmax = 2,
1823 .args = "offset len",
1824 .oneline = "close a range of zones in zone block device",
1825};
1826
1827static int zone_finish_f(BlockBackend *blk, int argc, char **argv)
1828{
1829 int ret;
1830 int64_t offset, len;
1831 ++optind;
1832 offset = cvtnum(argv[optind]);
1833 ++optind;
1834 len = cvtnum(argv[optind]);
1835 ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len);
1836 if (ret < 0) {
1837 printf("zone finish failed: %s\n", strerror(-ret));
1838 }
1839 return ret;
1840}
1841
1842static const cmdinfo_t zone_finish_cmd = {
1843 .name = "zone_finish",
1844 .altname = "zf",
1845 .cfunc = zone_finish_f,
1846 .argmin = 2,
1847 .argmax = 2,
1848 .args = "offset len",
1849 .oneline = "finish a range of zones in zone block device",
1850};
1851
1852static int zone_reset_f(BlockBackend *blk, int argc, char **argv)
1853{
1854 int ret;
1855 int64_t offset, len;
1856 ++optind;
1857 offset = cvtnum(argv[optind]);
1858 ++optind;
1859 len = cvtnum(argv[optind]);
1860 ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len);
1861 if (ret < 0) {
1862 printf("zone reset failed: %s\n", strerror(-ret));
1863 }
1864 return ret;
1865}
1866
1867static const cmdinfo_t zone_reset_cmd = {
1868 .name = "zone_reset",
1869 .altname = "zrs",
1870 .cfunc = zone_reset_f,
1871 .argmin = 2,
1872 .argmax = 2,
1873 .args = "offset len",
1874 .oneline = "reset a zone write pointer in zone block device",
1875};
1876
1877static int do_aio_zone_append(BlockBackend *blk, QEMUIOVector *qiov,
1878 int64_t *offset, int flags, int *total)
1879{
1880 int async_ret = NOT_DONE;
1881
1882 blk_aio_zone_append(blk, offset, qiov, flags, aio_rw_done, &async_ret);
1883 while (async_ret == NOT_DONE) {
1884 main_loop_wait(false);
1885 }
1886
1887 *total = qiov->size;
1888 return async_ret < 0 ? async_ret : 1;
1889}
1890
1891static int zone_append_f(BlockBackend *blk, int argc, char **argv)
1892{
1893 int ret;
1894 bool pflag = false;
1895 int flags = 0;
1896 int total = 0;
1897 int64_t offset;
1898 char *buf;
1899 int c, nr_iov;
1900 int pattern = 0xcd;
1901 QEMUIOVector qiov;
1902
1903 if (optind > argc - 3) {
1904 return -EINVAL;
1905 }
1906
1907 if ((c = getopt(argc, argv, "p")) != -1) {
1908 pflag = true;
1909 }
1910
1911 offset = cvtnum(argv[optind]);
1912 if (offset < 0) {
1913 print_cvtnum_err(offset, argv[optind]);
1914 return offset;
1915 }
1916 optind++;
1917 nr_iov = argc - optind;
1918 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern,
1919 flags & BDRV_REQ_REGISTERED_BUF);
1920 if (buf == NULL) {
1921 return -EINVAL;
1922 }
1923 ret = do_aio_zone_append(blk, &qiov, &offset, flags, &total);
1924 if (ret < 0) {
1925 printf("zone append failed: %s\n", strerror(-ret));
1926 goto out;
1927 }
1928
1929 if (pflag) {
1930 printf("After zap done, the append sector is 0x%" PRIx64 "\n",
1931 tosector(offset));
1932 }
1933
1934out:
1935 qemu_io_free(blk, buf, qiov.size,
1936 flags & BDRV_REQ_REGISTERED_BUF);
1937 qemu_iovec_destroy(&qiov);
1938 return ret;
1939}
1940
1941static const cmdinfo_t zone_append_cmd = {
1942 .name = "zone_append",
1943 .altname = "zap",
1944 .cfunc = zone_append_f,
1945 .argmin = 3,
1946 .argmax = 4,
1947 .args = "offset len [len..]",
1948 .oneline = "append write a number of bytes at a specified offset",
1949};
1950
1951static int truncate_f(BlockBackend *blk, int argc, char **argv);
1952static const cmdinfo_t truncate_cmd = {
1953 .name = "truncate",
1954 .altname = "t",
1955 .cfunc = truncate_f,
1956 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
1957 .argmin = 1,
1958 .argmax = 3,
1959 .args = "[-m prealloc_mode] off",
1960 .oneline = "truncates the current file at the given offset",
1961};
1962
1963static int truncate_f(BlockBackend *blk, int argc, char **argv)
1964{
1965 Error *local_err = NULL;
1966 int64_t offset;
1967 int c, ret;
1968 PreallocMode prealloc = PREALLOC_MODE_OFF;
1969
1970 while ((c = getopt(argc, argv, "m:")) != -1) {
1971 switch (c) {
1972 case 'm':
1973 prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
1974 PREALLOC_MODE__MAX, NULL);
1975 if (prealloc == PREALLOC_MODE__MAX) {
1976 error_report("Invalid preallocation mode '%s'", optarg);
1977 return -EINVAL;
1978 }
1979 break;
1980 default:
1981 qemuio_command_usage(&truncate_cmd);
1982 return -EINVAL;
1983 }
1984 }
1985
1986 offset = cvtnum(argv[optind]);
1987 if (offset < 0) {
1988 print_cvtnum_err(offset, argv[1]);
1989 return offset;
1990 }
1991
1992 /*
1993 * qemu-io is a debugging tool, so let us be strict here and pass
1994 * exact=true. It is better to err on the "emit more errors" side
1995 * than to be overly permissive.
1996 */
1997 ret = blk_truncate(blk, offset, false, prealloc, 0, &local_err);
1998 if (ret < 0) {
1999 error_report_err(local_err);
2000 return ret;
2001 }
2002
2003 return 0;
2004}
2005
2006static int length_f(BlockBackend *blk, int argc, char **argv)
2007{
2008 int64_t size;
2009 char s1[64];
2010
2011 size = blk_getlength(blk);
2012 if (size < 0) {
2013 printf("getlength: %s\n", strerror(-size));
2014 return size;
2015 }
2016
2017 cvtstr(size, s1, sizeof(s1));
2018 printf("%s\n", s1);
2019 return 0;
2020}
2021
2022
2023static const cmdinfo_t length_cmd = {
2024 .name = "length",
2025 .altname = "l",
2026 .cfunc = length_f,
2027 .oneline = "gets the length of the current file",
2028};
2029
2030
2031static int info_f(BlockBackend *blk, int argc, char **argv)
2032{
2033 BlockDriverState *bs = blk_bs(blk);
2034 BlockDriverInfo bdi;
2035 ImageInfoSpecific *spec_info;
2036 Error *local_err = NULL;
2037 char s1[64], s2[64];
2038 int ret;
2039
2040 if (bs->drv && bs->drv->format_name) {
2041 printf("format name: %s\n", bs->drv->format_name);
2042 }
2043 if (bs->drv && bs->drv->protocol_name) {
2044 printf("format name: %s\n", bs->drv->protocol_name);
2045 }
2046
2047 ret = bdrv_get_info(bs, &bdi);
2048 if (ret) {
2049 return ret;
2050 }
2051
2052 cvtstr(bdi.cluster_size, s1, sizeof(s1));
2053 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
2054
2055 printf("cluster size: %s\n", s1);
2056 printf("vm state offset: %s\n", s2);
2057
2058 spec_info = bdrv_get_specific_info(bs, &local_err);
2059 if (local_err) {
2060 error_report_err(local_err);
2061 return -EIO;
2062 }
2063 if (spec_info) {
2064 bdrv_image_info_specific_dump(spec_info,
2065 "Format specific information:\n",
2066 0);
2067 qapi_free_ImageInfoSpecific(spec_info);
2068 }
2069
2070 return 0;
2071}
2072
2073
2074
2075static const cmdinfo_t info_cmd = {
2076 .name = "info",
2077 .altname = "i",
2078 .cfunc = info_f,
2079 .oneline = "prints information about the current file",
2080};
2081
2082static void discard_help(void)
2083{
2084 printf(
2085"\n"
2086" discards a range of bytes from the given offset\n"
2087"\n"
2088" Example:\n"
2089" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
2090"\n"
2091" Discards a segment of the currently open file.\n"
2092" -C, -- report statistics in a machine parsable format\n"
2093" -q, -- quiet mode, do not show I/O statistics\n"
2094"\n");
2095}
2096
2097static int discard_f(BlockBackend *blk, int argc, char **argv);
2098
2099static const cmdinfo_t discard_cmd = {
2100 .name = "discard",
2101 .altname = "d",
2102 .cfunc = discard_f,
2103 .perm = BLK_PERM_WRITE,
2104 .argmin = 2,
2105 .argmax = -1,
2106 .args = "[-Cq] off len",
2107 .oneline = "discards a number of bytes at a specified offset",
2108 .help = discard_help,
2109};
2110
2111static int discard_f(BlockBackend *blk, int argc, char **argv)
2112{
2113 struct timespec t1, t2;
2114 bool Cflag = false, qflag = false;
2115 int c, ret;
2116 int64_t offset, bytes;
2117
2118 while ((c = getopt(argc, argv, "Cq")) != -1) {
2119 switch (c) {
2120 case 'C':
2121 Cflag = true;
2122 break;
2123 case 'q':
2124 qflag = true;
2125 break;
2126 default:
2127 qemuio_command_usage(&discard_cmd);
2128 return -EINVAL;
2129 }
2130 }
2131
2132 if (optind != argc - 2) {
2133 qemuio_command_usage(&discard_cmd);
2134 return -EINVAL;
2135 }
2136
2137 offset = cvtnum(argv[optind]);
2138 if (offset < 0) {
2139 print_cvtnum_err(offset, argv[optind]);
2140 return offset;
2141 }
2142
2143 optind++;
2144 bytes = cvtnum(argv[optind]);
2145 if (bytes < 0) {
2146 print_cvtnum_err(bytes, argv[optind]);
2147 return bytes;
2148 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
2149 printf("length cannot exceed %"PRIu64", given %s\n",
2150 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
2151 return -EINVAL;
2152 }
2153
2154 clock_gettime(CLOCK_MONOTONIC, &t1);
2155 ret = blk_pdiscard(blk, offset, bytes);
2156 clock_gettime(CLOCK_MONOTONIC, &t2);
2157
2158 if (ret < 0) {
2159 printf("discard failed: %s\n", strerror(-ret));
2160 return ret;
2161 }
2162
2163 /* Finally, report back -- -C gives a parsable format */
2164 if (!qflag) {
2165 t2 = tsub(t2, t1);
2166 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
2167 }
2168
2169 return 0;
2170}
2171
2172static int alloc_f(BlockBackend *blk, int argc, char **argv)
2173{
2174 BlockDriverState *bs = blk_bs(blk);
2175 int64_t offset, start, remaining, count;
2176 char s1[64];
2177 int ret;
2178 int64_t num, sum_alloc;
2179
2180 start = offset = cvtnum(argv[1]);
2181 if (offset < 0) {
2182 print_cvtnum_err(offset, argv[1]);
2183 return offset;
2184 }
2185
2186 if (argc == 3) {
2187 count = cvtnum(argv[2]);
2188 if (count < 0) {
2189 print_cvtnum_err(count, argv[2]);
2190 return count;
2191 }
2192 } else {
2193 count = BDRV_SECTOR_SIZE;
2194 }
2195
2196 remaining = count;
2197 sum_alloc = 0;
2198 while (remaining) {
2199 ret = bdrv_is_allocated(bs, offset, remaining, &num);
2200 if (ret < 0) {
2201 printf("is_allocated failed: %s\n", strerror(-ret));
2202 return ret;
2203 }
2204 offset += num;
2205 remaining -= num;
2206 if (ret) {
2207 sum_alloc += num;
2208 }
2209 if (num == 0) {
2210 count -= remaining;
2211 remaining = 0;
2212 }
2213 }
2214
2215 cvtstr(start, s1, sizeof(s1));
2216
2217 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
2218 sum_alloc, count, s1);
2219 return 0;
2220}
2221
2222static const cmdinfo_t alloc_cmd = {
2223 .name = "alloc",
2224 .altname = "a",
2225 .argmin = 1,
2226 .argmax = 2,
2227 .cfunc = alloc_f,
2228 .args = "offset [count]",
2229 .oneline = "checks if offset is allocated in the file",
2230};
2231
2232
2233static int map_is_allocated(BlockDriverState *bs, int64_t offset,
2234 int64_t bytes, int64_t *pnum)
2235{
2236 int64_t num;
2237 int ret, firstret;
2238
2239 ret = bdrv_is_allocated(bs, offset, bytes, &num);
2240 if (ret < 0) {
2241 return ret;
2242 }
2243
2244 firstret = ret;
2245 *pnum = num;
2246
2247 while (bytes > 0 && ret == firstret) {
2248 offset += num;
2249 bytes -= num;
2250
2251 ret = bdrv_is_allocated(bs, offset, bytes, &num);
2252 if (ret == firstret && num) {
2253 *pnum += num;
2254 } else {
2255 break;
2256 }
2257 }
2258
2259 return firstret;
2260}
2261
2262static int map_f(BlockBackend *blk, int argc, char **argv)
2263{
2264 int64_t offset, bytes;
2265 char s1[64], s2[64];
2266 int64_t num;
2267 int ret;
2268 const char *retstr;
2269
2270 offset = 0;
2271 bytes = blk_getlength(blk);
2272 if (bytes < 0) {
2273 error_report("Failed to query image length: %s", strerror(-bytes));
2274 return bytes;
2275 }
2276
2277 while (bytes) {
2278 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
2279 if (ret < 0) {
2280 error_report("Failed to get allocation status: %s", strerror(-ret));
2281 return ret;
2282 } else if (!num) {
2283 error_report("Unexpected end of image");
2284 return -EIO;
2285 }
2286
2287 retstr = ret ? " allocated" : "not allocated";
2288 cvtstr(num, s1, sizeof(s1));
2289 cvtstr(offset, s2, sizeof(s2));
2290 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
2291 s1, num, retstr, s2, offset);
2292
2293 offset += num;
2294 bytes -= num;
2295 }
2296
2297 return 0;
2298}
2299
2300static const cmdinfo_t map_cmd = {
2301 .name = "map",
2302 .argmin = 0,
2303 .argmax = 0,
2304 .cfunc = map_f,
2305 .args = "",
2306 .oneline = "prints the allocated areas of a file",
2307};
2308
2309static void reopen_help(void)
2310{
2311 printf(
2312"\n"
2313" Changes the open options of an already opened image\n"
2314"\n"
2315" Example:\n"
2316" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2317"\n"
2318" -r, -- Reopen the image read-only\n"
2319" -w, -- Reopen the image read-write\n"
2320" -c, -- Change the cache mode to the given value\n"
2321" -o, -- Changes block driver options (cf. 'open' command)\n"
2322"\n");
2323}
2324
2325static int reopen_f(BlockBackend *blk, int argc, char **argv);
2326
2327static QemuOptsList reopen_opts = {
2328 .name = "reopen",
2329 .merge_lists = true,
2330 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2331 .desc = {
2332 /* no elements => accept any params */
2333 { /* end of list */ }
2334 },
2335};
2336
2337static const cmdinfo_t reopen_cmd = {
2338 .name = "reopen",
2339 .argmin = 0,
2340 .argmax = -1,
2341 .cfunc = reopen_f,
2342 .args = "[(-r|-w)] [-c cache] [-o options]",
2343 .oneline = "reopens an image with new options",
2344 .help = reopen_help,
2345};
2346
2347static int reopen_f(BlockBackend *blk, int argc, char **argv)
2348{
2349 BlockDriverState *bs = blk_bs(blk);
2350 QemuOpts *qopts;
2351 QDict *opts;
2352 int c;
2353 int flags = bs->open_flags;
2354 bool writethrough = !blk_enable_write_cache(blk);
2355 bool has_rw_option = false;
2356 bool has_cache_option = false;
2357 Error *local_err = NULL;
2358
2359 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
2360 switch (c) {
2361 case 'c':
2362 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
2363 error_report("Invalid cache option: %s", optarg);
2364 return -EINVAL;
2365 }
2366 has_cache_option = true;
2367 break;
2368 case 'o':
2369 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2370 qemu_opts_reset(&reopen_opts);
2371 return -EINVAL;
2372 }
2373 break;
2374 case 'r':
2375 if (has_rw_option) {
2376 error_report("Only one -r/-w option may be given");
2377 return -EINVAL;
2378 }
2379 flags &= ~BDRV_O_RDWR;
2380 has_rw_option = true;
2381 break;
2382 case 'w':
2383 if (has_rw_option) {
2384 error_report("Only one -r/-w option may be given");
2385 return -EINVAL;
2386 }
2387 flags |= BDRV_O_RDWR;
2388 has_rw_option = true;
2389 break;
2390 default:
2391 qemu_opts_reset(&reopen_opts);
2392 qemuio_command_usage(&reopen_cmd);
2393 return -EINVAL;
2394 }
2395 }
2396
2397 if (optind != argc) {
2398 qemu_opts_reset(&reopen_opts);
2399 qemuio_command_usage(&reopen_cmd);
2400 return -EINVAL;
2401 }
2402
2403 if (!writethrough != blk_enable_write_cache(blk) &&
2404 blk_get_attached_dev(blk))
2405 {
2406 error_report("Cannot change cache.writeback: Device attached");
2407 qemu_opts_reset(&reopen_opts);
2408 return -EBUSY;
2409 }
2410
2411 if (!(flags & BDRV_O_RDWR)) {
2412 uint64_t orig_perm, orig_shared_perm;
2413
2414 bdrv_drain(bs);
2415
2416 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2417 blk_set_perm(blk,
2418 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2419 orig_shared_perm,
2420 &error_abort);
2421 }
2422
2423 qopts = qemu_opts_find(&reopen_opts, NULL);
2424 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
2425 qemu_opts_reset(&reopen_opts);
2426
2427 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2428 if (has_rw_option) {
2429 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2430 qobject_unref(opts);
2431 return -EINVAL;
2432 }
2433 } else {
2434 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2435 }
2436
2437 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2438 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2439 if (has_cache_option) {
2440 error_report("Cannot set both -c and the cache options");
2441 qobject_unref(opts);
2442 return -EINVAL;
2443 }
2444 } else {
2445 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2446 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2447 }
2448
2449 bdrv_reopen(bs, opts, true, &local_err);
2450
2451 if (local_err) {
2452 error_report_err(local_err);
2453 return -EINVAL;
2454 }
2455
2456 blk_set_enable_write_cache(blk, !writethrough);
2457 return 0;
2458}
2459
2460static int break_f(BlockBackend *blk, int argc, char **argv)
2461{
2462 int ret;
2463
2464 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
2465 if (ret < 0) {
2466 printf("Could not set breakpoint: %s\n", strerror(-ret));
2467 return ret;
2468 }
2469
2470 return 0;
2471}
2472
2473static int remove_break_f(BlockBackend *blk, int argc, char **argv)
2474{
2475 int ret;
2476
2477 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
2478 if (ret < 0) {
2479 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
2480 return ret;
2481 }
2482
2483 return 0;
2484}
2485
2486static const cmdinfo_t break_cmd = {
2487 .name = "break",
2488 .argmin = 2,
2489 .argmax = 2,
2490 .cfunc = break_f,
2491 .args = "event tag",
2492 .oneline = "sets a breakpoint on event and tags the stopped "
2493 "request as tag",
2494};
2495
2496static const cmdinfo_t remove_break_cmd = {
2497 .name = "remove_break",
2498 .argmin = 1,
2499 .argmax = 1,
2500 .cfunc = remove_break_f,
2501 .args = "tag",
2502 .oneline = "remove a breakpoint by tag",
2503};
2504
2505static int resume_f(BlockBackend *blk, int argc, char **argv)
2506{
2507 int ret;
2508
2509 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
2510 if (ret < 0) {
2511 printf("Could not resume request: %s\n", strerror(-ret));
2512 return ret;
2513 }
2514
2515 return 0;
2516}
2517
2518static const cmdinfo_t resume_cmd = {
2519 .name = "resume",
2520 .argmin = 1,
2521 .argmax = 1,
2522 .cfunc = resume_f,
2523 .args = "tag",
2524 .oneline = "resumes the request tagged as tag",
2525};
2526
2527static int wait_break_f(BlockBackend *blk, int argc, char **argv)
2528{
2529 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2530 aio_poll(blk_get_aio_context(blk), true);
2531 }
2532 return 0;
2533}
2534
2535static const cmdinfo_t wait_break_cmd = {
2536 .name = "wait_break",
2537 .argmin = 1,
2538 .argmax = 1,
2539 .cfunc = wait_break_f,
2540 .args = "tag",
2541 .oneline = "waits for the suspension of a request",
2542};
2543
2544static int abort_f(BlockBackend *blk, int argc, char **argv)
2545{
2546 abort();
2547}
2548
2549static const cmdinfo_t abort_cmd = {
2550 .name = "abort",
2551 .cfunc = abort_f,
2552 .flags = CMD_NOFILE_OK,
2553 .oneline = "simulate a program crash using abort(3)",
2554};
2555
2556static void sigraise_help(void)
2557{
2558 printf(
2559"\n"
2560" raises the given signal\n"
2561"\n"
2562" Example:\n"
2563" 'sigraise %i' - raises SIGTERM\n"
2564"\n"
2565" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2566" given to sigraise.\n"
2567"\n", SIGTERM);
2568}
2569
2570static int sigraise_f(BlockBackend *blk, int argc, char **argv);
2571
2572static const cmdinfo_t sigraise_cmd = {
2573 .name = "sigraise",
2574 .cfunc = sigraise_f,
2575 .argmin = 1,
2576 .argmax = 1,
2577 .flags = CMD_NOFILE_OK,
2578 .args = "signal",
2579 .oneline = "raises a signal",
2580 .help = sigraise_help,
2581};
2582
2583static int sigraise_f(BlockBackend *blk, int argc, char **argv)
2584{
2585 int64_t sig = cvtnum(argv[1]);
2586 if (sig < 0) {
2587 print_cvtnum_err(sig, argv[1]);
2588 return sig;
2589 } else if (sig > NSIG) {
2590 printf("signal argument '%s' is too large to be a valid signal\n",
2591 argv[1]);
2592 return -EINVAL;
2593 }
2594
2595 /* Using raise() to kill this process does not necessarily flush all open
2596 * streams. At least stdout and stderr (although the latter should be
2597 * non-buffered anyway) should be flushed, though. */
2598 fflush(stdout);
2599 fflush(stderr);
2600
2601 raise(sig);
2602
2603 return 0;
2604}
2605
2606static void sleep_cb(void *opaque)
2607{
2608 bool *expired = opaque;
2609 *expired = true;
2610}
2611
2612static int sleep_f(BlockBackend *blk, int argc, char **argv)
2613{
2614 char *endptr;
2615 long ms;
2616 struct QEMUTimer *timer;
2617 bool expired = false;
2618
2619 ms = strtol(argv[1], &endptr, 0);
2620 if (ms < 0 || *endptr != '\0') {
2621 printf("%s is not a valid number\n", argv[1]);
2622 return -EINVAL;
2623 }
2624
2625 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2626 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2627
2628 while (!expired) {
2629 main_loop_wait(false);
2630 }
2631
2632 timer_free(timer);
2633 return 0;
2634}
2635
2636static const cmdinfo_t sleep_cmd = {
2637 .name = "sleep",
2638 .argmin = 1,
2639 .argmax = 1,
2640 .cfunc = sleep_f,
2641 .flags = CMD_NOFILE_OK,
2642 .oneline = "waits for the given value in milliseconds",
2643};
2644
2645static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2646{
2647 printf("%s ", cmd);
2648
2649 if (ct->args) {
2650 printf("%s ", ct->args);
2651 }
2652 printf("-- %s\n", ct->oneline);
2653}
2654
2655static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2656{
2657 help_oneline(cmd, ct);
2658 if (ct->help) {
2659 ct->help();
2660 }
2661}
2662
2663static void help_all(void)
2664{
2665 const cmdinfo_t *ct;
2666
2667 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2668 help_oneline(ct->name, ct);
2669 }
2670 printf("\nUse 'help commandname' for extended help.\n");
2671}
2672
2673static int help_f(BlockBackend *blk, int argc, char **argv)
2674{
2675 const cmdinfo_t *ct;
2676
2677 if (argc < 2) {
2678 help_all();
2679 return 0;
2680 }
2681
2682 ct = find_command(argv[1]);
2683 if (ct == NULL) {
2684 printf("command %s not found\n", argv[1]);
2685 return -EINVAL;
2686 }
2687
2688 help_onecmd(argv[1], ct);
2689 return 0;
2690}
2691
2692static const cmdinfo_t help_cmd = {
2693 .name = "help",
2694 .altname = "?",
2695 .cfunc = help_f,
2696 .argmin = 0,
2697 .argmax = 1,
2698 .flags = CMD_FLAG_GLOBAL,
2699 .args = "[command]",
2700 .oneline = "help for one or all commands",
2701};
2702
2703/*
2704 * Called with aio context of blk acquired. Or with qemu_get_aio_context()
2705 * context acquired if blk is NULL.
2706 */
2707int qemuio_command(BlockBackend *blk, const char *cmd)
2708{
2709 char *input;
2710 const cmdinfo_t *ct;
2711 char **v;
2712 int c;
2713 int ret = 0;
2714
2715 input = g_strdup(cmd);
2716 v = breakline(input, &c);
2717 if (c) {
2718 ct = find_command(v[0]);
2719 if (ct) {
2720 ret = command(blk, ct, c, v);
2721 } else {
2722 fprintf(stderr, "command \"%s\" not found\n", v[0]);
2723 ret = -EINVAL;
2724 }
2725 }
2726 g_free(input);
2727 g_free(v);
2728
2729 return ret;
2730}
2731
2732static void __attribute((constructor)) init_qemuio_commands(void)
2733{
2734 /* initialize commands */
2735 qemuio_add_command(&help_cmd);
2736 qemuio_add_command(&read_cmd);
2737 qemuio_add_command(&readv_cmd);
2738 qemuio_add_command(&write_cmd);
2739 qemuio_add_command(&writev_cmd);
2740 qemuio_add_command(&aio_read_cmd);
2741 qemuio_add_command(&aio_write_cmd);
2742 qemuio_add_command(&aio_flush_cmd);
2743 qemuio_add_command(&flush_cmd);
2744 qemuio_add_command(&zone_report_cmd);
2745 qemuio_add_command(&zone_open_cmd);
2746 qemuio_add_command(&zone_close_cmd);
2747 qemuio_add_command(&zone_finish_cmd);
2748 qemuio_add_command(&zone_reset_cmd);
2749 qemuio_add_command(&zone_append_cmd);
2750 qemuio_add_command(&truncate_cmd);
2751 qemuio_add_command(&length_cmd);
2752 qemuio_add_command(&info_cmd);
2753 qemuio_add_command(&discard_cmd);
2754 qemuio_add_command(&alloc_cmd);
2755 qemuio_add_command(&map_cmd);
2756 qemuio_add_command(&reopen_cmd);
2757 qemuio_add_command(&break_cmd);
2758 qemuio_add_command(&remove_break_cmd);
2759 qemuio_add_command(&resume_cmd);
2760 qemuio_add_command(&wait_break_cmd);
2761 qemuio_add_command(&abort_cmd);
2762 qemuio_add_command(&sleep_cmd);
2763 qemuio_add_command(&sigraise_cmd);
2764}