blob: 8904733961ed4e3707fe6c72d7542b2469372434 [file] [log] [blame]
Kevin Wolf797ac582013-06-05 14:19:31 +02001/*
2 * Command line utility to exercise the QEMU I/O path.
3 *
Eric Blake093ea232016-05-07 21:16:43 -06004 * Copyright (C) 2009-2016 Red Hat, Inc.
Kevin Wolf797ac582013-06-05 14:19:31 +02005 * 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
Peter Maydell80c71a22016-01-18 18:01:42 +000011#include "qemu/osdep.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010012#include "qapi/error.h"
Alberto Garciadc900c32018-11-12 16:00:42 +020013#include "qapi/qmp/qdict.h"
Kevin Wolf3d219942013-06-05 14:19:39 +020014#include "qemu-io.h"
Max Reitz4c7b7e92015-02-05 13:58:22 -050015#include "sysemu/block-backend.h"
16#include "block/block.h"
17#include "block/block_int.h" /* for info_f() */
Max Reitza8d8ecb2013-10-09 10:46:17 +020018#include "block/qapi.h"
Markus Armbrusterd49b6832015-03-17 18:29:20 +010019#include "qemu/error-report.h"
Alex Bligh6a1751b2013-08-21 16:02:47 +010020#include "qemu/main-loop.h"
Markus Armbruster922a01a2018-02-01 12:18:46 +010021#include "qemu/option.h"
Kevin Wolfcd33d022014-01-15 15:39:10 +010022#include "qemu/timer.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020023#include "qemu/cutils.h"
Kevin Wolf797ac582013-06-05 14:19:31 +020024
25#define CMD_NOFILE_OK 0x01
26
Stefan Weilf9883882014-03-05 22:23:00 +010027bool qemuio_misalign;
Kevin Wolf797ac582013-06-05 14:19:31 +020028
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020029static cmdinfo_t *cmdtab;
30static int ncmds;
31
32static int compare_cmdname(const void *a, const void *b)
33{
34 return strcmp(((const cmdinfo_t *)a)->name,
35 ((const cmdinfo_t *)b)->name);
36}
37
38void qemuio_add_command(const cmdinfo_t *ci)
39{
Peter Maydell6aabeb52017-03-31 14:38:49 +010040 /* ci->perm assumes a file is open, but the GLOBAL and NOFILE_OK
41 * flags allow it not to be, so that combination is invalid.
42 * Catch it now rather than letting it manifest as a crash if a
43 * particular set of command line options are used.
44 */
45 assert(ci->perm == 0 ||
46 (ci->flags & (CMD_FLAG_GLOBAL | CMD_NOFILE_OK)) == 0);
Markus Armbruster02c4f262014-08-19 10:31:09 +020047 cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020048 cmdtab[ncmds - 1] = *ci;
49 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
50}
51
Max Reitzb444d0e2018-05-09 21:42:58 +020052void qemuio_command_usage(const cmdinfo_t *ci)
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020053{
54 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020055}
56
Max Reitz4c7b7e92015-02-05 13:58:22 -050057static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020058{
59 if (ct->flags & CMD_FLAG_GLOBAL) {
60 return 1;
61 }
Max Reitz4c7b7e92015-02-05 13:58:22 -050062 if (!(ct->flags & CMD_NOFILE_OK) && !blk) {
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020063 fprintf(stderr, "no file open, try 'help open'\n");
64 return 0;
65 }
66 return 1;
67}
68
Max Reitzb32d7a32018-05-09 21:42:59 +020069static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
70 char **argv)
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020071{
72 char *cmd = argv[0];
73
Max Reitz4c7b7e92015-02-05 13:58:22 -050074 if (!init_check_command(blk, ct)) {
Max Reitzb32d7a32018-05-09 21:42:59 +020075 return -EINVAL;
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020076 }
77
78 if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
79 if (ct->argmax == -1) {
80 fprintf(stderr,
81 "bad argument count %d to %s, expected at least %d arguments\n",
82 argc-1, cmd, ct->argmin);
83 } else if (ct->argmin == ct->argmax) {
84 fprintf(stderr,
85 "bad argument count %d to %s, expected %d arguments\n",
86 argc-1, cmd, ct->argmin);
87 } else {
88 fprintf(stderr,
89 "bad argument count %d to %s, expected between %d and %d arguments\n",
90 argc-1, cmd, ct->argmin, ct->argmax);
91 }
Max Reitzb32d7a32018-05-09 21:42:59 +020092 return -EINVAL;
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +020093 }
Kevin Wolf887354b2017-02-10 16:24:56 +010094
95 /* Request additional permissions if necessary for this command. The caller
96 * is responsible for restoring the original permissions afterwards if this
97 * is what it wants. */
98 if (ct->perm && blk_is_available(blk)) {
99 uint64_t orig_perm, orig_shared_perm;
100 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
101
102 if (ct->perm & ~orig_perm) {
103 uint64_t new_perm;
104 Error *local_err = NULL;
105 int ret;
106
107 new_perm = orig_perm | ct->perm;
108
109 ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
110 if (ret < 0) {
111 error_report_err(local_err);
Max Reitzb32d7a32018-05-09 21:42:59 +0200112 return ret;
Kevin Wolf887354b2017-02-10 16:24:56 +0100113 }
114 }
115 }
116
Richard W.M. Jonesd339d762019-01-18 10:11:14 +0000117 qemu_reset_optind();
Max Reitzb32d7a32018-05-09 21:42:59 +0200118 return ct->cfunc(blk, argc, argv);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +0200119}
120
121static const cmdinfo_t *find_command(const char *cmd)
122{
123 cmdinfo_t *ct;
124
125 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
126 if (strcmp(ct->name, cmd) == 0 ||
127 (ct->altname && strcmp(ct->altname, cmd) == 0))
128 {
129 return (const cmdinfo_t *)ct;
130 }
131 }
132 return NULL;
133}
134
Stefan Hajnoczi46940202013-11-14 11:54:18 +0100135/* Invoke fn() for commands with a matching prefix */
136void qemuio_complete_command(const char *input,
137 void (*fn)(const char *cmd, void *opaque),
138 void *opaque)
139{
140 cmdinfo_t *ct;
141 size_t input_len = strlen(input);
142
143 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
144 if (strncmp(input, ct->name, input_len) == 0) {
145 fn(ct->name, opaque);
146 }
147 }
148}
149
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +0200150static char **breakline(char *input, int *count)
151{
152 int c = 0;
153 char *p;
Markus Armbruster5839e532014-08-19 10:31:08 +0200154 char **rval = g_new0(char *, 1);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +0200155
156 while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
157 if (!*p) {
158 continue;
159 }
160 c++;
Markus Armbruster08193dd2014-08-19 10:31:10 +0200161 rval = g_renew(char *, rval, (c + 1));
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +0200162 rval[c - 1] = p;
163 rval[c] = NULL;
164 }
165 *count = c;
166 return rval;
167}
168
Kevin Wolf797ac582013-06-05 14:19:31 +0200169static int64_t cvtnum(const char *s)
170{
Markus Armbrusterf17fd4f2017-02-21 21:14:06 +0100171 int err;
Markus Armbrusterf46bfdb2017-02-21 21:14:07 +0100172 uint64_t value;
John Snowef5a7882015-11-05 18:53:03 -0500173
Markus Armbrusterf17fd4f2017-02-21 21:14:06 +0100174 err = qemu_strtosz(s, NULL, &value);
175 if (err < 0) {
176 return err;
177 }
Markus Armbrusterf46bfdb2017-02-21 21:14:07 +0100178 if (value > INT64_MAX) {
179 return -ERANGE;
180 }
Markus Armbrusterf17fd4f2017-02-21 21:14:06 +0100181 return value;
Kevin Wolf797ac582013-06-05 14:19:31 +0200182}
183
John Snowa9ecfa02015-11-05 18:53:04 -0500184static void print_cvtnum_err(int64_t rc, const char *arg)
185{
186 switch (rc) {
187 case -EINVAL:
188 printf("Parsing error: non-numeric argument,"
189 " or extraneous/unrecognized suffix -- %s\n", arg);
190 break;
191 case -ERANGE:
192 printf("Parsing error: argument too large -- %s\n", arg);
193 break;
194 default:
195 printf("Parsing error: %s\n", arg);
196 }
197}
198
Kevin Wolf0b613882013-06-05 14:19:38 +0200199#define EXABYTES(x) ((long long)(x) << 60)
200#define PETABYTES(x) ((long long)(x) << 50)
201#define TERABYTES(x) ((long long)(x) << 40)
202#define GIGABYTES(x) ((long long)(x) << 30)
203#define MEGABYTES(x) ((long long)(x) << 20)
204#define KILOBYTES(x) ((long long)(x) << 10)
205
206#define TO_EXABYTES(x) ((x) / EXABYTES(1))
207#define TO_PETABYTES(x) ((x) / PETABYTES(1))
208#define TO_TERABYTES(x) ((x) / TERABYTES(1))
209#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
210#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
211#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
212
213static void cvtstr(double value, char *str, size_t size)
214{
215 char *trim;
216 const char *suffix;
217
218 if (value >= EXABYTES(1)) {
219 suffix = " EiB";
220 snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
221 } else if (value >= PETABYTES(1)) {
222 suffix = " PiB";
223 snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
224 } else if (value >= TERABYTES(1)) {
225 suffix = " TiB";
226 snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
227 } else if (value >= GIGABYTES(1)) {
228 suffix = " GiB";
229 snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
230 } else if (value >= MEGABYTES(1)) {
231 suffix = " MiB";
232 snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
233 } else if (value >= KILOBYTES(1)) {
234 suffix = " KiB";
235 snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
236 } else {
237 suffix = " bytes";
238 snprintf(str, size - 6, "%f", value);
239 }
240
241 trim = strstr(str, ".000");
242 if (trim) {
243 strcpy(trim, suffix);
244 } else {
245 strcat(str, suffix);
246 }
247}
248
249
250
Alex Bennée50290c02019-05-29 17:16:32 +0100251static struct timespec tsub(struct timespec t1, struct timespec t2)
Kevin Wolf0b613882013-06-05 14:19:38 +0200252{
Alex Bennée50290c02019-05-29 17:16:32 +0100253 t1.tv_nsec -= t2.tv_nsec;
254 if (t1.tv_nsec < 0) {
255 t1.tv_nsec += NANOSECONDS_PER_SECOND;
Kevin Wolf0b613882013-06-05 14:19:38 +0200256 t1.tv_sec--;
257 }
258 t1.tv_sec -= t2.tv_sec;
259 return t1;
260}
261
Alex Bennée50290c02019-05-29 17:16:32 +0100262static double tdiv(double value, struct timespec tv)
Kevin Wolf0b613882013-06-05 14:19:38 +0200263{
Alex Bennée50290c02019-05-29 17:16:32 +0100264 double seconds = tv.tv_sec + (tv.tv_nsec / 1e9);
265 return value / seconds;
Kevin Wolf0b613882013-06-05 14:19:38 +0200266}
267
268#define HOURS(sec) ((sec) / (60 * 60))
269#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
270#define SECONDS(sec) ((sec) % 60)
271
272enum {
273 DEFAULT_TIME = 0x0,
274 TERSE_FIXED_TIME = 0x1,
275 VERBOSE_FIXED_TIME = 0x2,
276};
277
Alex Bennée50290c02019-05-29 17:16:32 +0100278static void timestr(struct timespec *tv, char *ts, size_t size, int format)
Kevin Wolf0b613882013-06-05 14:19:38 +0200279{
Alex Bennée50290c02019-05-29 17:16:32 +0100280 double frac_sec = tv->tv_nsec / 1e9;
Kevin Wolf0b613882013-06-05 14:19:38 +0200281
282 if (format & TERSE_FIXED_TIME) {
283 if (!HOURS(tv->tv_sec)) {
Alex Bennée50290c02019-05-29 17:16:32 +0100284 snprintf(ts, size, "%u:%05.2f",
285 (unsigned int) MINUTES(tv->tv_sec),
286 SECONDS(tv->tv_sec) + frac_sec);
Kevin Wolf0b613882013-06-05 14:19:38 +0200287 return;
288 }
289 format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
290 }
291
292 if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
Alex Bennée50290c02019-05-29 17:16:32 +0100293 snprintf(ts, size, "%u:%02u:%05.2f",
Kevin Wolf0b613882013-06-05 14:19:38 +0200294 (unsigned int) HOURS(tv->tv_sec),
295 (unsigned int) MINUTES(tv->tv_sec),
Alex Bennée50290c02019-05-29 17:16:32 +0100296 SECONDS(tv->tv_sec) + frac_sec);
Kevin Wolf0b613882013-06-05 14:19:38 +0200297 } else {
Alex Bennée50290c02019-05-29 17:16:32 +0100298 snprintf(ts, size, "%05.2f sec", frac_sec);
Kevin Wolf0b613882013-06-05 14:19:38 +0200299 }
300}
301
Kevin Wolf797ac582013-06-05 14:19:31 +0200302/*
303 * Parse the pattern argument to various sub-commands.
304 *
305 * Because the pattern is used as an argument to memset it must evaluate
306 * to an unsigned integer that fits into a single byte.
307 */
308static int parse_pattern(const char *arg)
309{
310 char *endptr = NULL;
311 long pattern;
312
313 pattern = strtol(arg, &endptr, 0);
314 if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
315 printf("%s is not a valid pattern byte\n", arg);
316 return -1;
317 }
318
319 return pattern;
320}
321
322/*
323 * Memory allocation helpers.
324 *
325 * Make sure memory is aligned by default, or purposefully misaligned if
326 * that is specified on the command line.
327 */
328
329#define MISALIGN_OFFSET 16
Max Reitz4c7b7e92015-02-05 13:58:22 -0500330static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern)
Kevin Wolf797ac582013-06-05 14:19:31 +0200331{
332 void *buf;
333
334 if (qemuio_misalign) {
335 len += MISALIGN_OFFSET;
336 }
Max Reitz4c7b7e92015-02-05 13:58:22 -0500337 buf = blk_blockalign(blk, len);
Kevin Wolf797ac582013-06-05 14:19:31 +0200338 memset(buf, pattern, len);
339 if (qemuio_misalign) {
340 buf += MISALIGN_OFFSET;
341 }
342 return buf;
343}
344
345static void qemu_io_free(void *p)
346{
347 if (qemuio_misalign) {
348 p -= MISALIGN_OFFSET;
349 }
350 qemu_vfree(p);
351}
352
John Snow9b0beaf2015-11-05 18:53:02 -0500353static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
Kevin Wolf797ac582013-06-05 14:19:31 +0200354{
John Snow9b0beaf2015-11-05 18:53:02 -0500355 uint64_t i;
356 int j;
Kevin Wolf797ac582013-06-05 14:19:31 +0200357 const uint8_t *p;
358
359 for (i = 0, p = buffer; i < len; i += 16) {
360 const uint8_t *s = p;
361
362 printf("%08" PRIx64 ": ", offset + i);
363 for (j = 0; j < 16 && i + j < len; j++, p++) {
364 printf("%02x ", *p);
365 }
366 printf(" ");
367 for (j = 0; j < 16 && i + j < len; j++, s++) {
368 if (isalnum(*s)) {
369 printf("%c", *s);
370 } else {
371 printf(".");
372 }
373 }
374 printf("\n");
375 }
376}
377
Alex Bennée50290c02019-05-29 17:16:32 +0100378static void print_report(const char *op, struct timespec *t, int64_t offset,
Eric Blakedc388522016-05-07 21:16:42 -0600379 int64_t count, int64_t total, int cnt, bool Cflag)
Kevin Wolf797ac582013-06-05 14:19:31 +0200380{
381 char s1[64], s2[64], ts[64];
382
383 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
384 if (!Cflag) {
385 cvtstr((double)total, s1, sizeof(s1));
386 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
John Snow9b0beaf2015-11-05 18:53:02 -0500387 printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200388 op, total, count, offset);
389 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
390 s1, cnt, ts, s2, tdiv((double)cnt, *t));
391 } else {/* bytes,ops,time,bytes/sec,ops/sec */
John Snow9b0beaf2015-11-05 18:53:02 -0500392 printf("%"PRId64",%d,%s,%.3f,%.3f\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200393 total, cnt, ts,
394 tdiv((double)total, *t),
395 tdiv((double)cnt, *t));
396 }
397}
398
399/*
400 * Parse multiple length statements for vectored I/O, and construct an I/O
401 * vector matching it.
402 */
403static void *
Max Reitz4c7b7e92015-02-05 13:58:22 -0500404create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
Kevin Wolf797ac582013-06-05 14:19:31 +0200405 int pattern)
406{
407 size_t *sizes = g_new0(size_t, nr_iov);
408 size_t count = 0;
409 void *buf = NULL;
410 void *p;
411 int i;
412
413 for (i = 0; i < nr_iov; i++) {
414 char *arg = argv[i];
415 int64_t len;
416
417 len = cvtnum(arg);
418 if (len < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500419 print_cvtnum_err(len, arg);
Kevin Wolf797ac582013-06-05 14:19:31 +0200420 goto fail;
421 }
422
Alberto Garcia3026c462017-01-31 18:09:54 +0200423 if (len > BDRV_REQUEST_MAX_BYTES) {
424 printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg,
425 (uint64_t)BDRV_REQUEST_MAX_BYTES);
426 goto fail;
427 }
428
429 if (count > BDRV_REQUEST_MAX_BYTES - len) {
430 printf("The total number of bytes exceed the maximum size %" PRIu64
431 "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES);
Kevin Wolf797ac582013-06-05 14:19:31 +0200432 goto fail;
433 }
434
Kevin Wolf797ac582013-06-05 14:19:31 +0200435 sizes[i] = len;
436 count += len;
437 }
438
439 qemu_iovec_init(qiov, nr_iov);
440
Max Reitz4c7b7e92015-02-05 13:58:22 -0500441 buf = p = qemu_io_alloc(blk, count, pattern);
Kevin Wolf797ac582013-06-05 14:19:31 +0200442
443 for (i = 0; i < nr_iov; i++) {
444 qemu_iovec_add(qiov, p, sizes[i]);
445 p += sizes[i];
446 }
447
448fail:
449 g_free(sizes);
450 return buf;
451}
452
John Snow9b0beaf2015-11-05 18:53:02 -0500453static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300454 int64_t bytes, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200455{
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300456 if (bytes > INT_MAX) {
John Snow9b0beaf2015-11-05 18:53:02 -0500457 return -ERANGE;
458 }
459
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300460 *total = blk_pread(blk, offset, (uint8_t *)buf, bytes);
Kevin Wolf797ac582013-06-05 14:19:31 +0200461 if (*total < 0) {
462 return *total;
463 }
464 return 1;
465}
466
John Snow9b0beaf2015-11-05 18:53:02 -0500467static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300468 int64_t bytes, int flags, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200469{
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300470 if (bytes > INT_MAX) {
John Snow9b0beaf2015-11-05 18:53:02 -0500471 return -ERANGE;
472 }
473
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300474 *total = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
Kevin Wolf797ac582013-06-05 14:19:31 +0200475 if (*total < 0) {
476 return *total;
477 }
478 return 1;
479}
480
481typedef struct {
Max Reitz4c7b7e92015-02-05 13:58:22 -0500482 BlockBackend *blk;
Kevin Wolf797ac582013-06-05 14:19:31 +0200483 int64_t offset;
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300484 int64_t bytes;
John Snow9b0beaf2015-11-05 18:53:02 -0500485 int64_t *total;
Eric Blake770e0e02016-05-07 21:16:44 -0600486 int flags;
Kevin Wolf797ac582013-06-05 14:19:31 +0200487 int ret;
488 bool done;
489} CoWriteZeroes;
490
Eric Blaked004bd52016-05-24 16:25:20 -0600491static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
Kevin Wolf797ac582013-06-05 14:19:31 +0200492{
493 CoWriteZeroes *data = opaque;
494
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300495 data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
Eric Blaked004bd52016-05-24 16:25:20 -0600496 data->flags);
Kevin Wolf797ac582013-06-05 14:19:31 +0200497 data->done = true;
498 if (data->ret < 0) {
499 *data->total = data->ret;
500 return;
501 }
502
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300503 *data->total = data->bytes;
Kevin Wolf797ac582013-06-05 14:19:31 +0200504}
505
Eric Blaked004bd52016-05-24 16:25:20 -0600506static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300507 int64_t bytes, int flags, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200508{
509 Coroutine *co;
510 CoWriteZeroes data = {
Max Reitz4c7b7e92015-02-05 13:58:22 -0500511 .blk = blk,
Kevin Wolf797ac582013-06-05 14:19:31 +0200512 .offset = offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300513 .bytes = bytes,
Kevin Wolf797ac582013-06-05 14:19:31 +0200514 .total = total,
Eric Blake770e0e02016-05-07 21:16:44 -0600515 .flags = flags,
Kevin Wolf797ac582013-06-05 14:19:31 +0200516 .done = false,
517 };
518
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300519 if (bytes > INT_MAX) {
John Snow9b0beaf2015-11-05 18:53:02 -0500520 return -ERANGE;
521 }
522
Paolo Bonzini0b8b8752016-07-04 19:10:01 +0200523 co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
Fam Zheng324ec3e2017-04-10 20:16:18 +0800524 bdrv_coroutine_enter(blk_bs(blk), co);
Kevin Wolf797ac582013-06-05 14:19:31 +0200525 while (!data.done) {
Max Reitz4c7b7e92015-02-05 13:58:22 -0500526 aio_poll(blk_get_aio_context(blk), true);
Kevin Wolf797ac582013-06-05 14:19:31 +0200527 }
528 if (data.ret < 0) {
529 return data.ret;
530 } else {
531 return 1;
532 }
533}
534
Max Reitz4c7b7e92015-02-05 13:58:22 -0500535static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300536 int64_t bytes, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200537{
538 int ret;
539
Alberto Garcia41ae31e2019-05-14 16:57:35 +0300540 if (bytes > BDRV_REQUEST_MAX_BYTES) {
John Snow9b0beaf2015-11-05 18:53:02 -0500541 return -ERANGE;
542 }
543
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300544 ret = blk_pwrite_compressed(blk, offset, buf, bytes);
Kevin Wolf797ac582013-06-05 14:19:31 +0200545 if (ret < 0) {
546 return ret;
547 }
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300548 *total = bytes;
Kevin Wolf797ac582013-06-05 14:19:31 +0200549 return 1;
550}
551
Max Reitz4c7b7e92015-02-05 13:58:22 -0500552static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset,
John Snow9b0beaf2015-11-05 18:53:02 -0500553 int64_t count, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200554{
John Snow9b0beaf2015-11-05 18:53:02 -0500555 if (count > INT_MAX) {
556 return -ERANGE;
557 }
558
Max Reitz4c7b7e92015-02-05 13:58:22 -0500559 *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count);
Kevin Wolf797ac582013-06-05 14:19:31 +0200560 if (*total < 0) {
561 return *total;
562 }
563 return 1;
564}
565
Max Reitz4c7b7e92015-02-05 13:58:22 -0500566static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset,
John Snow9b0beaf2015-11-05 18:53:02 -0500567 int64_t count, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200568{
John Snow9b0beaf2015-11-05 18:53:02 -0500569 if (count > INT_MAX) {
570 return -ERANGE;
571 }
572
Max Reitz4c7b7e92015-02-05 13:58:22 -0500573 *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count);
Kevin Wolf797ac582013-06-05 14:19:31 +0200574 if (*total < 0) {
575 return *total;
576 }
577 return 1;
578}
579
580#define NOT_DONE 0x7fffffff
581static void aio_rw_done(void *opaque, int ret)
582{
583 *(int *)opaque = ret;
584}
585
Max Reitz4c7b7e92015-02-05 13:58:22 -0500586static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
Kevin Wolf797ac582013-06-05 14:19:31 +0200587 int64_t offset, int *total)
588{
589 int async_ret = NOT_DONE;
590
Eric Blake7b3f9712016-05-06 10:26:44 -0600591 blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret);
Kevin Wolf797ac582013-06-05 14:19:31 +0200592 while (async_ret == NOT_DONE) {
593 main_loop_wait(false);
594 }
595
596 *total = qiov->size;
597 return async_ret < 0 ? async_ret : 1;
598}
599
Max Reitz4c7b7e92015-02-05 13:58:22 -0500600static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
Eric Blake770e0e02016-05-07 21:16:44 -0600601 int64_t offset, int flags, int *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200602{
603 int async_ret = NOT_DONE;
604
Eric Blake770e0e02016-05-07 21:16:44 -0600605 blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret);
Kevin Wolf797ac582013-06-05 14:19:31 +0200606 while (async_ret == NOT_DONE) {
607 main_loop_wait(false);
608 }
609
610 *total = qiov->size;
611 return async_ret < 0 ? async_ret : 1;
612}
613
Kevin Wolf797ac582013-06-05 14:19:31 +0200614static void read_help(void)
615{
616 printf(
617"\n"
618" reads a range of bytes from the given offset\n"
619"\n"
620" Example:\n"
621" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
622"\n"
623" Reads a segment of the currently open file, optionally dumping it to the\n"
624" standard output stream (with -v option) for subsequent inspection.\n"
625" -b, -- read from the VM state rather than the virtual disk\n"
626" -C, -- report statistics in a machine parsable format\n"
627" -l, -- length for pattern verification (only with -P)\n"
Eric Blake093ea232016-05-07 21:16:43 -0600628" -p, -- ignored for backwards compatibility\n"
Kevin Wolf797ac582013-06-05 14:19:31 +0200629" -P, -- use a pattern to verify read data\n"
630" -q, -- quiet mode, do not show I/O statistics\n"
631" -s, -- start offset for pattern verification (only with -P)\n"
632" -v, -- dump buffer to standard output\n"
633"\n");
634}
635
Max Reitzb32d7a32018-05-09 21:42:59 +0200636static int read_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +0200637
638static const cmdinfo_t read_cmd = {
639 .name = "read",
640 .altname = "r",
641 .cfunc = read_f,
642 .argmin = 2,
643 .argmax = -1,
Eric Blake093ea232016-05-07 21:16:43 -0600644 .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len",
Kevin Wolf797ac582013-06-05 14:19:31 +0200645 .oneline = "reads a number of bytes at a specified offset",
646 .help = read_help,
647};
648
Max Reitzb32d7a32018-05-09 21:42:59 +0200649static int read_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +0200650{
Alex Bennée50290c02019-05-29 17:16:32 +0100651 struct timespec t1, t2;
Eric Blake093ea232016-05-07 21:16:43 -0600652 bool Cflag = false, qflag = false, vflag = false;
Eric Blakedc388522016-05-07 21:16:42 -0600653 bool Pflag = false, sflag = false, lflag = false, bflag = false;
Max Reitzb32d7a32018-05-09 21:42:59 +0200654 int c, cnt, ret;
Kevin Wolf797ac582013-06-05 14:19:31 +0200655 char *buf;
656 int64_t offset;
John Snow9b0beaf2015-11-05 18:53:02 -0500657 int64_t count;
Kevin Wolf797ac582013-06-05 14:19:31 +0200658 /* Some compilers get confused and warn if this is not initialized. */
John Snow9b0beaf2015-11-05 18:53:02 -0500659 int64_t total = 0;
660 int pattern = 0;
661 int64_t pattern_offset = 0, pattern_count = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +0200662
Eric Blakeb062ad82015-05-12 09:10:56 -0600663 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +0200664 switch (c) {
665 case 'b':
Eric Blakedc388522016-05-07 21:16:42 -0600666 bflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200667 break;
668 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -0600669 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200670 break;
671 case 'l':
Eric Blakedc388522016-05-07 21:16:42 -0600672 lflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200673 pattern_count = cvtnum(optarg);
674 if (pattern_count < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500675 print_cvtnum_err(pattern_count, optarg);
Max Reitzb32d7a32018-05-09 21:42:59 +0200676 return pattern_count;
Kevin Wolf797ac582013-06-05 14:19:31 +0200677 }
678 break;
679 case 'p':
Eric Blake093ea232016-05-07 21:16:43 -0600680 /* Ignored for backwards compatibility */
Kevin Wolf797ac582013-06-05 14:19:31 +0200681 break;
682 case 'P':
Eric Blakedc388522016-05-07 21:16:42 -0600683 Pflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200684 pattern = parse_pattern(optarg);
685 if (pattern < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +0200686 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200687 }
688 break;
689 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -0600690 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200691 break;
692 case 's':
Eric Blakedc388522016-05-07 21:16:42 -0600693 sflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200694 pattern_offset = cvtnum(optarg);
695 if (pattern_offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500696 print_cvtnum_err(pattern_offset, optarg);
Max Reitzb32d7a32018-05-09 21:42:59 +0200697 return pattern_offset;
Kevin Wolf797ac582013-06-05 14:19:31 +0200698 }
699 break;
700 case 'v':
Eric Blakedc388522016-05-07 21:16:42 -0600701 vflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200702 break;
703 default:
Max Reitzb444d0e2018-05-09 21:42:58 +0200704 qemuio_command_usage(&read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200705 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200706 }
707 }
708
709 if (optind != argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +0200710 qemuio_command_usage(&read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200711 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200712 }
713
Kevin Wolf797ac582013-06-05 14:19:31 +0200714 offset = cvtnum(argv[optind]);
715 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500716 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +0200717 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +0200718 }
719
720 optind++;
721 count = cvtnum(argv[optind]);
722 if (count < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500723 print_cvtnum_err(count, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +0200724 return count;
Alberto Garcia3026c462017-01-31 18:09:54 +0200725 } else if (count > BDRV_REQUEST_MAX_BYTES) {
John Snow9b0beaf2015-11-05 18:53:02 -0500726 printf("length cannot exceed %" PRIu64 ", given %s\n",
Alberto Garcia3026c462017-01-31 18:09:54 +0200727 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +0200728 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200729 }
730
731 if (!Pflag && (lflag || sflag)) {
Max Reitzb444d0e2018-05-09 21:42:58 +0200732 qemuio_command_usage(&read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200733 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200734 }
735
736 if (!lflag) {
737 pattern_count = count - pattern_offset;
738 }
739
740 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
741 printf("pattern verification range exceeds end of read data\n");
Max Reitzb32d7a32018-05-09 21:42:59 +0200742 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200743 }
744
Eric Blake093ea232016-05-07 21:16:43 -0600745 if (bflag) {
Eric Blake1bce6b42017-04-29 14:14:11 -0500746 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
747 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200748 offset);
Max Reitzb32d7a32018-05-09 21:42:59 +0200749 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200750 }
Eric Blake1bce6b42017-04-29 14:14:11 -0500751 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
752 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200753 count);
Max Reitzb32d7a32018-05-09 21:42:59 +0200754 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200755 }
756 }
757
Max Reitz4c7b7e92015-02-05 13:58:22 -0500758 buf = qemu_io_alloc(blk, count, 0xab);
Kevin Wolf797ac582013-06-05 14:19:31 +0200759
Alex Bennée50290c02019-05-29 17:16:32 +0100760 clock_gettime(CLOCK_MONOTONIC, &t1);
Eric Blake7b3f9712016-05-06 10:26:44 -0600761 if (bflag) {
Max Reitzb32d7a32018-05-09 21:42:59 +0200762 ret = do_load_vmstate(blk, buf, offset, count, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +0200763 } else {
Max Reitzb32d7a32018-05-09 21:42:59 +0200764 ret = do_pread(blk, buf, offset, count, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +0200765 }
Alex Bennée50290c02019-05-29 17:16:32 +0100766 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +0200767
Max Reitzb32d7a32018-05-09 21:42:59 +0200768 if (ret < 0) {
769 printf("read failed: %s\n", strerror(-ret));
Kevin Wolf797ac582013-06-05 14:19:31 +0200770 goto out;
771 }
Max Reitzb32d7a32018-05-09 21:42:59 +0200772 cnt = ret;
773
774 ret = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +0200775
776 if (Pflag) {
777 void *cmp_buf = g_malloc(pattern_count);
778 memset(cmp_buf, pattern, pattern_count);
779 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
780 printf("Pattern verification failed at offset %"
John Snow9b0beaf2015-11-05 18:53:02 -0500781 PRId64 ", %"PRId64" bytes\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200782 offset + pattern_offset, pattern_count);
Max Reitzb32d7a32018-05-09 21:42:59 +0200783 ret = -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200784 }
785 g_free(cmp_buf);
786 }
787
788 if (qflag) {
789 goto out;
790 }
791
792 if (vflag) {
793 dump_buffer(buf, offset, count);
794 }
795
796 /* Finally, report back -- -C gives a parsable format */
797 t2 = tsub(t2, t1);
798 print_report("read", &t2, offset, count, total, cnt, Cflag);
799
800out:
801 qemu_io_free(buf);
Max Reitzb32d7a32018-05-09 21:42:59 +0200802 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +0200803}
804
805static void readv_help(void)
806{
807 printf(
808"\n"
809" reads a range of bytes from the given offset into multiple buffers\n"
810"\n"
811" Example:\n"
812" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
813"\n"
814" Reads a segment of the currently open file, optionally dumping it to the\n"
815" standard output stream (with -v option) for subsequent inspection.\n"
816" Uses multiple iovec buffers if more than one byte range is specified.\n"
817" -C, -- report statistics in a machine parsable format\n"
818" -P, -- use a pattern to verify read data\n"
819" -v, -- dump buffer to standard output\n"
820" -q, -- quiet mode, do not show I/O statistics\n"
821"\n");
822}
823
Max Reitzb32d7a32018-05-09 21:42:59 +0200824static int readv_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +0200825
826static const cmdinfo_t readv_cmd = {
827 .name = "readv",
828 .cfunc = readv_f,
829 .argmin = 2,
830 .argmax = -1,
Eric Blake093ea232016-05-07 21:16:43 -0600831 .args = "[-Cqv] [-P pattern] off len [len..]",
Kevin Wolf797ac582013-06-05 14:19:31 +0200832 .oneline = "reads a number of bytes at a specified offset",
833 .help = readv_help,
834};
835
Max Reitzb32d7a32018-05-09 21:42:59 +0200836static int readv_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +0200837{
Alex Bennée50290c02019-05-29 17:16:32 +0100838 struct timespec t1, t2;
Eric Blakedc388522016-05-07 21:16:42 -0600839 bool Cflag = false, qflag = false, vflag = false;
Max Reitzb32d7a32018-05-09 21:42:59 +0200840 int c, cnt, ret;
Kevin Wolf797ac582013-06-05 14:19:31 +0200841 char *buf;
842 int64_t offset;
843 /* Some compilers get confused and warn if this is not initialized. */
844 int total = 0;
845 int nr_iov;
846 QEMUIOVector qiov;
847 int pattern = 0;
Eric Blakedc388522016-05-07 21:16:42 -0600848 bool Pflag = false;
Kevin Wolf797ac582013-06-05 14:19:31 +0200849
Eric Blakeb062ad82015-05-12 09:10:56 -0600850 while ((c = getopt(argc, argv, "CP:qv")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +0200851 switch (c) {
852 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -0600853 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200854 break;
855 case 'P':
Eric Blakedc388522016-05-07 21:16:42 -0600856 Pflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200857 pattern = parse_pattern(optarg);
858 if (pattern < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +0200859 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200860 }
861 break;
862 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -0600863 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200864 break;
865 case 'v':
Eric Blakedc388522016-05-07 21:16:42 -0600866 vflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200867 break;
868 default:
Max Reitzb444d0e2018-05-09 21:42:58 +0200869 qemuio_command_usage(&readv_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200870 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200871 }
872 }
873
874 if (optind > argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +0200875 qemuio_command_usage(&readv_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200876 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200877 }
878
879
880 offset = cvtnum(argv[optind]);
881 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500882 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +0200883 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +0200884 }
885 optind++;
886
Kevin Wolf797ac582013-06-05 14:19:31 +0200887 nr_iov = argc - optind;
Max Reitz4c7b7e92015-02-05 13:58:22 -0500888 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
Kevin Wolf797ac582013-06-05 14:19:31 +0200889 if (buf == NULL) {
Max Reitzb32d7a32018-05-09 21:42:59 +0200890 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200891 }
892
Alex Bennée50290c02019-05-29 17:16:32 +0100893 clock_gettime(CLOCK_MONOTONIC, &t1);
Max Reitzb32d7a32018-05-09 21:42:59 +0200894 ret = do_aio_readv(blk, &qiov, offset, &total);
Alex Bennée50290c02019-05-29 17:16:32 +0100895 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +0200896
Max Reitzb32d7a32018-05-09 21:42:59 +0200897 if (ret < 0) {
898 printf("readv failed: %s\n", strerror(-ret));
Kevin Wolf797ac582013-06-05 14:19:31 +0200899 goto out;
900 }
Max Reitzb32d7a32018-05-09 21:42:59 +0200901 cnt = ret;
902
903 ret = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +0200904
905 if (Pflag) {
906 void *cmp_buf = g_malloc(qiov.size);
907 memset(cmp_buf, pattern, qiov.size);
908 if (memcmp(buf, cmp_buf, qiov.size)) {
909 printf("Pattern verification failed at offset %"
Stefan Weilcf67b692018-10-06 20:38:51 +0200910 PRId64 ", %zu bytes\n", offset, qiov.size);
Max Reitzb32d7a32018-05-09 21:42:59 +0200911 ret = -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200912 }
913 g_free(cmp_buf);
914 }
915
916 if (qflag) {
917 goto out;
918 }
919
920 if (vflag) {
921 dump_buffer(buf, offset, qiov.size);
922 }
923
924 /* Finally, report back -- -C gives a parsable format */
925 t2 = tsub(t2, t1);
926 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
927
928out:
929 qemu_iovec_destroy(&qiov);
930 qemu_io_free(buf);
Max Reitzb32d7a32018-05-09 21:42:59 +0200931 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +0200932}
933
934static void write_help(void)
935{
936 printf(
937"\n"
938" writes a range of bytes from the given offset\n"
939"\n"
940" Example:\n"
941" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
942"\n"
943" Writes into a segment of the currently open file, using a buffer\n"
944" filled with a set pattern (0xcdcdcdcd).\n"
945" -b, -- write to the VM state rather than the virtual disk\n"
Max Reitz4c7b7e92015-02-05 13:58:22 -0500946" -c, -- write compressed data with blk_write_compressed\n"
Eric Blake770e0e02016-05-07 21:16:44 -0600947" -f, -- use Force Unit Access semantics\n"
Kevin Wolfc6e3f522019-03-22 13:53:03 +0100948" -n, -- with -z, don't allow slow fallback\n"
Eric Blake093ea232016-05-07 21:16:43 -0600949" -p, -- ignored for backwards compatibility\n"
Kevin Wolf797ac582013-06-05 14:19:31 +0200950" -P, -- use different pattern to fill file\n"
951" -C, -- report statistics in a machine parsable format\n"
952" -q, -- quiet mode, do not show I/O statistics\n"
Eric Blakec2e001c2016-05-07 21:16:45 -0600953" -u, -- with -z, allow unmapping\n"
Eric Blaked004bd52016-05-24 16:25:20 -0600954" -z, -- write zeroes using blk_co_pwrite_zeroes\n"
Kevin Wolf797ac582013-06-05 14:19:31 +0200955"\n");
956}
957
Max Reitzb32d7a32018-05-09 21:42:59 +0200958static int write_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +0200959
960static const cmdinfo_t write_cmd = {
961 .name = "write",
962 .altname = "w",
963 .cfunc = write_f,
Kevin Wolf887354b2017-02-10 16:24:56 +0100964 .perm = BLK_PERM_WRITE,
Kevin Wolf797ac582013-06-05 14:19:31 +0200965 .argmin = 2,
966 .argmax = -1,
Kevin Wolfc6e3f522019-03-22 13:53:03 +0100967 .args = "[-bcCfnquz] [-P pattern] off len",
Kevin Wolf797ac582013-06-05 14:19:31 +0200968 .oneline = "writes a number of bytes at a specified offset",
969 .help = write_help,
970};
971
Max Reitzb32d7a32018-05-09 21:42:59 +0200972static int write_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +0200973{
Alex Bennée50290c02019-05-29 17:16:32 +0100974 struct timespec t1, t2;
Eric Blake093ea232016-05-07 21:16:43 -0600975 bool Cflag = false, qflag = false, bflag = false;
Eric Blakedc388522016-05-07 21:16:42 -0600976 bool Pflag = false, zflag = false, cflag = false;
Eric Blake770e0e02016-05-07 21:16:44 -0600977 int flags = 0;
Max Reitzb32d7a32018-05-09 21:42:59 +0200978 int c, cnt, ret;
Kevin Wolf797ac582013-06-05 14:19:31 +0200979 char *buf = NULL;
980 int64_t offset;
John Snow9b0beaf2015-11-05 18:53:02 -0500981 int64_t count;
Kevin Wolf797ac582013-06-05 14:19:31 +0200982 /* Some compilers get confused and warn if this is not initialized. */
John Snow9b0beaf2015-11-05 18:53:02 -0500983 int64_t total = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +0200984 int pattern = 0xcd;
985
Kevin Wolfc6e3f522019-03-22 13:53:03 +0100986 while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +0200987 switch (c) {
988 case 'b':
Eric Blakedc388522016-05-07 21:16:42 -0600989 bflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200990 break;
991 case 'c':
Eric Blakedc388522016-05-07 21:16:42 -0600992 cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200993 break;
994 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -0600995 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200996 break;
Eric Blake770e0e02016-05-07 21:16:44 -0600997 case 'f':
998 flags |= BDRV_REQ_FUA;
999 break;
Kevin Wolfc6e3f522019-03-22 13:53:03 +01001000 case 'n':
1001 flags |= BDRV_REQ_NO_FALLBACK;
1002 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001003 case 'p':
Eric Blake093ea232016-05-07 21:16:43 -06001004 /* Ignored for backwards compatibility */
Kevin Wolf797ac582013-06-05 14:19:31 +02001005 break;
1006 case 'P':
Eric Blakedc388522016-05-07 21:16:42 -06001007 Pflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001008 pattern = parse_pattern(optarg);
1009 if (pattern < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001010 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001011 }
1012 break;
1013 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001014 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001015 break;
Eric Blakec2e001c2016-05-07 21:16:45 -06001016 case 'u':
1017 flags |= BDRV_REQ_MAY_UNMAP;
1018 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001019 case 'z':
Eric Blakedc388522016-05-07 21:16:42 -06001020 zflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001021 break;
1022 default:
Max Reitzb444d0e2018-05-09 21:42:58 +02001023 qemuio_command_usage(&write_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001024 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001025 }
1026 }
1027
1028 if (optind != argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +02001029 qemuio_command_usage(&write_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001030 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001031 }
1032
Eric Blake093ea232016-05-07 21:16:43 -06001033 if (bflag && zflag) {
1034 printf("-b and -z cannot be specified at the same time\n");
Max Reitzb32d7a32018-05-09 21:42:59 +02001035 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001036 }
1037
Eric Blake770e0e02016-05-07 21:16:44 -06001038 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
1039 printf("-f and -b or -c cannot be specified at the same time\n");
Max Reitzb32d7a32018-05-09 21:42:59 +02001040 return -EINVAL;
Eric Blake770e0e02016-05-07 21:16:44 -06001041 }
1042
Kevin Wolfc6e3f522019-03-22 13:53:03 +01001043 if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
1044 printf("-n requires -z to be specified\n");
1045 return -EINVAL;
1046 }
1047
Eric Blakec2e001c2016-05-07 21:16:45 -06001048 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
1049 printf("-u requires -z to be specified\n");
Max Reitzb32d7a32018-05-09 21:42:59 +02001050 return -EINVAL;
Eric Blakec2e001c2016-05-07 21:16:45 -06001051 }
1052
Kevin Wolf797ac582013-06-05 14:19:31 +02001053 if (zflag && Pflag) {
1054 printf("-z and -P cannot be specified at the same time\n");
Max Reitzb32d7a32018-05-09 21:42:59 +02001055 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001056 }
1057
1058 offset = cvtnum(argv[optind]);
1059 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001060 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001061 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001062 }
1063
1064 optind++;
1065 count = cvtnum(argv[optind]);
1066 if (count < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001067 print_cvtnum_err(count, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001068 return count;
Alberto Garcia3026c462017-01-31 18:09:54 +02001069 } else if (count > BDRV_REQUEST_MAX_BYTES) {
John Snow9b0beaf2015-11-05 18:53:02 -05001070 printf("length cannot exceed %" PRIu64 ", given %s\n",
Alberto Garcia3026c462017-01-31 18:09:54 +02001071 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001072 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001073 }
1074
Eric Blake093ea232016-05-07 21:16:43 -06001075 if (bflag || cflag) {
Eric Blake1bce6b42017-04-29 14:14:11 -05001076 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
1077 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
Kevin Wolf797ac582013-06-05 14:19:31 +02001078 offset);
Max Reitzb32d7a32018-05-09 21:42:59 +02001079 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001080 }
1081
Eric Blake1bce6b42017-04-29 14:14:11 -05001082 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
1083 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
Kevin Wolf797ac582013-06-05 14:19:31 +02001084 count);
Max Reitzb32d7a32018-05-09 21:42:59 +02001085 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001086 }
1087 }
1088
1089 if (!zflag) {
Max Reitz4c7b7e92015-02-05 13:58:22 -05001090 buf = qemu_io_alloc(blk, count, pattern);
Kevin Wolf797ac582013-06-05 14:19:31 +02001091 }
1092
Alex Bennée50290c02019-05-29 17:16:32 +01001093 clock_gettime(CLOCK_MONOTONIC, &t1);
Eric Blake7b3f9712016-05-06 10:26:44 -06001094 if (bflag) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001095 ret = do_save_vmstate(blk, buf, offset, count, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +02001096 } else if (zflag) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001097 ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +02001098 } else if (cflag) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001099 ret = do_write_compressed(blk, buf, offset, count, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +02001100 } else {
Max Reitzb32d7a32018-05-09 21:42:59 +02001101 ret = do_pwrite(blk, buf, offset, count, flags, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +02001102 }
Alex Bennée50290c02019-05-29 17:16:32 +01001103 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001104
Max Reitzb32d7a32018-05-09 21:42:59 +02001105 if (ret < 0) {
1106 printf("write failed: %s\n", strerror(-ret));
Kevin Wolf797ac582013-06-05 14:19:31 +02001107 goto out;
1108 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001109 cnt = ret;
1110
1111 ret = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001112
1113 if (qflag) {
1114 goto out;
1115 }
1116
1117 /* Finally, report back -- -C gives a parsable format */
1118 t2 = tsub(t2, t1);
1119 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1120
1121out:
1122 if (!zflag) {
1123 qemu_io_free(buf);
1124 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001125 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001126}
1127
1128static void
1129writev_help(void)
1130{
1131 printf(
1132"\n"
1133" writes a range of bytes from the given offset source from multiple buffers\n"
1134"\n"
1135" Example:\n"
Maria Kustova6e6507c2014-03-18 09:59:17 +04001136" 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001137"\n"
1138" Writes into a segment of the currently open file, using a buffer\n"
1139" filled with a set pattern (0xcdcdcdcd).\n"
1140" -P, -- use different pattern to fill file\n"
1141" -C, -- report statistics in a machine parsable format\n"
Eric Blake770e0e02016-05-07 21:16:44 -06001142" -f, -- use Force Unit Access semantics\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001143" -q, -- quiet mode, do not show I/O statistics\n"
1144"\n");
1145}
1146
Max Reitzb32d7a32018-05-09 21:42:59 +02001147static int writev_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001148
1149static const cmdinfo_t writev_cmd = {
1150 .name = "writev",
1151 .cfunc = writev_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001152 .perm = BLK_PERM_WRITE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001153 .argmin = 2,
1154 .argmax = -1,
Eric Blake770e0e02016-05-07 21:16:44 -06001155 .args = "[-Cfq] [-P pattern] off len [len..]",
Kevin Wolf797ac582013-06-05 14:19:31 +02001156 .oneline = "writes a number of bytes at a specified offset",
1157 .help = writev_help,
1158};
1159
Max Reitzb32d7a32018-05-09 21:42:59 +02001160static int writev_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001161{
Alex Bennée50290c02019-05-29 17:16:32 +01001162 struct timespec t1, t2;
Eric Blakedc388522016-05-07 21:16:42 -06001163 bool Cflag = false, qflag = false;
Eric Blake770e0e02016-05-07 21:16:44 -06001164 int flags = 0;
Max Reitzb32d7a32018-05-09 21:42:59 +02001165 int c, cnt, ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001166 char *buf;
1167 int64_t offset;
1168 /* Some compilers get confused and warn if this is not initialized. */
1169 int total = 0;
1170 int nr_iov;
1171 int pattern = 0xcd;
1172 QEMUIOVector qiov;
1173
Eric Blake4ca1d342016-05-16 10:43:01 -06001174 while ((c = getopt(argc, argv, "CfqP:")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001175 switch (c) {
1176 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001177 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001178 break;
Eric Blake770e0e02016-05-07 21:16:44 -06001179 case 'f':
1180 flags |= BDRV_REQ_FUA;
1181 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001182 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001183 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001184 break;
1185 case 'P':
1186 pattern = parse_pattern(optarg);
1187 if (pattern < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001188 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001189 }
1190 break;
1191 default:
Max Reitzb444d0e2018-05-09 21:42:58 +02001192 qemuio_command_usage(&writev_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001193 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001194 }
1195 }
1196
1197 if (optind > argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +02001198 qemuio_command_usage(&writev_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001199 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001200 }
1201
1202 offset = cvtnum(argv[optind]);
1203 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001204 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001205 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001206 }
1207 optind++;
1208
Kevin Wolf797ac582013-06-05 14:19:31 +02001209 nr_iov = argc - optind;
Max Reitz4c7b7e92015-02-05 13:58:22 -05001210 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
Kevin Wolf797ac582013-06-05 14:19:31 +02001211 if (buf == NULL) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001212 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001213 }
1214
Alex Bennée50290c02019-05-29 17:16:32 +01001215 clock_gettime(CLOCK_MONOTONIC, &t1);
Max Reitzb32d7a32018-05-09 21:42:59 +02001216 ret = do_aio_writev(blk, &qiov, offset, flags, &total);
Alex Bennée50290c02019-05-29 17:16:32 +01001217 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001218
Max Reitzb32d7a32018-05-09 21:42:59 +02001219 if (ret < 0) {
1220 printf("writev failed: %s\n", strerror(-ret));
Kevin Wolf797ac582013-06-05 14:19:31 +02001221 goto out;
1222 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001223 cnt = ret;
1224
1225 ret = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001226
1227 if (qflag) {
1228 goto out;
1229 }
1230
1231 /* Finally, report back -- -C gives a parsable format */
1232 t2 = tsub(t2, t1);
1233 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1234out:
1235 qemu_iovec_destroy(&qiov);
1236 qemu_io_free(buf);
Max Reitzb32d7a32018-05-09 21:42:59 +02001237 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001238}
1239
Kevin Wolf797ac582013-06-05 14:19:31 +02001240struct aio_ctx {
Max Reitz4c7b7e92015-02-05 13:58:22 -05001241 BlockBackend *blk;
Kevin Wolf797ac582013-06-05 14:19:31 +02001242 QEMUIOVector qiov;
1243 int64_t offset;
1244 char *buf;
Eric Blakedc388522016-05-07 21:16:42 -06001245 bool qflag;
1246 bool vflag;
1247 bool Cflag;
1248 bool Pflag;
1249 bool zflag;
Fam Zhenga91f9582015-01-30 10:49:42 +08001250 BlockAcctCookie acct;
Kevin Wolf797ac582013-06-05 14:19:31 +02001251 int pattern;
Alex Bennée50290c02019-05-29 17:16:32 +01001252 struct timespec t1;
Kevin Wolf797ac582013-06-05 14:19:31 +02001253};
1254
1255static void aio_write_done(void *opaque, int ret)
1256{
1257 struct aio_ctx *ctx = opaque;
Alex Bennée50290c02019-05-29 17:16:32 +01001258 struct timespec t2;
Kevin Wolf797ac582013-06-05 14:19:31 +02001259
Alex Bennée50290c02019-05-29 17:16:32 +01001260 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001261
1262
1263 if (ret < 0) {
1264 printf("aio_write failed: %s\n", strerror(-ret));
Alberto Garcia556c2b62015-10-28 17:33:08 +02001265 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
Kevin Wolf797ac582013-06-05 14:19:31 +02001266 goto out;
1267 }
1268
Max Reitz4c7b7e92015-02-05 13:58:22 -05001269 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
Fam Zhenga91f9582015-01-30 10:49:42 +08001270
Kevin Wolf797ac582013-06-05 14:19:31 +02001271 if (ctx->qflag) {
1272 goto out;
1273 }
1274
1275 /* Finally, report back -- -C gives a parsable format */
1276 t2 = tsub(t2, ctx->t1);
1277 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1278 ctx->qiov.size, 1, ctx->Cflag);
1279out:
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001280 if (!ctx->zflag) {
1281 qemu_io_free(ctx->buf);
1282 qemu_iovec_destroy(&ctx->qiov);
1283 }
Kevin Wolf797ac582013-06-05 14:19:31 +02001284 g_free(ctx);
1285}
1286
1287static void aio_read_done(void *opaque, int ret)
1288{
1289 struct aio_ctx *ctx = opaque;
Alex Bennée50290c02019-05-29 17:16:32 +01001290 struct timespec t2;
Kevin Wolf797ac582013-06-05 14:19:31 +02001291
Alex Bennée50290c02019-05-29 17:16:32 +01001292 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001293
1294 if (ret < 0) {
1295 printf("readv failed: %s\n", strerror(-ret));
Alberto Garcia556c2b62015-10-28 17:33:08 +02001296 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
Kevin Wolf797ac582013-06-05 14:19:31 +02001297 goto out;
1298 }
1299
1300 if (ctx->Pflag) {
1301 void *cmp_buf = g_malloc(ctx->qiov.size);
1302
1303 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1304 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1305 printf("Pattern verification failed at offset %"
Stefan Weilcf67b692018-10-06 20:38:51 +02001306 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
Kevin Wolf797ac582013-06-05 14:19:31 +02001307 }
1308 g_free(cmp_buf);
1309 }
1310
Max Reitz4c7b7e92015-02-05 13:58:22 -05001311 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
Fam Zhenga91f9582015-01-30 10:49:42 +08001312
Kevin Wolf797ac582013-06-05 14:19:31 +02001313 if (ctx->qflag) {
1314 goto out;
1315 }
1316
1317 if (ctx->vflag) {
1318 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1319 }
1320
1321 /* Finally, report back -- -C gives a parsable format */
1322 t2 = tsub(t2, ctx->t1);
1323 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1324 ctx->qiov.size, 1, ctx->Cflag);
1325out:
1326 qemu_io_free(ctx->buf);
1327 qemu_iovec_destroy(&ctx->qiov);
1328 g_free(ctx);
1329}
1330
1331static void aio_read_help(void)
1332{
1333 printf(
1334"\n"
1335" asynchronously reads a range of bytes from the given offset\n"
1336"\n"
1337" Example:\n"
1338" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1339"\n"
1340" Reads a segment of the currently open file, optionally dumping it to the\n"
1341" standard output stream (with -v option) for subsequent inspection.\n"
1342" The read is performed asynchronously and the aio_flush command must be\n"
1343" used to ensure all outstanding aio requests have been completed.\n"
Max Reitzb32d7a32018-05-09 21:42:59 +02001344" Note that due to its asynchronous nature, this command will be\n"
1345" considered successful once the request is submitted, independently\n"
1346" of potential I/O errors or pattern mismatches.\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001347" -C, -- report statistics in a machine parsable format\n"
1348" -P, -- use a pattern to verify read data\n"
Eric Blake37546ff2016-05-16 10:43:03 -06001349" -i, -- treat request as invalid, for exercising stats\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001350" -v, -- dump buffer to standard output\n"
1351" -q, -- quiet mode, do not show I/O statistics\n"
1352"\n");
1353}
1354
Max Reitzb32d7a32018-05-09 21:42:59 +02001355static int aio_read_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001356
1357static const cmdinfo_t aio_read_cmd = {
1358 .name = "aio_read",
1359 .cfunc = aio_read_f,
1360 .argmin = 2,
1361 .argmax = -1,
Eric Blake37546ff2016-05-16 10:43:03 -06001362 .args = "[-Ciqv] [-P pattern] off len [len..]",
Kevin Wolf797ac582013-06-05 14:19:31 +02001363 .oneline = "asynchronously reads a number of bytes",
1364 .help = aio_read_help,
1365};
1366
Max Reitzb32d7a32018-05-09 21:42:59 +02001367static int aio_read_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001368{
1369 int nr_iov, c;
1370 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1371
Max Reitz4c7b7e92015-02-05 13:58:22 -05001372 ctx->blk = blk;
Eric Blake37546ff2016-05-16 10:43:03 -06001373 while ((c = getopt(argc, argv, "CP:iqv")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001374 switch (c) {
1375 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001376 ctx->Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001377 break;
1378 case 'P':
Eric Blakedc388522016-05-07 21:16:42 -06001379 ctx->Pflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001380 ctx->pattern = parse_pattern(optarg);
1381 if (ctx->pattern < 0) {
1382 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001383 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001384 }
1385 break;
Eric Blake37546ff2016-05-16 10:43:03 -06001386 case 'i':
1387 printf("injecting invalid read request\n");
1388 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1389 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001390 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001391 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001392 ctx->qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001393 break;
1394 case 'v':
Eric Blakedc388522016-05-07 21:16:42 -06001395 ctx->vflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001396 break;
1397 default:
1398 g_free(ctx);
Max Reitzb444d0e2018-05-09 21:42:58 +02001399 qemuio_command_usage(&aio_read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001400 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001401 }
1402 }
1403
1404 if (optind > argc - 2) {
1405 g_free(ctx);
Max Reitzb444d0e2018-05-09 21:42:58 +02001406 qemuio_command_usage(&aio_read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001407 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001408 }
1409
1410 ctx->offset = cvtnum(argv[optind]);
1411 if (ctx->offset < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001412 int ret = ctx->offset;
1413 print_cvtnum_err(ret, argv[optind]);
Kevin Wolf797ac582013-06-05 14:19:31 +02001414 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001415 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001416 }
1417 optind++;
1418
Kevin Wolf797ac582013-06-05 14:19:31 +02001419 nr_iov = argc - optind;
Max Reitz4c7b7e92015-02-05 13:58:22 -05001420 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
Kevin Wolf797ac582013-06-05 14:19:31 +02001421 if (ctx->buf == NULL) {
Alberto Garcia556c2b62015-10-28 17:33:08 +02001422 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
Kevin Wolf797ac582013-06-05 14:19:31 +02001423 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001424 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001425 }
1426
Alex Bennée50290c02019-05-29 17:16:32 +01001427 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
Max Reitz4c7b7e92015-02-05 13:58:22 -05001428 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1429 BLOCK_ACCT_READ);
Eric Blake7b3f9712016-05-06 10:26:44 -06001430 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001431 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001432}
1433
1434static void aio_write_help(void)
1435{
1436 printf(
1437"\n"
1438" asynchronously writes a range of bytes from the given offset source\n"
1439" from multiple buffers\n"
1440"\n"
1441" Example:\n"
1442" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1443"\n"
1444" Writes into a segment of the currently open file, using a buffer\n"
1445" filled with a set pattern (0xcdcdcdcd).\n"
1446" The write is performed asynchronously and the aio_flush command must be\n"
1447" used to ensure all outstanding aio requests have been completed.\n"
Max Reitzb32d7a32018-05-09 21:42:59 +02001448" Note that due to its asynchronous nature, this command will be\n"
1449" considered successful once the request is submitted, independently\n"
1450" of potential I/O errors or pattern mismatches.\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001451" -P, -- use different pattern to fill file\n"
1452" -C, -- report statistics in a machine parsable format\n"
Eric Blake770e0e02016-05-07 21:16:44 -06001453" -f, -- use Force Unit Access semantics\n"
Eric Blake37546ff2016-05-16 10:43:03 -06001454" -i, -- treat request as invalid, for exercising stats\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001455" -q, -- quiet mode, do not show I/O statistics\n"
Eric Blakec2e001c2016-05-07 21:16:45 -06001456" -u, -- with -z, allow unmapping\n"
Eric Blaked004bd52016-05-24 16:25:20 -06001457" -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001458"\n");
1459}
1460
Max Reitzb32d7a32018-05-09 21:42:59 +02001461static int aio_write_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001462
1463static const cmdinfo_t aio_write_cmd = {
1464 .name = "aio_write",
1465 .cfunc = aio_write_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001466 .perm = BLK_PERM_WRITE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001467 .argmin = 2,
1468 .argmax = -1,
Eric Blake37546ff2016-05-16 10:43:03 -06001469 .args = "[-Cfiquz] [-P pattern] off len [len..]",
Kevin Wolf797ac582013-06-05 14:19:31 +02001470 .oneline = "asynchronously writes a number of bytes",
1471 .help = aio_write_help,
1472};
1473
Max Reitzb32d7a32018-05-09 21:42:59 +02001474static int aio_write_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001475{
1476 int nr_iov, c;
1477 int pattern = 0xcd;
1478 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
Eric Blake770e0e02016-05-07 21:16:44 -06001479 int flags = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001480
Max Reitz4c7b7e92015-02-05 13:58:22 -05001481 ctx->blk = blk;
Eric Blake37546ff2016-05-16 10:43:03 -06001482 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001483 switch (c) {
1484 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001485 ctx->Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001486 break;
Eric Blake770e0e02016-05-07 21:16:44 -06001487 case 'f':
1488 flags |= BDRV_REQ_FUA;
1489 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001490 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001491 ctx->qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001492 break;
Eric Blakec2e001c2016-05-07 21:16:45 -06001493 case 'u':
1494 flags |= BDRV_REQ_MAY_UNMAP;
1495 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001496 case 'P':
1497 pattern = parse_pattern(optarg);
1498 if (pattern < 0) {
1499 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001500 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001501 }
1502 break;
Eric Blake37546ff2016-05-16 10:43:03 -06001503 case 'i':
1504 printf("injecting invalid write request\n");
1505 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1506 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001507 return 0;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001508 case 'z':
Eric Blakedc388522016-05-07 21:16:42 -06001509 ctx->zflag = true;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001510 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001511 default:
1512 g_free(ctx);
Max Reitzb444d0e2018-05-09 21:42:58 +02001513 qemuio_command_usage(&aio_write_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001514 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001515 }
1516 }
1517
1518 if (optind > argc - 2) {
1519 g_free(ctx);
Max Reitzb444d0e2018-05-09 21:42:58 +02001520 qemuio_command_usage(&aio_write_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001521 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001522 }
1523
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001524 if (ctx->zflag && optind != argc - 2) {
1525 printf("-z supports only a single length parameter\n");
1526 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001527 return -EINVAL;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001528 }
1529
Eric Blakec2e001c2016-05-07 21:16:45 -06001530 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
1531 printf("-u requires -z to be specified\n");
Eric Blake4ca1d342016-05-16 10:43:01 -06001532 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001533 return -EINVAL;
Eric Blakec2e001c2016-05-07 21:16:45 -06001534 }
1535
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001536 if (ctx->zflag && ctx->Pflag) {
1537 printf("-z and -P cannot be specified at the same time\n");
1538 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001539 return -EINVAL;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001540 }
1541
Kevin Wolf797ac582013-06-05 14:19:31 +02001542 ctx->offset = cvtnum(argv[optind]);
1543 if (ctx->offset < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001544 int ret = ctx->offset;
1545 print_cvtnum_err(ret, argv[optind]);
Kevin Wolf797ac582013-06-05 14:19:31 +02001546 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001547 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001548 }
1549 optind++;
1550
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001551 if (ctx->zflag) {
1552 int64_t count = cvtnum(argv[optind]);
1553 if (count < 0) {
1554 print_cvtnum_err(count, argv[optind]);
Kevin Wolf0e01b762016-05-09 12:03:04 +02001555 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001556 return count;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001557 }
Kevin Wolf797ac582013-06-05 14:19:31 +02001558
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001559 ctx->qiov.size = count;
Eric Blaked004bd52016-05-24 16:25:20 -06001560 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done,
1561 ctx);
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001562 } else {
1563 nr_iov = argc - optind;
1564 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
1565 pattern);
1566 if (ctx->buf == NULL) {
1567 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1568 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001569 return -EINVAL;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001570 }
1571
Alex Bennée50290c02019-05-29 17:16:32 +01001572 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001573 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1574 BLOCK_ACCT_WRITE);
1575
Eric Blake770e0e02016-05-07 21:16:44 -06001576 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
1577 ctx);
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001578 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001579
1580 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001581}
1582
Max Reitzb32d7a32018-05-09 21:42:59 +02001583static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001584{
Alberto Garcia556c2b62015-10-28 17:33:08 +02001585 BlockAcctCookie cookie;
1586 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
Max Reitz4c7b7e92015-02-05 13:58:22 -05001587 blk_drain_all();
Alberto Garcia556c2b62015-10-28 17:33:08 +02001588 block_acct_done(blk_get_stats(blk), &cookie);
Max Reitzb32d7a32018-05-09 21:42:59 +02001589 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001590}
1591
1592static const cmdinfo_t aio_flush_cmd = {
1593 .name = "aio_flush",
1594 .cfunc = aio_flush_f,
1595 .oneline = "completes all outstanding aio requests"
1596};
1597
Max Reitzb32d7a32018-05-09 21:42:59 +02001598static int flush_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001599{
Max Reitzb32d7a32018-05-09 21:42:59 +02001600 return blk_flush(blk);
Kevin Wolf797ac582013-06-05 14:19:31 +02001601}
1602
1603static const cmdinfo_t flush_cmd = {
1604 .name = "flush",
1605 .altname = "f",
1606 .cfunc = flush_f,
1607 .oneline = "flush all in-core file state to disk",
1608};
1609
Max Reitzb32d7a32018-05-09 21:42:59 +02001610static int truncate_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001611{
Max Reitzed3d2ec2017-03-28 22:51:27 +02001612 Error *local_err = NULL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001613 int64_t offset;
1614 int ret;
1615
1616 offset = cvtnum(argv[1]);
1617 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001618 print_cvtnum_err(offset, argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001619 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001620 }
1621
Max Reitz3a691c52017-06-13 22:20:54 +02001622 ret = blk_truncate(blk, offset, PREALLOC_MODE_OFF, &local_err);
Kevin Wolf797ac582013-06-05 14:19:31 +02001623 if (ret < 0) {
Max Reitzed3d2ec2017-03-28 22:51:27 +02001624 error_report_err(local_err);
Max Reitzb32d7a32018-05-09 21:42:59 +02001625 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001626 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001627
1628 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001629}
1630
1631static const cmdinfo_t truncate_cmd = {
1632 .name = "truncate",
1633 .altname = "t",
1634 .cfunc = truncate_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001635 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001636 .argmin = 1,
1637 .argmax = 1,
1638 .args = "off",
1639 .oneline = "truncates the current file at the given offset",
1640};
1641
Max Reitzb32d7a32018-05-09 21:42:59 +02001642static int length_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001643{
1644 int64_t size;
1645 char s1[64];
1646
Max Reitz4c7b7e92015-02-05 13:58:22 -05001647 size = blk_getlength(blk);
Kevin Wolf797ac582013-06-05 14:19:31 +02001648 if (size < 0) {
1649 printf("getlength: %s\n", strerror(-size));
Max Reitzb32d7a32018-05-09 21:42:59 +02001650 return size;
Kevin Wolf797ac582013-06-05 14:19:31 +02001651 }
1652
1653 cvtstr(size, s1, sizeof(s1));
1654 printf("%s\n", s1);
Max Reitzb32d7a32018-05-09 21:42:59 +02001655 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001656}
1657
1658
1659static const cmdinfo_t length_cmd = {
1660 .name = "length",
1661 .altname = "l",
1662 .cfunc = length_f,
1663 .oneline = "gets the length of the current file",
1664};
1665
1666
Max Reitzb32d7a32018-05-09 21:42:59 +02001667static int info_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001668{
Max Reitz4c7b7e92015-02-05 13:58:22 -05001669 BlockDriverState *bs = blk_bs(blk);
Kevin Wolf797ac582013-06-05 14:19:31 +02001670 BlockDriverInfo bdi;
Max Reitza8d8ecb2013-10-09 10:46:17 +02001671 ImageInfoSpecific *spec_info;
Andrey Shinkevich1bf6e9c2019-02-08 18:06:06 +03001672 Error *local_err = NULL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001673 char s1[64], s2[64];
1674 int ret;
1675
1676 if (bs->drv && bs->drv->format_name) {
1677 printf("format name: %s\n", bs->drv->format_name);
1678 }
1679 if (bs->drv && bs->drv->protocol_name) {
1680 printf("format name: %s\n", bs->drv->protocol_name);
1681 }
1682
1683 ret = bdrv_get_info(bs, &bdi);
1684 if (ret) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001685 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001686 }
1687
1688 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1689 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1690
1691 printf("cluster size: %s\n", s1);
1692 printf("vm state offset: %s\n", s2);
1693
Andrey Shinkevich1bf6e9c2019-02-08 18:06:06 +03001694 spec_info = bdrv_get_specific_info(bs, &local_err);
1695 if (local_err) {
1696 error_report_err(local_err);
1697 return -EIO;
1698 }
Max Reitza8d8ecb2013-10-09 10:46:17 +02001699 if (spec_info) {
1700 printf("Format specific information:\n");
Markus Armbrustere1ce7d72019-04-17 21:17:55 +02001701 bdrv_image_info_specific_dump(spec_info);
Max Reitza8d8ecb2013-10-09 10:46:17 +02001702 qapi_free_ImageInfoSpecific(spec_info);
1703 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001704
1705 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001706}
1707
1708
1709
1710static const cmdinfo_t info_cmd = {
1711 .name = "info",
1712 .altname = "i",
1713 .cfunc = info_f,
1714 .oneline = "prints information about the current file",
1715};
1716
1717static void discard_help(void)
1718{
1719 printf(
1720"\n"
1721" discards a range of bytes from the given offset\n"
1722"\n"
1723" Example:\n"
1724" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1725"\n"
1726" Discards a segment of the currently open file.\n"
1727" -C, -- report statistics in a machine parsable format\n"
1728" -q, -- quiet mode, do not show I/O statistics\n"
1729"\n");
1730}
1731
Max Reitzb32d7a32018-05-09 21:42:59 +02001732static int discard_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001733
1734static const cmdinfo_t discard_cmd = {
1735 .name = "discard",
1736 .altname = "d",
1737 .cfunc = discard_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001738 .perm = BLK_PERM_WRITE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001739 .argmin = 2,
1740 .argmax = -1,
1741 .args = "[-Cq] off len",
1742 .oneline = "discards a number of bytes at a specified offset",
1743 .help = discard_help,
1744};
1745
Max Reitzb32d7a32018-05-09 21:42:59 +02001746static int discard_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001747{
Alex Bennée50290c02019-05-29 17:16:32 +01001748 struct timespec t1, t2;
Eric Blakedc388522016-05-07 21:16:42 -06001749 bool Cflag = false, qflag = false;
Kevin Wolf797ac582013-06-05 14:19:31 +02001750 int c, ret;
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +03001751 int64_t offset, bytes;
Kevin Wolf797ac582013-06-05 14:19:31 +02001752
Eric Blakeb062ad82015-05-12 09:10:56 -06001753 while ((c = getopt(argc, argv, "Cq")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001754 switch (c) {
1755 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001756 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001757 break;
1758 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001759 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001760 break;
1761 default:
Max Reitzb444d0e2018-05-09 21:42:58 +02001762 qemuio_command_usage(&discard_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001763 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001764 }
1765 }
1766
1767 if (optind != argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +02001768 qemuio_command_usage(&discard_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001769 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001770 }
1771
1772 offset = cvtnum(argv[optind]);
1773 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001774 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001775 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001776 }
1777
1778 optind++;
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +03001779 bytes = cvtnum(argv[optind]);
1780 if (bytes < 0) {
1781 print_cvtnum_err(bytes, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001782 return bytes;
Alberto Garcia41ae31e2019-05-14 16:57:35 +03001783 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
John Snow9b0beaf2015-11-05 18:53:02 -05001784 printf("length cannot exceed %"PRIu64", given %s\n",
Alberto Garcia41ae31e2019-05-14 16:57:35 +03001785 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001786 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001787 }
1788
Alex Bennée50290c02019-05-29 17:16:32 +01001789 clock_gettime(CLOCK_MONOTONIC, &t1);
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +03001790 ret = blk_pdiscard(blk, offset, bytes);
Alex Bennée50290c02019-05-29 17:16:32 +01001791 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001792
1793 if (ret < 0) {
1794 printf("discard failed: %s\n", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02001795 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001796 }
1797
1798 /* Finally, report back -- -C gives a parsable format */
1799 if (!qflag) {
1800 t2 = tsub(t2, t1);
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +03001801 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
Kevin Wolf797ac582013-06-05 14:19:31 +02001802 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001803
1804 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001805}
1806
Max Reitzb32d7a32018-05-09 21:42:59 +02001807static int alloc_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001808{
Max Reitz4c7b7e92015-02-05 13:58:22 -05001809 BlockDriverState *bs = blk_bs(blk);
Eric Blaked6a644b2017-07-07 07:44:57 -05001810 int64_t offset, start, remaining, count;
Kevin Wolf797ac582013-06-05 14:19:31 +02001811 char s1[64];
Eric Blaked6a644b2017-07-07 07:44:57 -05001812 int ret;
1813 int64_t num, sum_alloc;
Kevin Wolf797ac582013-06-05 14:19:31 +02001814
Eric Blaked6a644b2017-07-07 07:44:57 -05001815 start = offset = cvtnum(argv[1]);
Kevin Wolf797ac582013-06-05 14:19:31 +02001816 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001817 print_cvtnum_err(offset, argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001818 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001819 }
1820
1821 if (argc == 3) {
Eric Blake4401fdc2017-04-29 14:14:12 -05001822 count = cvtnum(argv[2]);
1823 if (count < 0) {
1824 print_cvtnum_err(count, argv[2]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001825 return count;
Kevin Wolf797ac582013-06-05 14:19:31 +02001826 }
1827 } else {
Eric Blake4401fdc2017-04-29 14:14:12 -05001828 count = BDRV_SECTOR_SIZE;
Kevin Wolf797ac582013-06-05 14:19:31 +02001829 }
1830
Eric Blaked6a644b2017-07-07 07:44:57 -05001831 remaining = count;
Kevin Wolf797ac582013-06-05 14:19:31 +02001832 sum_alloc = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001833 while (remaining) {
Eric Blaked6a644b2017-07-07 07:44:57 -05001834 ret = bdrv_is_allocated(bs, offset, remaining, &num);
Paolo Bonzinid6636402013-09-04 19:00:25 +02001835 if (ret < 0) {
1836 printf("is_allocated failed: %s\n", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02001837 return ret;
Paolo Bonzinid6636402013-09-04 19:00:25 +02001838 }
Eric Blaked6a644b2017-07-07 07:44:57 -05001839 offset += num;
Kevin Wolf797ac582013-06-05 14:19:31 +02001840 remaining -= num;
1841 if (ret) {
1842 sum_alloc += num;
1843 }
1844 if (num == 0) {
Eric Blaked6a644b2017-07-07 07:44:57 -05001845 count -= remaining;
Kevin Wolf797ac582013-06-05 14:19:31 +02001846 remaining = 0;
1847 }
1848 }
1849
Eric Blaked6a644b2017-07-07 07:44:57 -05001850 cvtstr(start, s1, sizeof(s1));
Kevin Wolf797ac582013-06-05 14:19:31 +02001851
Eric Blake4401fdc2017-04-29 14:14:12 -05001852 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
Eric Blaked6a644b2017-07-07 07:44:57 -05001853 sum_alloc, count, s1);
Max Reitzb32d7a32018-05-09 21:42:59 +02001854 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001855}
1856
1857static const cmdinfo_t alloc_cmd = {
1858 .name = "alloc",
1859 .altname = "a",
1860 .argmin = 1,
1861 .argmax = 2,
1862 .cfunc = alloc_f,
Eric Blake4401fdc2017-04-29 14:14:12 -05001863 .args = "offset [count]",
1864 .oneline = "checks if offset is allocated in the file",
Kevin Wolf797ac582013-06-05 14:19:31 +02001865};
1866
1867
Eric Blaked6a644b2017-07-07 07:44:57 -05001868static int map_is_allocated(BlockDriverState *bs, int64_t offset,
1869 int64_t bytes, int64_t *pnum)
Kevin Wolf797ac582013-06-05 14:19:31 +02001870{
Eric Blaked6a644b2017-07-07 07:44:57 -05001871 int64_t num;
1872 int num_checked;
Kevin Wolf797ac582013-06-05 14:19:31 +02001873 int ret, firstret;
1874
Eric Blaked6a644b2017-07-07 07:44:57 -05001875 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1876 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
Kevin Wolf797ac582013-06-05 14:19:31 +02001877 if (ret < 0) {
1878 return ret;
1879 }
1880
1881 firstret = ret;
1882 *pnum = num;
1883
Eric Blaked6a644b2017-07-07 07:44:57 -05001884 while (bytes > 0 && ret == firstret) {
1885 offset += num;
1886 bytes -= num;
Kevin Wolf797ac582013-06-05 14:19:31 +02001887
Eric Blaked6a644b2017-07-07 07:44:57 -05001888 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1889 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
Max Reitz4b25bbc2014-10-22 17:00:16 +02001890 if (ret == firstret && num) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001891 *pnum += num;
1892 } else {
1893 break;
1894 }
1895 }
1896
1897 return firstret;
1898}
1899
Max Reitzb32d7a32018-05-09 21:42:59 +02001900static int map_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001901{
Eric Blaked6a644b2017-07-07 07:44:57 -05001902 int64_t offset, bytes;
Eric Blake6f3c90a2017-04-29 14:14:13 -05001903 char s1[64], s2[64];
Kevin Wolf797ac582013-06-05 14:19:31 +02001904 int64_t num;
1905 int ret;
1906 const char *retstr;
1907
1908 offset = 0;
Eric Blaked6a644b2017-07-07 07:44:57 -05001909 bytes = blk_getlength(blk);
1910 if (bytes < 0) {
1911 error_report("Failed to query image length: %s", strerror(-bytes));
Max Reitzb32d7a32018-05-09 21:42:59 +02001912 return bytes;
Max Reitz4c7b7e92015-02-05 13:58:22 -05001913 }
1914
Eric Blaked6a644b2017-07-07 07:44:57 -05001915 while (bytes) {
1916 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
Kevin Wolf797ac582013-06-05 14:19:31 +02001917 if (ret < 0) {
1918 error_report("Failed to get allocation status: %s", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02001919 return ret;
Max Reitz4b25bbc2014-10-22 17:00:16 +02001920 } else if (!num) {
1921 error_report("Unexpected end of image");
Max Reitzb32d7a32018-05-09 21:42:59 +02001922 return -EIO;
Kevin Wolf797ac582013-06-05 14:19:31 +02001923 }
1924
1925 retstr = ret ? " allocated" : "not allocated";
Eric Blaked6a644b2017-07-07 07:44:57 -05001926 cvtstr(num, s1, sizeof(s1));
1927 cvtstr(offset, s2, sizeof(s2));
Eric Blake6f3c90a2017-04-29 14:14:13 -05001928 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
Eric Blaked6a644b2017-07-07 07:44:57 -05001929 s1, num, retstr, s2, offset);
Kevin Wolf797ac582013-06-05 14:19:31 +02001930
1931 offset += num;
Eric Blaked6a644b2017-07-07 07:44:57 -05001932 bytes -= num;
1933 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001934
1935 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001936}
1937
1938static const cmdinfo_t map_cmd = {
1939 .name = "map",
1940 .argmin = 0,
1941 .argmax = 0,
1942 .cfunc = map_f,
1943 .args = "",
1944 .oneline = "prints the allocated areas of a file",
1945};
1946
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01001947static void reopen_help(void)
1948{
1949 printf(
1950"\n"
1951" Changes the open options of an already opened image\n"
1952"\n"
1953" Example:\n"
1954" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
1955"\n"
1956" -r, -- Reopen the image read-only\n"
Kevin Wolfea922032017-08-03 17:03:00 +02001957" -w, -- Reopen the image read-write\n"
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01001958" -c, -- Change the cache mode to the given value\n"
1959" -o, -- Changes block driver options (cf. 'open' command)\n"
1960"\n");
1961}
1962
Max Reitzb32d7a32018-05-09 21:42:59 +02001963static int reopen_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01001964
1965static QemuOptsList reopen_opts = {
1966 .name = "reopen",
1967 .merge_lists = true,
1968 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
1969 .desc = {
1970 /* no elements => accept any params */
1971 { /* end of list */ }
1972 },
1973};
1974
1975static const cmdinfo_t reopen_cmd = {
1976 .name = "reopen",
1977 .argmin = 0,
1978 .argmax = -1,
1979 .cfunc = reopen_f,
Kevin Wolfea922032017-08-03 17:03:00 +02001980 .args = "[(-r|-w)] [-c cache] [-o options]",
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01001981 .oneline = "reopens an image with new options",
1982 .help = reopen_help,
1983};
1984
Max Reitzb32d7a32018-05-09 21:42:59 +02001985static int reopen_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01001986{
1987 BlockDriverState *bs = blk_bs(blk);
1988 QemuOpts *qopts;
1989 QDict *opts;
1990 int c;
1991 int flags = bs->open_flags;
Kevin Wolf19dbecd2016-03-18 15:36:31 +01001992 bool writethrough = !blk_enable_write_cache(blk);
Kevin Wolfea922032017-08-03 17:03:00 +02001993 bool has_rw_option = false;
Alberto Garciadc900c32018-11-12 16:00:42 +02001994 bool has_cache_option = false;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01001995
1996 BlockReopenQueue *brq;
1997 Error *local_err = NULL;
1998
Kevin Wolfea922032017-08-03 17:03:00 +02001999 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002000 switch (c) {
2001 case 'c':
Kevin Wolf19dbecd2016-03-18 15:36:31 +01002002 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002003 error_report("Invalid cache option: %s", optarg);
Max Reitzb32d7a32018-05-09 21:42:59 +02002004 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002005 }
Alberto Garciadc900c32018-11-12 16:00:42 +02002006 has_cache_option = true;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002007 break;
2008 case 'o':
2009 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2010 qemu_opts_reset(&reopen_opts);
Max Reitzb32d7a32018-05-09 21:42:59 +02002011 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002012 }
2013 break;
2014 case 'r':
Kevin Wolfea922032017-08-03 17:03:00 +02002015 if (has_rw_option) {
2016 error_report("Only one -r/-w option may be given");
Max Reitzb32d7a32018-05-09 21:42:59 +02002017 return -EINVAL;
Kevin Wolfea922032017-08-03 17:03:00 +02002018 }
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002019 flags &= ~BDRV_O_RDWR;
Kevin Wolfea922032017-08-03 17:03:00 +02002020 has_rw_option = true;
2021 break;
2022 case 'w':
2023 if (has_rw_option) {
2024 error_report("Only one -r/-w option may be given");
Max Reitzb32d7a32018-05-09 21:42:59 +02002025 return -EINVAL;
Kevin Wolfea922032017-08-03 17:03:00 +02002026 }
2027 flags |= BDRV_O_RDWR;
2028 has_rw_option = true;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002029 break;
2030 default:
2031 qemu_opts_reset(&reopen_opts);
Max Reitzb444d0e2018-05-09 21:42:58 +02002032 qemuio_command_usage(&reopen_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02002033 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002034 }
2035 }
2036
2037 if (optind != argc) {
2038 qemu_opts_reset(&reopen_opts);
Max Reitzb444d0e2018-05-09 21:42:58 +02002039 qemuio_command_usage(&reopen_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02002040 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002041 }
2042
Alberto Garciaa8003ec2018-09-06 12:37:01 +03002043 if (!writethrough != blk_enable_write_cache(blk) &&
Kevin Wolf19dbecd2016-03-18 15:36:31 +01002044 blk_get_attached_dev(blk))
2045 {
2046 error_report("Cannot change cache.writeback: Device attached");
2047 qemu_opts_reset(&reopen_opts);
Max Reitzb32d7a32018-05-09 21:42:59 +02002048 return -EBUSY;
Kevin Wolf19dbecd2016-03-18 15:36:31 +01002049 }
2050
Kevin Wolff3adefb2017-09-22 14:50:12 +02002051 if (!(flags & BDRV_O_RDWR)) {
2052 uint64_t orig_perm, orig_shared_perm;
2053
2054 bdrv_drain(bs);
2055
2056 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2057 blk_set_perm(blk,
2058 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2059 orig_shared_perm,
2060 &error_abort);
2061 }
2062
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002063 qopts = qemu_opts_find(&reopen_opts, NULL);
Alberto Garciadc900c32018-11-12 16:00:42 +02002064 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002065 qemu_opts_reset(&reopen_opts);
2066
Alberto Garciadc900c32018-11-12 16:00:42 +02002067 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2068 if (has_rw_option) {
2069 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2070 qobject_unref(opts);
2071 return -EINVAL;
2072 }
2073 } else {
2074 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2075 }
2076
2077 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2078 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2079 if (has_cache_option) {
2080 error_report("Cannot set both -c and the cache options");
2081 qobject_unref(opts);
2082 return -EINVAL;
2083 }
2084 } else {
2085 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2086 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2087 }
2088
Kevin Wolf1a63a902017-12-06 20:24:44 +01002089 bdrv_subtree_drained_begin(bs);
Alberto Garcia077e8e22019-03-12 18:48:44 +02002090 brq = bdrv_reopen_queue(NULL, bs, opts, true);
Alberto Garcia5019aec2019-03-12 18:48:50 +02002091 bdrv_reopen_multiple(brq, &local_err);
Kevin Wolf1a63a902017-12-06 20:24:44 +01002092 bdrv_subtree_drained_end(bs);
2093
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002094 if (local_err) {
2095 error_report_err(local_err);
Max Reitzb32d7a32018-05-09 21:42:59 +02002096 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002097 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002098
2099 blk_set_enable_write_cache(blk, !writethrough);
2100 return 0;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002101}
2102
Max Reitzb32d7a32018-05-09 21:42:59 +02002103static int break_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02002104{
2105 int ret;
2106
Max Reitz4c7b7e92015-02-05 13:58:22 -05002107 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
Kevin Wolf797ac582013-06-05 14:19:31 +02002108 if (ret < 0) {
2109 printf("Could not set breakpoint: %s\n", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02002110 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02002111 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002112
2113 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02002114}
2115
Max Reitzb32d7a32018-05-09 21:42:59 +02002116static int remove_break_f(BlockBackend *blk, int argc, char **argv)
Fam Zheng4cc70e92013-11-20 10:01:54 +08002117{
2118 int ret;
2119
Max Reitz4c7b7e92015-02-05 13:58:22 -05002120 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
Fam Zheng4cc70e92013-11-20 10:01:54 +08002121 if (ret < 0) {
2122 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02002123 return ret;
Fam Zheng4cc70e92013-11-20 10:01:54 +08002124 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002125
2126 return 0;
Fam Zheng4cc70e92013-11-20 10:01:54 +08002127}
2128
Kevin Wolf797ac582013-06-05 14:19:31 +02002129static const cmdinfo_t break_cmd = {
2130 .name = "break",
2131 .argmin = 2,
2132 .argmax = 2,
2133 .cfunc = break_f,
2134 .args = "event tag",
2135 .oneline = "sets a breakpoint on event and tags the stopped "
2136 "request as tag",
2137};
2138
Fam Zheng4cc70e92013-11-20 10:01:54 +08002139static const cmdinfo_t remove_break_cmd = {
2140 .name = "remove_break",
2141 .argmin = 1,
2142 .argmax = 1,
2143 .cfunc = remove_break_f,
2144 .args = "tag",
2145 .oneline = "remove a breakpoint by tag",
2146};
2147
Max Reitzb32d7a32018-05-09 21:42:59 +02002148static int resume_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02002149{
2150 int ret;
2151
Max Reitz4c7b7e92015-02-05 13:58:22 -05002152 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
Kevin Wolf797ac582013-06-05 14:19:31 +02002153 if (ret < 0) {
2154 printf("Could not resume request: %s\n", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02002155 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02002156 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002157
2158 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02002159}
2160
2161static const cmdinfo_t resume_cmd = {
2162 .name = "resume",
2163 .argmin = 1,
2164 .argmax = 1,
2165 .cfunc = resume_f,
2166 .args = "tag",
2167 .oneline = "resumes the request tagged as tag",
2168};
2169
Max Reitzb32d7a32018-05-09 21:42:59 +02002170static int wait_break_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02002171{
Max Reitz4c7b7e92015-02-05 13:58:22 -05002172 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2173 aio_poll(blk_get_aio_context(blk), true);
Kevin Wolf797ac582013-06-05 14:19:31 +02002174 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002175 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02002176}
2177
2178static const cmdinfo_t wait_break_cmd = {
2179 .name = "wait_break",
2180 .argmin = 1,
2181 .argmax = 1,
2182 .cfunc = wait_break_f,
2183 .args = "tag",
2184 .oneline = "waits for the suspension of a request",
2185};
2186
Max Reitzb32d7a32018-05-09 21:42:59 +02002187static int abort_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02002188{
2189 abort();
2190}
2191
2192static const cmdinfo_t abort_cmd = {
2193 .name = "abort",
2194 .cfunc = abort_f,
2195 .flags = CMD_NOFILE_OK,
2196 .oneline = "simulate a program crash using abort(3)",
2197};
2198
Max Reitz0e82dc72014-12-08 10:48:10 +01002199static void sigraise_help(void)
2200{
2201 printf(
2202"\n"
2203" raises the given signal\n"
2204"\n"
2205" Example:\n"
2206" 'sigraise %i' - raises SIGTERM\n"
2207"\n"
2208" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2209" given to sigraise.\n"
2210"\n", SIGTERM);
2211}
2212
Max Reitzb32d7a32018-05-09 21:42:59 +02002213static int sigraise_f(BlockBackend *blk, int argc, char **argv);
Max Reitz0e82dc72014-12-08 10:48:10 +01002214
2215static const cmdinfo_t sigraise_cmd = {
2216 .name = "sigraise",
2217 .cfunc = sigraise_f,
2218 .argmin = 1,
2219 .argmax = 1,
2220 .flags = CMD_NOFILE_OK,
2221 .args = "signal",
2222 .oneline = "raises a signal",
2223 .help = sigraise_help,
2224};
2225
Max Reitzb32d7a32018-05-09 21:42:59 +02002226static int sigraise_f(BlockBackend *blk, int argc, char **argv)
Max Reitz0e82dc72014-12-08 10:48:10 +01002227{
John Snow9b0beaf2015-11-05 18:53:02 -05002228 int64_t sig = cvtnum(argv[1]);
Max Reitz0e82dc72014-12-08 10:48:10 +01002229 if (sig < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05002230 print_cvtnum_err(sig, argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002231 return sig;
John Snow9b0beaf2015-11-05 18:53:02 -05002232 } else if (sig > NSIG) {
2233 printf("signal argument '%s' is too large to be a valid signal\n",
2234 argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002235 return -EINVAL;
Max Reitz0e82dc72014-12-08 10:48:10 +01002236 }
2237
2238 /* Using raise() to kill this process does not necessarily flush all open
2239 * streams. At least stdout and stderr (although the latter should be
2240 * non-buffered anyway) should be flushed, though. */
2241 fflush(stdout);
2242 fflush(stderr);
2243
2244 raise(sig);
Max Reitzb32d7a32018-05-09 21:42:59 +02002245
2246 return 0;
Max Reitz0e82dc72014-12-08 10:48:10 +01002247}
2248
Kevin Wolfcd33d022014-01-15 15:39:10 +01002249static void sleep_cb(void *opaque)
2250{
2251 bool *expired = opaque;
2252 *expired = true;
2253}
2254
Max Reitzb32d7a32018-05-09 21:42:59 +02002255static int sleep_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolfcd33d022014-01-15 15:39:10 +01002256{
2257 char *endptr;
2258 long ms;
2259 struct QEMUTimer *timer;
2260 bool expired = false;
2261
2262 ms = strtol(argv[1], &endptr, 0);
2263 if (ms < 0 || *endptr != '\0') {
2264 printf("%s is not a valid number\n", argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002265 return -EINVAL;
Kevin Wolfcd33d022014-01-15 15:39:10 +01002266 }
2267
2268 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2269 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2270
2271 while (!expired) {
2272 main_loop_wait(false);
2273 }
2274
2275 timer_free(timer);
Max Reitzb32d7a32018-05-09 21:42:59 +02002276 return 0;
Kevin Wolfcd33d022014-01-15 15:39:10 +01002277}
2278
2279static const cmdinfo_t sleep_cmd = {
2280 .name = "sleep",
2281 .argmin = 1,
2282 .argmax = 1,
2283 .cfunc = sleep_f,
2284 .flags = CMD_NOFILE_OK,
2285 .oneline = "waits for the given value in milliseconds",
2286};
2287
Kevin Wolff18a8342013-06-05 14:19:33 +02002288static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2289{
2290 if (cmd) {
2291 printf("%s ", cmd);
2292 } else {
2293 printf("%s ", ct->name);
2294 if (ct->altname) {
2295 printf("(or %s) ", ct->altname);
2296 }
2297 }
2298
2299 if (ct->args) {
2300 printf("%s ", ct->args);
2301 }
2302 printf("-- %s\n", ct->oneline);
2303}
2304
2305static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2306{
2307 help_oneline(cmd, ct);
2308 if (ct->help) {
2309 ct->help();
2310 }
2311}
2312
2313static void help_all(void)
2314{
2315 const cmdinfo_t *ct;
2316
2317 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2318 help_oneline(ct->name, ct);
2319 }
2320 printf("\nUse 'help commandname' for extended help.\n");
2321}
2322
Max Reitzb32d7a32018-05-09 21:42:59 +02002323static int help_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolff18a8342013-06-05 14:19:33 +02002324{
2325 const cmdinfo_t *ct;
2326
2327 if (argc == 1) {
2328 help_all();
Max Reitzb32d7a32018-05-09 21:42:59 +02002329 return 0;
Kevin Wolff18a8342013-06-05 14:19:33 +02002330 }
2331
2332 ct = find_command(argv[1]);
2333 if (ct == NULL) {
2334 printf("command %s not found\n", argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002335 return -EINVAL;
Kevin Wolff18a8342013-06-05 14:19:33 +02002336 }
2337
2338 help_onecmd(argv[1], ct);
Max Reitzb32d7a32018-05-09 21:42:59 +02002339 return 0;
Kevin Wolff18a8342013-06-05 14:19:33 +02002340}
2341
2342static const cmdinfo_t help_cmd = {
2343 .name = "help",
2344 .altname = "?",
2345 .cfunc = help_f,
2346 .argmin = 0,
2347 .argmax = 1,
2348 .flags = CMD_FLAG_GLOBAL,
2349 .args = "[command]",
2350 .oneline = "help for one or all commands",
2351};
2352
Max Reitzb32d7a32018-05-09 21:42:59 +02002353int qemuio_command(BlockBackend *blk, const char *cmd)
Kevin Wolfdd583292013-06-05 14:19:32 +02002354{
Paolo Bonzini15afd942016-10-27 12:49:03 +02002355 AioContext *ctx;
Kevin Wolfdd583292013-06-05 14:19:32 +02002356 char *input;
2357 const cmdinfo_t *ct;
2358 char **v;
2359 int c;
Max Reitzb32d7a32018-05-09 21:42:59 +02002360 int ret = 0;
Kevin Wolfdd583292013-06-05 14:19:32 +02002361
2362 input = g_strdup(cmd);
2363 v = breakline(input, &c);
2364 if (c) {
2365 ct = find_command(v[0]);
2366 if (ct) {
Paolo Bonzini15afd942016-10-27 12:49:03 +02002367 ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
2368 aio_context_acquire(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02002369 ret = command(blk, ct, c, v);
Paolo Bonzini15afd942016-10-27 12:49:03 +02002370 aio_context_release(ctx);
Kevin Wolfdd583292013-06-05 14:19:32 +02002371 } else {
2372 fprintf(stderr, "command \"%s\" not found\n", v[0]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002373 ret = -EINVAL;
Kevin Wolfdd583292013-06-05 14:19:32 +02002374 }
2375 }
2376 g_free(input);
2377 g_free(v);
Max Reitzb32d7a32018-05-09 21:42:59 +02002378
2379 return ret;
Kevin Wolfdd583292013-06-05 14:19:32 +02002380}
2381
Kevin Wolf797ac582013-06-05 14:19:31 +02002382static void __attribute((constructor)) init_qemuio_commands(void)
2383{
2384 /* initialize commands */
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +02002385 qemuio_add_command(&help_cmd);
2386 qemuio_add_command(&read_cmd);
2387 qemuio_add_command(&readv_cmd);
2388 qemuio_add_command(&write_cmd);
2389 qemuio_add_command(&writev_cmd);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +02002390 qemuio_add_command(&aio_read_cmd);
2391 qemuio_add_command(&aio_write_cmd);
2392 qemuio_add_command(&aio_flush_cmd);
2393 qemuio_add_command(&flush_cmd);
2394 qemuio_add_command(&truncate_cmd);
2395 qemuio_add_command(&length_cmd);
2396 qemuio_add_command(&info_cmd);
2397 qemuio_add_command(&discard_cmd);
2398 qemuio_add_command(&alloc_cmd);
2399 qemuio_add_command(&map_cmd);
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002400 qemuio_add_command(&reopen_cmd);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +02002401 qemuio_add_command(&break_cmd);
Fam Zheng4cc70e92013-11-20 10:01:54 +08002402 qemuio_add_command(&remove_break_cmd);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +02002403 qemuio_add_command(&resume_cmd);
2404 qemuio_add_command(&wait_break_cmd);
2405 qemuio_add_command(&abort_cmd);
Kevin Wolfcd33d022014-01-15 15:39:10 +01002406 qemuio_add_command(&sleep_cmd);
Max Reitz0e82dc72014-12-08 10:48:10 +01002407 qemuio_add_command(&sigraise_cmd);
Kevin Wolf797ac582013-06-05 14:19:31 +02002408}