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