xref: /qemu/qemu-io-cmds.c (revision 3574499a)
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 
28 bool qemuio_misalign;
29 
30 static cmdinfo_t *cmdtab;
31 static int ncmds;
32 
compare_cmdname(const void * a,const void * b)33 static 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 
qemuio_add_command(const cmdinfo_t * ci)39 void 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 
qemuio_command_usage(const cmdinfo_t * ci)53 void qemuio_command_usage(const cmdinfo_t *ci)
54 {
55     printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
56 }
57 
init_check_command(BlockBackend * blk,const cmdinfo_t * ct)58 static 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 
command(BlockBackend * blk,const cmdinfo_t * ct,int argc,char ** argv)70 static 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 
find_command(const char * cmd)132 static 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 */
qemuio_complete_command(const char * input,void (* fn)(const char * cmd,void * opaque),void * opaque)147 void 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 
breakline(char * input,int * count)161 static 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 
cvtnum(const char * s)180 static 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 
print_cvtnum_err(int64_t rc,const char * arg)195 static 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 
cvtstr(double value,char * str,size_t size)224 static 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 
tsub(struct timespec t1,struct timespec t2)262 static 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 
tdiv(double value,struct timespec tv)273 static 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 
283 enum {
284     DEFAULT_TIME        = 0x0,
285     TERSE_FIXED_TIME    = 0x1,
286     VERBOSE_FIXED_TIME  = 0x2,
287 };
288 
timestr(struct timespec * tv,char * ts,size_t size,int format)289 static 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  */
parse_pattern(const char * arg)319 static 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
qemu_io_alloc(BlockBackend * blk,size_t len,int pattern,bool register_buf)341 static 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 
qemu_io_free(BlockBackend * blk,void * p,size_t len,bool unregister_buf)360 static 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  */
qemu_io_alloc_from_file(BlockBackend * blk,size_t len,const char * file_name,bool register_buf)388 static 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 
433 error:
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 
dump_buffer(const void * buffer,int64_t offset,int64_t len)445 static 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 
print_report(const char * op,struct timespec * t,int64_t offset,int64_t count,int64_t total,int cnt,bool Cflag)470 static 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  */
495 static void *
create_iovec(BlockBackend * blk,QEMUIOVector * qiov,char ** argv,int nr_iov,int pattern,bool register_buf)496 create_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 
540 fail:
541     g_free(sizes);
542     return buf;
543 }
544 
do_pread(BlockBackend * blk,char * buf,int64_t offset,int64_t bytes,BdrvRequestFlags flags,int64_t * total)545 static 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 
do_pwrite(BlockBackend * blk,char * buf,int64_t offset,int64_t bytes,BdrvRequestFlags flags,int64_t * total)562 static 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 
do_pwrite_zeroes(BlockBackend * blk,int64_t offset,int64_t bytes,BdrvRequestFlags flags,int64_t * total)579 static 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 
do_write_compressed(BlockBackend * blk,char * buf,int64_t offset,int64_t bytes,int64_t * total)593 static 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 
do_load_vmstate(BlockBackend * blk,char * buf,int64_t offset,int64_t count,int64_t * total)610 static 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 
do_save_vmstate(BlockBackend * blk,char * buf,int64_t offset,int64_t count,int64_t * total)624 static 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
aio_rw_done(void * opaque,int ret)639 static void aio_rw_done(void *opaque, int ret)
640 {
641     *(int *)opaque = ret;
642 }
643 
do_aio_readv(BlockBackend * blk,QEMUIOVector * qiov,int64_t offset,BdrvRequestFlags flags,int * total)644 static 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 
do_aio_writev(BlockBackend * blk,QEMUIOVector * qiov,int64_t offset,BdrvRequestFlags flags,int * total)658 static 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 
read_help(void)672 static 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 
695 static int read_f(BlockBackend *blk, int argc, char **argv);
696 
697 static 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 
read_f(BlockBackend * blk,int argc,char ** argv)708 static 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 
868 out:
869     qemu_io_free(blk, buf, count, flags & BDRV_REQ_REGISTERED_BUF);
870     return ret;
871 }
872 
readv_help(void)873 static 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 
893 static int readv_f(BlockBackend *blk, int argc, char **argv);
894 
895 static 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 
readv_f(BlockBackend * blk,int argc,char ** argv)905 static 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 
1002 out:
1003     qemu_io_free(blk, buf, qiov.size, flags & BDRV_REQ_REGISTERED_BUF);
1004     qemu_iovec_destroy(&qiov);
1005     return ret;
1006 }
1007 
write_help(void)1008 static 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 
1034 static int write_f(BlockBackend *blk, int argc, char **argv);
1035 
1036 static 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 
write_f(BlockBackend * blk,int argc,char ** argv)1048 static 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 
1221 out:
1222     if (!zflag) {
1223         qemu_io_free(blk, buf, count, flags & BDRV_REQ_REGISTERED_BUF);
1224     }
1225     return ret;
1226 }
1227 
1228 static void
writev_help(void)1229 writev_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 
1248 static int writev_f(BlockBackend *blk, int argc, char **argv);
1249 
1250 static 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 
writev_f(BlockBackend * blk,int argc,char ** argv)1261 static 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);
1339 out:
1340     qemu_io_free(blk, buf, qiov.size, flags & BDRV_REQ_REGISTERED_BUF);
1341     qemu_iovec_destroy(&qiov);
1342     return ret;
1343 }
1344 
1345 struct 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 
aio_write_done(void * opaque,int ret)1361 static 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);
1385 out:
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 
aio_read_done(void * opaque,int ret)1394 static 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);
1432 out:
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 
aio_read_help(void)1439 static 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 
1464 static int aio_read_f(BlockBackend *blk, int argc, char **argv);
1465 
1466 static 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 
aio_read_f(BlockBackend * blk,int argc,char ** argv)1476 static 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 
aio_write_help(void)1548 static 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 
1576 static int aio_write_f(BlockBackend *blk, int argc, char **argv);
1577 
1578 static 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 
aio_write_f(BlockBackend * blk,int argc,char ** argv)1589 static 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 
aio_flush_f(BlockBackend * blk,int argc,char ** argv)1706 static 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 
1715 static const cmdinfo_t aio_flush_cmd = {
1716     .name       = "aio_flush",
1717     .cfunc      = aio_flush_f,
1718     .oneline    = "completes all outstanding aio requests"
1719 };
1720 
flush_f(BlockBackend * blk,int argc,char ** argv)1721 static int flush_f(BlockBackend *blk, int argc, char **argv)
1722 {
1723     return blk_flush(blk);
1724 }
1725 
1726 static 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 
tosector(int64_t bytes)1733 static inline int64_t tosector(int64_t bytes)
1734 {
1735     return bytes >> BDRV_SECTOR_BITS;
1736 }
1737 
zone_report_f(BlockBackend * blk,int argc,char ** argv)1738 static 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 
1767 static 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 
zone_open_f(BlockBackend * blk,int argc,char ** argv)1777 static 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 
1792 static 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 
zone_close_f(BlockBackend * blk,int argc,char ** argv)1802 static 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 
1817 static 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 
zone_finish_f(BlockBackend * blk,int argc,char ** argv)1827 static 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 
1842 static 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 
zone_reset_f(BlockBackend * blk,int argc,char ** argv)1852 static 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 
1867 static 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 
do_aio_zone_append(BlockBackend * blk,QEMUIOVector * qiov,int64_t * offset,int flags,int * total)1877 static 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 
zone_append_f(BlockBackend * blk,int argc,char ** argv)1891 static 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 
1934 out:
1935     qemu_io_free(blk, buf, qiov.size,
1936                  flags & BDRV_REQ_REGISTERED_BUF);
1937     qemu_iovec_destroy(&qiov);
1938     return ret;
1939 }
1940 
1941 static 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 
1951 static int truncate_f(BlockBackend *blk, int argc, char **argv);
1952 static 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 
truncate_f(BlockBackend * blk,int argc,char ** argv)1963 static 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 
length_f(BlockBackend * blk,int argc,char ** argv)2006 static 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 
2023 static 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 
info_f(BlockBackend * blk,int argc,char ** argv)2031 static 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     GLOBAL_STATE_CODE();
2041     GRAPH_RDLOCK_GUARD_MAINLOOP();
2042 
2043     if (bs->drv && bs->drv->format_name) {
2044         printf("format name: %s\n", bs->drv->format_name);
2045     }
2046     if (bs->drv && bs->drv->protocol_name) {
2047         printf("format name: %s\n", bs->drv->protocol_name);
2048     }
2049 
2050     ret = bdrv_get_info(bs, &bdi);
2051     if (ret) {
2052         return ret;
2053     }
2054 
2055     cvtstr(bdi.cluster_size, s1, sizeof(s1));
2056     cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
2057 
2058     printf("cluster size: %s\n", s1);
2059     printf("vm state offset: %s\n", s2);
2060 
2061     spec_info = bdrv_get_specific_info(bs, &local_err);
2062     if (local_err) {
2063         error_report_err(local_err);
2064         return -EIO;
2065     }
2066     if (spec_info) {
2067         bdrv_image_info_specific_dump(spec_info,
2068                                       "Format specific information:\n",
2069                                       0);
2070         qapi_free_ImageInfoSpecific(spec_info);
2071     }
2072 
2073     return 0;
2074 }
2075 
2076 
2077 
2078 static const cmdinfo_t info_cmd = {
2079     .name       = "info",
2080     .altname    = "i",
2081     .cfunc      = info_f,
2082     .oneline    = "prints information about the current file",
2083 };
2084 
discard_help(void)2085 static void discard_help(void)
2086 {
2087     printf(
2088 "\n"
2089 " discards a range of bytes from the given offset\n"
2090 "\n"
2091 " Example:\n"
2092 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
2093 "\n"
2094 " Discards a segment of the currently open file.\n"
2095 " -C, -- report statistics in a machine parsable format\n"
2096 " -q, -- quiet mode, do not show I/O statistics\n"
2097 "\n");
2098 }
2099 
2100 static int discard_f(BlockBackend *blk, int argc, char **argv);
2101 
2102 static const cmdinfo_t discard_cmd = {
2103     .name       = "discard",
2104     .altname    = "d",
2105     .cfunc      = discard_f,
2106     .perm       = BLK_PERM_WRITE,
2107     .argmin     = 2,
2108     .argmax     = -1,
2109     .args       = "[-Cq] off len",
2110     .oneline    = "discards a number of bytes at a specified offset",
2111     .help       = discard_help,
2112 };
2113 
discard_f(BlockBackend * blk,int argc,char ** argv)2114 static int discard_f(BlockBackend *blk, int argc, char **argv)
2115 {
2116     struct timespec t1, t2;
2117     bool Cflag = false, qflag = false;
2118     int c, ret;
2119     int64_t offset, bytes;
2120 
2121     while ((c = getopt(argc, argv, "Cq")) != -1) {
2122         switch (c) {
2123         case 'C':
2124             Cflag = true;
2125             break;
2126         case 'q':
2127             qflag = true;
2128             break;
2129         default:
2130             qemuio_command_usage(&discard_cmd);
2131             return -EINVAL;
2132         }
2133     }
2134 
2135     if (optind != argc - 2) {
2136         qemuio_command_usage(&discard_cmd);
2137         return -EINVAL;
2138     }
2139 
2140     offset = cvtnum(argv[optind]);
2141     if (offset < 0) {
2142         print_cvtnum_err(offset, argv[optind]);
2143         return offset;
2144     }
2145 
2146     optind++;
2147     bytes = cvtnum(argv[optind]);
2148     if (bytes < 0) {
2149         print_cvtnum_err(bytes, argv[optind]);
2150         return bytes;
2151     } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
2152         printf("length cannot exceed %"PRIu64", given %s\n",
2153                (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
2154         return -EINVAL;
2155     }
2156 
2157     clock_gettime(CLOCK_MONOTONIC, &t1);
2158     ret = blk_pdiscard(blk, offset, bytes);
2159     clock_gettime(CLOCK_MONOTONIC, &t2);
2160 
2161     if (ret < 0) {
2162         printf("discard failed: %s\n", strerror(-ret));
2163         return ret;
2164     }
2165 
2166     /* Finally, report back -- -C gives a parsable format */
2167     if (!qflag) {
2168         t2 = tsub(t2, t1);
2169         print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
2170     }
2171 
2172     return 0;
2173 }
2174 
alloc_f(BlockBackend * blk,int argc,char ** argv)2175 static int alloc_f(BlockBackend *blk, int argc, char **argv)
2176 {
2177     BlockDriverState *bs = blk_bs(blk);
2178     int64_t offset, start, remaining, count;
2179     char s1[64];
2180     int ret;
2181     int64_t num, sum_alloc;
2182 
2183     start = offset = cvtnum(argv[1]);
2184     if (offset < 0) {
2185         print_cvtnum_err(offset, argv[1]);
2186         return offset;
2187     }
2188 
2189     if (argc == 3) {
2190         count = cvtnum(argv[2]);
2191         if (count < 0) {
2192             print_cvtnum_err(count, argv[2]);
2193             return count;
2194         }
2195     } else {
2196         count = BDRV_SECTOR_SIZE;
2197     }
2198 
2199     remaining = count;
2200     sum_alloc = 0;
2201     while (remaining) {
2202         ret = bdrv_is_allocated(bs, offset, remaining, &num);
2203         if (ret < 0) {
2204             printf("is_allocated failed: %s\n", strerror(-ret));
2205             return ret;
2206         }
2207         offset += num;
2208         remaining -= num;
2209         if (ret) {
2210             sum_alloc += num;
2211         }
2212         if (num == 0) {
2213             count -= remaining;
2214             remaining = 0;
2215         }
2216     }
2217 
2218     cvtstr(start, s1, sizeof(s1));
2219 
2220     printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
2221            sum_alloc, count, s1);
2222     return 0;
2223 }
2224 
2225 static const cmdinfo_t alloc_cmd = {
2226     .name       = "alloc",
2227     .altname    = "a",
2228     .argmin     = 1,
2229     .argmax     = 2,
2230     .cfunc      = alloc_f,
2231     .args       = "offset [count]",
2232     .oneline    = "checks if offset is allocated in the file",
2233 };
2234 
2235 
map_is_allocated(BlockDriverState * bs,int64_t offset,int64_t bytes,int64_t * pnum)2236 static int map_is_allocated(BlockDriverState *bs, int64_t offset,
2237                             int64_t bytes, int64_t *pnum)
2238 {
2239     int64_t num;
2240     int ret, firstret;
2241 
2242     ret = bdrv_is_allocated(bs, offset, bytes, &num);
2243     if (ret < 0) {
2244         return ret;
2245     }
2246 
2247     firstret = ret;
2248     *pnum = num;
2249 
2250     while (bytes > 0 && ret == firstret) {
2251         offset += num;
2252         bytes -= num;
2253 
2254         ret = bdrv_is_allocated(bs, offset, bytes, &num);
2255         if (ret == firstret && num) {
2256             *pnum += num;
2257         } else {
2258             break;
2259         }
2260     }
2261 
2262     return firstret;
2263 }
2264 
map_f(BlockBackend * blk,int argc,char ** argv)2265 static int map_f(BlockBackend *blk, int argc, char **argv)
2266 {
2267     int64_t offset, bytes;
2268     char s1[64], s2[64];
2269     int64_t num;
2270     int ret;
2271     const char *retstr;
2272 
2273     offset = 0;
2274     bytes = blk_getlength(blk);
2275     if (bytes < 0) {
2276         error_report("Failed to query image length: %s", strerror(-bytes));
2277         return bytes;
2278     }
2279 
2280     while (bytes) {
2281         ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
2282         if (ret < 0) {
2283             error_report("Failed to get allocation status: %s", strerror(-ret));
2284             return ret;
2285         } else if (!num) {
2286             error_report("Unexpected end of image");
2287             return -EIO;
2288         }
2289 
2290         retstr = ret ? "    allocated" : "not allocated";
2291         cvtstr(num, s1, sizeof(s1));
2292         cvtstr(offset, s2, sizeof(s2));
2293         printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
2294                s1, num, retstr, s2, offset);
2295 
2296         offset += num;
2297         bytes -= num;
2298     }
2299 
2300     return 0;
2301 }
2302 
2303 static const cmdinfo_t map_cmd = {
2304        .name           = "map",
2305        .argmin         = 0,
2306        .argmax         = 0,
2307        .cfunc          = map_f,
2308        .args           = "",
2309        .oneline        = "prints the allocated areas of a file",
2310 };
2311 
reopen_help(void)2312 static void reopen_help(void)
2313 {
2314     printf(
2315 "\n"
2316 " Changes the open options of an already opened image\n"
2317 "\n"
2318 " Example:\n"
2319 " 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2320 "\n"
2321 " -r, -- Reopen the image read-only\n"
2322 " -w, -- Reopen the image read-write\n"
2323 " -c, -- Change the cache mode to the given value\n"
2324 " -o, -- Changes block driver options (cf. 'open' command)\n"
2325 "\n");
2326 }
2327 
2328 static int reopen_f(BlockBackend *blk, int argc, char **argv);
2329 
2330 static QemuOptsList reopen_opts = {
2331     .name = "reopen",
2332     .merge_lists = true,
2333     .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2334     .desc = {
2335         /* no elements => accept any params */
2336         { /* end of list */ }
2337     },
2338 };
2339 
2340 static const cmdinfo_t reopen_cmd = {
2341        .name           = "reopen",
2342        .argmin         = 0,
2343        .argmax         = -1,
2344        .cfunc          = reopen_f,
2345        .args           = "[(-r|-w)] [-c cache] [-o options]",
2346        .oneline        = "reopens an image with new options",
2347        .help           = reopen_help,
2348 };
2349 
reopen_f(BlockBackend * blk,int argc,char ** argv)2350 static int reopen_f(BlockBackend *blk, int argc, char **argv)
2351 {
2352     BlockDriverState *bs = blk_bs(blk);
2353     QemuOpts *qopts;
2354     QDict *opts;
2355     int c;
2356     int flags = bs->open_flags;
2357     bool writethrough = !blk_enable_write_cache(blk);
2358     bool has_rw_option = false;
2359     bool has_cache_option = false;
2360     Error *local_err = NULL;
2361 
2362     while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
2363         switch (c) {
2364         case 'c':
2365             if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
2366                 error_report("Invalid cache option: %s", optarg);
2367                 return -EINVAL;
2368             }
2369             has_cache_option = true;
2370             break;
2371         case 'o':
2372             if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2373                 qemu_opts_reset(&reopen_opts);
2374                 return -EINVAL;
2375             }
2376             break;
2377         case 'r':
2378             if (has_rw_option) {
2379                 error_report("Only one -r/-w option may be given");
2380                 return -EINVAL;
2381             }
2382             flags &= ~BDRV_O_RDWR;
2383             has_rw_option = true;
2384             break;
2385         case 'w':
2386             if (has_rw_option) {
2387                 error_report("Only one -r/-w option may be given");
2388                 return -EINVAL;
2389             }
2390             flags |= BDRV_O_RDWR;
2391             has_rw_option = true;
2392             break;
2393         default:
2394             qemu_opts_reset(&reopen_opts);
2395             qemuio_command_usage(&reopen_cmd);
2396             return -EINVAL;
2397         }
2398     }
2399 
2400     if (optind != argc) {
2401         qemu_opts_reset(&reopen_opts);
2402         qemuio_command_usage(&reopen_cmd);
2403         return -EINVAL;
2404     }
2405 
2406     if (!writethrough != blk_enable_write_cache(blk) &&
2407         blk_get_attached_dev(blk))
2408     {
2409         error_report("Cannot change cache.writeback: Device attached");
2410         qemu_opts_reset(&reopen_opts);
2411         return -EBUSY;
2412     }
2413 
2414     if (!(flags & BDRV_O_RDWR)) {
2415         uint64_t orig_perm, orig_shared_perm;
2416 
2417         bdrv_drain(bs);
2418 
2419         blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2420         blk_set_perm(blk,
2421                      orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2422                      orig_shared_perm,
2423                      &error_abort);
2424     }
2425 
2426     qopts = qemu_opts_find(&reopen_opts, NULL);
2427     opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
2428     qemu_opts_reset(&reopen_opts);
2429 
2430     if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2431         if (has_rw_option) {
2432             error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2433             qobject_unref(opts);
2434             return -EINVAL;
2435         }
2436     } else {
2437         qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2438     }
2439 
2440     if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2441         qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2442         if (has_cache_option) {
2443             error_report("Cannot set both -c and the cache options");
2444             qobject_unref(opts);
2445             return -EINVAL;
2446         }
2447     } else {
2448         qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2449         qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2450     }
2451 
2452     bdrv_reopen(bs, opts, true, &local_err);
2453 
2454     if (local_err) {
2455         error_report_err(local_err);
2456         return -EINVAL;
2457     }
2458 
2459     blk_set_enable_write_cache(blk, !writethrough);
2460     return 0;
2461 }
2462 
break_f(BlockBackend * blk,int argc,char ** argv)2463 static int break_f(BlockBackend *blk, int argc, char **argv)
2464 {
2465     int ret;
2466 
2467     ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
2468     if (ret < 0) {
2469         printf("Could not set breakpoint: %s\n", strerror(-ret));
2470         return ret;
2471     }
2472 
2473     return 0;
2474 }
2475 
remove_break_f(BlockBackend * blk,int argc,char ** argv)2476 static int remove_break_f(BlockBackend *blk, int argc, char **argv)
2477 {
2478     int ret;
2479 
2480     ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
2481     if (ret < 0) {
2482         printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
2483         return ret;
2484     }
2485 
2486     return 0;
2487 }
2488 
2489 static const cmdinfo_t break_cmd = {
2490        .name           = "break",
2491        .argmin         = 2,
2492        .argmax         = 2,
2493        .cfunc          = break_f,
2494        .args           = "event tag",
2495        .oneline        = "sets a breakpoint on event and tags the stopped "
2496                          "request as tag",
2497 };
2498 
2499 static const cmdinfo_t remove_break_cmd = {
2500        .name           = "remove_break",
2501        .argmin         = 1,
2502        .argmax         = 1,
2503        .cfunc          = remove_break_f,
2504        .args           = "tag",
2505        .oneline        = "remove a breakpoint by tag",
2506 };
2507 
resume_f(BlockBackend * blk,int argc,char ** argv)2508 static int resume_f(BlockBackend *blk, int argc, char **argv)
2509 {
2510     int ret;
2511 
2512     ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
2513     if (ret < 0) {
2514         printf("Could not resume request: %s\n", strerror(-ret));
2515         return ret;
2516     }
2517 
2518     return 0;
2519 }
2520 
2521 static const cmdinfo_t resume_cmd = {
2522        .name           = "resume",
2523        .argmin         = 1,
2524        .argmax         = 1,
2525        .cfunc          = resume_f,
2526        .args           = "tag",
2527        .oneline        = "resumes the request tagged as tag",
2528 };
2529 
wait_break_f(BlockBackend * blk,int argc,char ** argv)2530 static int wait_break_f(BlockBackend *blk, int argc, char **argv)
2531 {
2532     while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2533         aio_poll(blk_get_aio_context(blk), true);
2534     }
2535     return 0;
2536 }
2537 
2538 static const cmdinfo_t wait_break_cmd = {
2539        .name           = "wait_break",
2540        .argmin         = 1,
2541        .argmax         = 1,
2542        .cfunc          = wait_break_f,
2543        .args           = "tag",
2544        .oneline        = "waits for the suspension of a request",
2545 };
2546 
abort_f(BlockBackend * blk,int argc,char ** argv)2547 static int abort_f(BlockBackend *blk, int argc, char **argv)
2548 {
2549     abort();
2550 }
2551 
2552 static const cmdinfo_t abort_cmd = {
2553        .name           = "abort",
2554        .cfunc          = abort_f,
2555        .flags          = CMD_NOFILE_OK,
2556        .oneline        = "simulate a program crash using abort(3)",
2557 };
2558 
sigraise_help(void)2559 static void sigraise_help(void)
2560 {
2561     printf(
2562 "\n"
2563 " raises the given signal\n"
2564 "\n"
2565 " Example:\n"
2566 " 'sigraise %i' - raises SIGTERM\n"
2567 "\n"
2568 " Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2569 " given to sigraise.\n"
2570 "\n", SIGTERM);
2571 }
2572 
2573 static int sigraise_f(BlockBackend *blk, int argc, char **argv);
2574 
2575 static const cmdinfo_t sigraise_cmd = {
2576     .name       = "sigraise",
2577     .cfunc      = sigraise_f,
2578     .argmin     = 1,
2579     .argmax     = 1,
2580     .flags      = CMD_NOFILE_OK,
2581     .args       = "signal",
2582     .oneline    = "raises a signal",
2583     .help       = sigraise_help,
2584 };
2585 
sigraise_f(BlockBackend * blk,int argc,char ** argv)2586 static int sigraise_f(BlockBackend *blk, int argc, char **argv)
2587 {
2588     int64_t sig = cvtnum(argv[1]);
2589     if (sig < 0) {
2590         print_cvtnum_err(sig, argv[1]);
2591         return sig;
2592     } else if (sig > NSIG) {
2593         printf("signal argument '%s' is too large to be a valid signal\n",
2594                argv[1]);
2595         return -EINVAL;
2596     }
2597 
2598     /* Using raise() to kill this process does not necessarily flush all open
2599      * streams. At least stdout and stderr (although the latter should be
2600      * non-buffered anyway) should be flushed, though. */
2601     fflush(stdout);
2602     fflush(stderr);
2603 
2604     raise(sig);
2605 
2606     return 0;
2607 }
2608 
sleep_cb(void * opaque)2609 static void sleep_cb(void *opaque)
2610 {
2611     bool *expired = opaque;
2612     *expired = true;
2613 }
2614 
sleep_f(BlockBackend * blk,int argc,char ** argv)2615 static int sleep_f(BlockBackend *blk, int argc, char **argv)
2616 {
2617     char *endptr;
2618     long ms;
2619     struct QEMUTimer *timer;
2620     bool expired = false;
2621 
2622     ms = strtol(argv[1], &endptr, 0);
2623     if (ms < 0 || *endptr != '\0') {
2624         printf("%s is not a valid number\n", argv[1]);
2625         return -EINVAL;
2626     }
2627 
2628     timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2629     timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2630 
2631     while (!expired) {
2632         main_loop_wait(false);
2633     }
2634 
2635     timer_free(timer);
2636     return 0;
2637 }
2638 
2639 static const cmdinfo_t sleep_cmd = {
2640        .name           = "sleep",
2641        .argmin         = 1,
2642        .argmax         = 1,
2643        .cfunc          = sleep_f,
2644        .flags          = CMD_NOFILE_OK,
2645        .oneline        = "waits for the given value in milliseconds",
2646 };
2647 
help_oneline(const char * cmd,const cmdinfo_t * ct)2648 static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2649 {
2650     printf("%s ", cmd);
2651 
2652     if (ct->args) {
2653         printf("%s ", ct->args);
2654     }
2655     printf("-- %s\n", ct->oneline);
2656 }
2657 
help_onecmd(const char * cmd,const cmdinfo_t * ct)2658 static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2659 {
2660     help_oneline(cmd, ct);
2661     if (ct->help) {
2662         ct->help();
2663     }
2664 }
2665 
help_all(void)2666 static void help_all(void)
2667 {
2668     const cmdinfo_t *ct;
2669 
2670     for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2671         help_oneline(ct->name, ct);
2672     }
2673     printf("\nUse 'help commandname' for extended help.\n");
2674 }
2675 
help_f(BlockBackend * blk,int argc,char ** argv)2676 static int help_f(BlockBackend *blk, int argc, char **argv)
2677 {
2678     const cmdinfo_t *ct;
2679 
2680     if (argc < 2) {
2681         help_all();
2682         return 0;
2683     }
2684 
2685     ct = find_command(argv[1]);
2686     if (ct == NULL) {
2687         printf("command %s not found\n", argv[1]);
2688         return -EINVAL;
2689     }
2690 
2691     help_onecmd(argv[1], ct);
2692     return 0;
2693 }
2694 
2695 static const cmdinfo_t help_cmd = {
2696     .name       = "help",
2697     .altname    = "?",
2698     .cfunc      = help_f,
2699     .argmin     = 0,
2700     .argmax     = 1,
2701     .flags      = CMD_FLAG_GLOBAL,
2702     .args       = "[command]",
2703     .oneline    = "help for one or all commands",
2704 };
2705 
2706 /*
2707  * Called with aio context of blk acquired. Or with qemu_get_aio_context()
2708  * context acquired if blk is NULL.
2709  */
qemuio_command(BlockBackend * blk,const char * cmd)2710 int qemuio_command(BlockBackend *blk, const char *cmd)
2711 {
2712     char *input;
2713     const cmdinfo_t *ct;
2714     char **v;
2715     int c;
2716     int ret = 0;
2717 
2718     input = g_strdup(cmd);
2719     v = breakline(input, &c);
2720     if (c) {
2721         ct = find_command(v[0]);
2722         if (ct) {
2723             ret = command(blk, ct, c, v);
2724         } else {
2725             fprintf(stderr, "command \"%s\" not found\n", v[0]);
2726             ret = -EINVAL;
2727         }
2728     }
2729     g_free(input);
2730     g_free(v);
2731 
2732     return ret;
2733 }
2734 
init_qemuio_commands(void)2735 static void __attribute((constructor)) init_qemuio_commands(void)
2736 {
2737     /* initialize commands */
2738     qemuio_add_command(&help_cmd);
2739     qemuio_add_command(&read_cmd);
2740     qemuio_add_command(&readv_cmd);
2741     qemuio_add_command(&write_cmd);
2742     qemuio_add_command(&writev_cmd);
2743     qemuio_add_command(&aio_read_cmd);
2744     qemuio_add_command(&aio_write_cmd);
2745     qemuio_add_command(&aio_flush_cmd);
2746     qemuio_add_command(&flush_cmd);
2747     qemuio_add_command(&zone_report_cmd);
2748     qemuio_add_command(&zone_open_cmd);
2749     qemuio_add_command(&zone_close_cmd);
2750     qemuio_add_command(&zone_finish_cmd);
2751     qemuio_add_command(&zone_reset_cmd);
2752     qemuio_add_command(&zone_append_cmd);
2753     qemuio_add_command(&truncate_cmd);
2754     qemuio_add_command(&length_cmd);
2755     qemuio_add_command(&info_cmd);
2756     qemuio_add_command(&discard_cmd);
2757     qemuio_add_command(&alloc_cmd);
2758     qemuio_add_command(&map_cmd);
2759     qemuio_add_command(&reopen_cmd);
2760     qemuio_add_command(&break_cmd);
2761     qemuio_add_command(&remove_break_cmd);
2762     qemuio_add_command(&resume_cmd);
2763     qemuio_add_command(&wait_break_cmd);
2764     qemuio_add_command(&abort_cmd);
2765     qemuio_add_command(&sleep_cmd);
2766     qemuio_add_command(&sigraise_cmd);
2767 }
2768