blob: d46fa166d308ad18e2c2c41d649d682ec80954d1 [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
Denis Plotnikov4d731512019-08-20 19:46:16 +0300353/*
354 * qemu_io_alloc_from_file()
355 *
356 * Allocates the buffer and populates it with the content of the given file
357 * up to @len bytes. If the file length is less than @len, then the buffer
358 * is populated with the file content cyclically.
359 *
360 * @blk - the block backend where the buffer content is going to be written to
361 * @len - the buffer length
362 * @file_name - the file to read the content from
363 *
364 * Returns: the buffer pointer on success
365 * NULL on error
366 */
367static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
368 const char *file_name)
369{
370 char *buf, *buf_origin;
371 FILE *f = fopen(file_name, "r");
372 int pattern_len;
373
374 if (!f) {
375 perror(file_name);
376 return NULL;
377 }
378
379 if (qemuio_misalign) {
380 len += MISALIGN_OFFSET;
381 }
382
383 buf_origin = buf = blk_blockalign(blk, len);
384
385 if (qemuio_misalign) {
386 buf_origin += MISALIGN_OFFSET;
387 buf += MISALIGN_OFFSET;
388 len -= MISALIGN_OFFSET;
389 }
390
391 pattern_len = fread(buf_origin, 1, len, f);
392
393 if (ferror(f)) {
394 perror(file_name);
395 goto error;
396 }
397
398 if (pattern_len == 0) {
399 fprintf(stderr, "%s: file is empty\n", file_name);
400 goto error;
401 }
402
403 fclose(f);
404
405 if (len > pattern_len) {
406 len -= pattern_len;
407 buf += pattern_len;
408
409 while (len > 0) {
410 size_t len_to_copy = MIN(pattern_len, len);
411
412 memcpy(buf, buf_origin, len_to_copy);
413
414 len -= len_to_copy;
415 buf += len_to_copy;
416 }
417 }
418
419 return buf_origin;
420
421error:
422 qemu_io_free(buf_origin);
423 return NULL;
424}
425
John Snow9b0beaf2015-11-05 18:53:02 -0500426static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
Kevin Wolf797ac582013-06-05 14:19:31 +0200427{
John Snow9b0beaf2015-11-05 18:53:02 -0500428 uint64_t i;
429 int j;
Kevin Wolf797ac582013-06-05 14:19:31 +0200430 const uint8_t *p;
431
432 for (i = 0, p = buffer; i < len; i += 16) {
433 const uint8_t *s = p;
434
435 printf("%08" PRIx64 ": ", offset + i);
436 for (j = 0; j < 16 && i + j < len; j++, p++) {
437 printf("%02x ", *p);
438 }
439 printf(" ");
440 for (j = 0; j < 16 && i + j < len; j++, s++) {
441 if (isalnum(*s)) {
442 printf("%c", *s);
443 } else {
444 printf(".");
445 }
446 }
447 printf("\n");
448 }
449}
450
Alex Bennée50290c02019-05-29 17:16:32 +0100451static void print_report(const char *op, struct timespec *t, int64_t offset,
Eric Blakedc388522016-05-07 21:16:42 -0600452 int64_t count, int64_t total, int cnt, bool Cflag)
Kevin Wolf797ac582013-06-05 14:19:31 +0200453{
454 char s1[64], s2[64], ts[64];
455
456 timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
457 if (!Cflag) {
458 cvtstr((double)total, s1, sizeof(s1));
459 cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
John Snow9b0beaf2015-11-05 18:53:02 -0500460 printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200461 op, total, count, offset);
462 printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
463 s1, cnt, ts, s2, tdiv((double)cnt, *t));
464 } else {/* bytes,ops,time,bytes/sec,ops/sec */
John Snow9b0beaf2015-11-05 18:53:02 -0500465 printf("%"PRId64",%d,%s,%.3f,%.3f\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200466 total, cnt, ts,
467 tdiv((double)total, *t),
468 tdiv((double)cnt, *t));
469 }
470}
471
472/*
473 * Parse multiple length statements for vectored I/O, and construct an I/O
474 * vector matching it.
475 */
476static void *
Max Reitz4c7b7e92015-02-05 13:58:22 -0500477create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
Kevin Wolf797ac582013-06-05 14:19:31 +0200478 int pattern)
479{
480 size_t *sizes = g_new0(size_t, nr_iov);
481 size_t count = 0;
482 void *buf = NULL;
483 void *p;
484 int i;
485
486 for (i = 0; i < nr_iov; i++) {
487 char *arg = argv[i];
488 int64_t len;
489
490 len = cvtnum(arg);
491 if (len < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500492 print_cvtnum_err(len, arg);
Kevin Wolf797ac582013-06-05 14:19:31 +0200493 goto fail;
494 }
495
Alberto Garcia3026c462017-01-31 18:09:54 +0200496 if (len > BDRV_REQUEST_MAX_BYTES) {
497 printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg,
498 (uint64_t)BDRV_REQUEST_MAX_BYTES);
499 goto fail;
500 }
501
502 if (count > BDRV_REQUEST_MAX_BYTES - len) {
503 printf("The total number of bytes exceed the maximum size %" PRIu64
504 "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES);
Kevin Wolf797ac582013-06-05 14:19:31 +0200505 goto fail;
506 }
507
Kevin Wolf797ac582013-06-05 14:19:31 +0200508 sizes[i] = len;
509 count += len;
510 }
511
512 qemu_iovec_init(qiov, nr_iov);
513
Max Reitz4c7b7e92015-02-05 13:58:22 -0500514 buf = p = qemu_io_alloc(blk, count, pattern);
Kevin Wolf797ac582013-06-05 14:19:31 +0200515
516 for (i = 0; i < nr_iov; i++) {
517 qemu_iovec_add(qiov, p, sizes[i]);
518 p += sizes[i];
519 }
520
521fail:
522 g_free(sizes);
523 return buf;
524}
525
John Snow9b0beaf2015-11-05 18:53:02 -0500526static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300527 int64_t bytes, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200528{
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300529 if (bytes > INT_MAX) {
John Snow9b0beaf2015-11-05 18:53:02 -0500530 return -ERANGE;
531 }
532
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300533 *total = blk_pread(blk, offset, (uint8_t *)buf, bytes);
Kevin Wolf797ac582013-06-05 14:19:31 +0200534 if (*total < 0) {
535 return *total;
536 }
537 return 1;
538}
539
John Snow9b0beaf2015-11-05 18:53:02 -0500540static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300541 int64_t bytes, int flags, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200542{
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300543 if (bytes > INT_MAX) {
John Snow9b0beaf2015-11-05 18:53:02 -0500544 return -ERANGE;
545 }
546
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300547 *total = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
Kevin Wolf797ac582013-06-05 14:19:31 +0200548 if (*total < 0) {
549 return *total;
550 }
551 return 1;
552}
553
554typedef struct {
Max Reitz4c7b7e92015-02-05 13:58:22 -0500555 BlockBackend *blk;
Kevin Wolf797ac582013-06-05 14:19:31 +0200556 int64_t offset;
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300557 int64_t bytes;
John Snow9b0beaf2015-11-05 18:53:02 -0500558 int64_t *total;
Eric Blake770e0e02016-05-07 21:16:44 -0600559 int flags;
Kevin Wolf797ac582013-06-05 14:19:31 +0200560 int ret;
561 bool done;
562} CoWriteZeroes;
563
Eric Blaked004bd52016-05-24 16:25:20 -0600564static void coroutine_fn co_pwrite_zeroes_entry(void *opaque)
Kevin Wolf797ac582013-06-05 14:19:31 +0200565{
566 CoWriteZeroes *data = opaque;
567
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300568 data->ret = blk_co_pwrite_zeroes(data->blk, data->offset, data->bytes,
Eric Blaked004bd52016-05-24 16:25:20 -0600569 data->flags);
Kevin Wolf797ac582013-06-05 14:19:31 +0200570 data->done = true;
571 if (data->ret < 0) {
572 *data->total = data->ret;
573 return;
574 }
575
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300576 *data->total = data->bytes;
Kevin Wolf797ac582013-06-05 14:19:31 +0200577}
578
Eric Blaked004bd52016-05-24 16:25:20 -0600579static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300580 int64_t bytes, int flags, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200581{
582 Coroutine *co;
583 CoWriteZeroes data = {
Max Reitz4c7b7e92015-02-05 13:58:22 -0500584 .blk = blk,
Kevin Wolf797ac582013-06-05 14:19:31 +0200585 .offset = offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300586 .bytes = bytes,
Kevin Wolf797ac582013-06-05 14:19:31 +0200587 .total = total,
Eric Blake770e0e02016-05-07 21:16:44 -0600588 .flags = flags,
Kevin Wolf797ac582013-06-05 14:19:31 +0200589 .done = false,
590 };
591
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300592 if (bytes > INT_MAX) {
John Snow9b0beaf2015-11-05 18:53:02 -0500593 return -ERANGE;
594 }
595
Paolo Bonzini0b8b8752016-07-04 19:10:01 +0200596 co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
Fam Zheng324ec3e2017-04-10 20:16:18 +0800597 bdrv_coroutine_enter(blk_bs(blk), co);
Kevin Wolf797ac582013-06-05 14:19:31 +0200598 while (!data.done) {
Max Reitz4c7b7e92015-02-05 13:58:22 -0500599 aio_poll(blk_get_aio_context(blk), true);
Kevin Wolf797ac582013-06-05 14:19:31 +0200600 }
601 if (data.ret < 0) {
602 return data.ret;
603 } else {
604 return 1;
605 }
606}
607
Max Reitz4c7b7e92015-02-05 13:58:22 -0500608static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300609 int64_t bytes, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200610{
611 int ret;
612
Alberto Garcia41ae31e2019-05-14 16:57:35 +0300613 if (bytes > BDRV_REQUEST_MAX_BYTES) {
John Snow9b0beaf2015-11-05 18:53:02 -0500614 return -ERANGE;
615 }
616
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300617 ret = blk_pwrite_compressed(blk, offset, buf, bytes);
Kevin Wolf797ac582013-06-05 14:19:31 +0200618 if (ret < 0) {
619 return ret;
620 }
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +0300621 *total = bytes;
Kevin Wolf797ac582013-06-05 14:19:31 +0200622 return 1;
623}
624
Max Reitz4c7b7e92015-02-05 13:58:22 -0500625static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset,
John Snow9b0beaf2015-11-05 18:53:02 -0500626 int64_t count, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200627{
John Snow9b0beaf2015-11-05 18:53:02 -0500628 if (count > INT_MAX) {
629 return -ERANGE;
630 }
631
Max Reitz4c7b7e92015-02-05 13:58:22 -0500632 *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count);
Kevin Wolf797ac582013-06-05 14:19:31 +0200633 if (*total < 0) {
634 return *total;
635 }
636 return 1;
637}
638
Max Reitz4c7b7e92015-02-05 13:58:22 -0500639static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset,
John Snow9b0beaf2015-11-05 18:53:02 -0500640 int64_t count, int64_t *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200641{
John Snow9b0beaf2015-11-05 18:53:02 -0500642 if (count > INT_MAX) {
643 return -ERANGE;
644 }
645
Max Reitz4c7b7e92015-02-05 13:58:22 -0500646 *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count);
Kevin Wolf797ac582013-06-05 14:19:31 +0200647 if (*total < 0) {
648 return *total;
649 }
650 return 1;
651}
652
653#define NOT_DONE 0x7fffffff
654static void aio_rw_done(void *opaque, int ret)
655{
656 *(int *)opaque = ret;
657}
658
Max Reitz4c7b7e92015-02-05 13:58:22 -0500659static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
Kevin Wolf797ac582013-06-05 14:19:31 +0200660 int64_t offset, int *total)
661{
662 int async_ret = NOT_DONE;
663
Eric Blake7b3f9712016-05-06 10:26:44 -0600664 blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret);
Kevin Wolf797ac582013-06-05 14:19:31 +0200665 while (async_ret == NOT_DONE) {
666 main_loop_wait(false);
667 }
668
669 *total = qiov->size;
670 return async_ret < 0 ? async_ret : 1;
671}
672
Max Reitz4c7b7e92015-02-05 13:58:22 -0500673static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
Eric Blake770e0e02016-05-07 21:16:44 -0600674 int64_t offset, int flags, int *total)
Kevin Wolf797ac582013-06-05 14:19:31 +0200675{
676 int async_ret = NOT_DONE;
677
Eric Blake770e0e02016-05-07 21:16:44 -0600678 blk_aio_pwritev(blk, offset, qiov, flags, aio_rw_done, &async_ret);
Kevin Wolf797ac582013-06-05 14:19:31 +0200679 while (async_ret == NOT_DONE) {
680 main_loop_wait(false);
681 }
682
683 *total = qiov->size;
684 return async_ret < 0 ? async_ret : 1;
685}
686
Kevin Wolf797ac582013-06-05 14:19:31 +0200687static void read_help(void)
688{
689 printf(
690"\n"
691" reads a range of bytes from the given offset\n"
692"\n"
693" Example:\n"
694" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
695"\n"
696" Reads a segment of the currently open file, optionally dumping it to the\n"
697" standard output stream (with -v option) for subsequent inspection.\n"
698" -b, -- read from the VM state rather than the virtual disk\n"
699" -C, -- report statistics in a machine parsable format\n"
700" -l, -- length for pattern verification (only with -P)\n"
Eric Blake093ea232016-05-07 21:16:43 -0600701" -p, -- ignored for backwards compatibility\n"
Kevin Wolf797ac582013-06-05 14:19:31 +0200702" -P, -- use a pattern to verify read data\n"
703" -q, -- quiet mode, do not show I/O statistics\n"
704" -s, -- start offset for pattern verification (only with -P)\n"
705" -v, -- dump buffer to standard output\n"
706"\n");
707}
708
Max Reitzb32d7a32018-05-09 21:42:59 +0200709static int read_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +0200710
711static const cmdinfo_t read_cmd = {
712 .name = "read",
713 .altname = "r",
714 .cfunc = read_f,
715 .argmin = 2,
716 .argmax = -1,
Eric Blake093ea232016-05-07 21:16:43 -0600717 .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len",
Kevin Wolf797ac582013-06-05 14:19:31 +0200718 .oneline = "reads a number of bytes at a specified offset",
719 .help = read_help,
720};
721
Max Reitzb32d7a32018-05-09 21:42:59 +0200722static int read_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +0200723{
Alex Bennée50290c02019-05-29 17:16:32 +0100724 struct timespec t1, t2;
Eric Blake093ea232016-05-07 21:16:43 -0600725 bool Cflag = false, qflag = false, vflag = false;
Eric Blakedc388522016-05-07 21:16:42 -0600726 bool Pflag = false, sflag = false, lflag = false, bflag = false;
Max Reitzb32d7a32018-05-09 21:42:59 +0200727 int c, cnt, ret;
Kevin Wolf797ac582013-06-05 14:19:31 +0200728 char *buf;
729 int64_t offset;
John Snow9b0beaf2015-11-05 18:53:02 -0500730 int64_t count;
Kevin Wolf797ac582013-06-05 14:19:31 +0200731 /* Some compilers get confused and warn if this is not initialized. */
John Snow9b0beaf2015-11-05 18:53:02 -0500732 int64_t total = 0;
733 int pattern = 0;
734 int64_t pattern_offset = 0, pattern_count = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +0200735
Eric Blakeb062ad82015-05-12 09:10:56 -0600736 while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +0200737 switch (c) {
738 case 'b':
Eric Blakedc388522016-05-07 21:16:42 -0600739 bflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200740 break;
741 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -0600742 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200743 break;
744 case 'l':
Eric Blakedc388522016-05-07 21:16:42 -0600745 lflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200746 pattern_count = cvtnum(optarg);
747 if (pattern_count < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500748 print_cvtnum_err(pattern_count, optarg);
Max Reitzb32d7a32018-05-09 21:42:59 +0200749 return pattern_count;
Kevin Wolf797ac582013-06-05 14:19:31 +0200750 }
751 break;
752 case 'p':
Eric Blake093ea232016-05-07 21:16:43 -0600753 /* Ignored for backwards compatibility */
Kevin Wolf797ac582013-06-05 14:19:31 +0200754 break;
755 case 'P':
Eric Blakedc388522016-05-07 21:16:42 -0600756 Pflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200757 pattern = parse_pattern(optarg);
758 if (pattern < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +0200759 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200760 }
761 break;
762 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -0600763 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200764 break;
765 case 's':
Eric Blakedc388522016-05-07 21:16:42 -0600766 sflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200767 pattern_offset = cvtnum(optarg);
768 if (pattern_offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500769 print_cvtnum_err(pattern_offset, optarg);
Max Reitzb32d7a32018-05-09 21:42:59 +0200770 return pattern_offset;
Kevin Wolf797ac582013-06-05 14:19:31 +0200771 }
772 break;
773 case 'v':
Eric Blakedc388522016-05-07 21:16:42 -0600774 vflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200775 break;
776 default:
Max Reitzb444d0e2018-05-09 21:42:58 +0200777 qemuio_command_usage(&read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200778 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200779 }
780 }
781
782 if (optind != argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +0200783 qemuio_command_usage(&read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200784 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200785 }
786
Kevin Wolf797ac582013-06-05 14:19:31 +0200787 offset = cvtnum(argv[optind]);
788 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500789 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +0200790 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +0200791 }
792
793 optind++;
794 count = cvtnum(argv[optind]);
795 if (count < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500796 print_cvtnum_err(count, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +0200797 return count;
Alberto Garcia3026c462017-01-31 18:09:54 +0200798 } else if (count > BDRV_REQUEST_MAX_BYTES) {
John Snow9b0beaf2015-11-05 18:53:02 -0500799 printf("length cannot exceed %" PRIu64 ", given %s\n",
Alberto Garcia3026c462017-01-31 18:09:54 +0200800 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +0200801 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200802 }
803
804 if (!Pflag && (lflag || sflag)) {
Max Reitzb444d0e2018-05-09 21:42:58 +0200805 qemuio_command_usage(&read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200806 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200807 }
808
809 if (!lflag) {
810 pattern_count = count - pattern_offset;
811 }
812
813 if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
814 printf("pattern verification range exceeds end of read data\n");
Max Reitzb32d7a32018-05-09 21:42:59 +0200815 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200816 }
817
Eric Blake093ea232016-05-07 21:16:43 -0600818 if (bflag) {
Eric Blake1bce6b42017-04-29 14:14:11 -0500819 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
820 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200821 offset);
Max Reitzb32d7a32018-05-09 21:42:59 +0200822 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200823 }
Eric Blake1bce6b42017-04-29 14:14:11 -0500824 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
825 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200826 count);
Max Reitzb32d7a32018-05-09 21:42:59 +0200827 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200828 }
829 }
830
Max Reitz4c7b7e92015-02-05 13:58:22 -0500831 buf = qemu_io_alloc(blk, count, 0xab);
Kevin Wolf797ac582013-06-05 14:19:31 +0200832
Alex Bennée50290c02019-05-29 17:16:32 +0100833 clock_gettime(CLOCK_MONOTONIC, &t1);
Eric Blake7b3f9712016-05-06 10:26:44 -0600834 if (bflag) {
Max Reitzb32d7a32018-05-09 21:42:59 +0200835 ret = do_load_vmstate(blk, buf, offset, count, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +0200836 } else {
Max Reitzb32d7a32018-05-09 21:42:59 +0200837 ret = do_pread(blk, buf, offset, count, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +0200838 }
Alex Bennée50290c02019-05-29 17:16:32 +0100839 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +0200840
Max Reitzb32d7a32018-05-09 21:42:59 +0200841 if (ret < 0) {
842 printf("read failed: %s\n", strerror(-ret));
Kevin Wolf797ac582013-06-05 14:19:31 +0200843 goto out;
844 }
Max Reitzb32d7a32018-05-09 21:42:59 +0200845 cnt = ret;
846
847 ret = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +0200848
849 if (Pflag) {
850 void *cmp_buf = g_malloc(pattern_count);
851 memset(cmp_buf, pattern, pattern_count);
852 if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
853 printf("Pattern verification failed at offset %"
John Snow9b0beaf2015-11-05 18:53:02 -0500854 PRId64 ", %"PRId64" bytes\n",
Kevin Wolf797ac582013-06-05 14:19:31 +0200855 offset + pattern_offset, pattern_count);
Max Reitzb32d7a32018-05-09 21:42:59 +0200856 ret = -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200857 }
858 g_free(cmp_buf);
859 }
860
861 if (qflag) {
862 goto out;
863 }
864
865 if (vflag) {
866 dump_buffer(buf, offset, count);
867 }
868
869 /* Finally, report back -- -C gives a parsable format */
870 t2 = tsub(t2, t1);
871 print_report("read", &t2, offset, count, total, cnt, Cflag);
872
873out:
874 qemu_io_free(buf);
Max Reitzb32d7a32018-05-09 21:42:59 +0200875 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +0200876}
877
878static void readv_help(void)
879{
880 printf(
881"\n"
882" reads a range of bytes from the given offset into multiple buffers\n"
883"\n"
884" Example:\n"
885" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
886"\n"
887" Reads a segment of the currently open file, optionally dumping it to the\n"
888" standard output stream (with -v option) for subsequent inspection.\n"
889" Uses multiple iovec buffers if more than one byte range is specified.\n"
890" -C, -- report statistics in a machine parsable format\n"
891" -P, -- use a pattern to verify read data\n"
892" -v, -- dump buffer to standard output\n"
893" -q, -- quiet mode, do not show I/O statistics\n"
894"\n");
895}
896
Max Reitzb32d7a32018-05-09 21:42:59 +0200897static int readv_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +0200898
899static const cmdinfo_t readv_cmd = {
900 .name = "readv",
901 .cfunc = readv_f,
902 .argmin = 2,
903 .argmax = -1,
Eric Blake093ea232016-05-07 21:16:43 -0600904 .args = "[-Cqv] [-P pattern] off len [len..]",
Kevin Wolf797ac582013-06-05 14:19:31 +0200905 .oneline = "reads a number of bytes at a specified offset",
906 .help = readv_help,
907};
908
Max Reitzb32d7a32018-05-09 21:42:59 +0200909static int readv_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +0200910{
Alex Bennée50290c02019-05-29 17:16:32 +0100911 struct timespec t1, t2;
Eric Blakedc388522016-05-07 21:16:42 -0600912 bool Cflag = false, qflag = false, vflag = false;
Max Reitzb32d7a32018-05-09 21:42:59 +0200913 int c, cnt, ret;
Kevin Wolf797ac582013-06-05 14:19:31 +0200914 char *buf;
915 int64_t offset;
916 /* Some compilers get confused and warn if this is not initialized. */
917 int total = 0;
918 int nr_iov;
919 QEMUIOVector qiov;
920 int pattern = 0;
Eric Blakedc388522016-05-07 21:16:42 -0600921 bool Pflag = false;
Kevin Wolf797ac582013-06-05 14:19:31 +0200922
Eric Blakeb062ad82015-05-12 09:10:56 -0600923 while ((c = getopt(argc, argv, "CP:qv")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +0200924 switch (c) {
925 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -0600926 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200927 break;
928 case 'P':
Eric Blakedc388522016-05-07 21:16:42 -0600929 Pflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200930 pattern = parse_pattern(optarg);
931 if (pattern < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +0200932 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200933 }
934 break;
935 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -0600936 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200937 break;
938 case 'v':
Eric Blakedc388522016-05-07 21:16:42 -0600939 vflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +0200940 break;
941 default:
Max Reitzb444d0e2018-05-09 21:42:58 +0200942 qemuio_command_usage(&readv_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200943 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200944 }
945 }
946
947 if (optind > argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +0200948 qemuio_command_usage(&readv_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +0200949 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200950 }
951
952
953 offset = cvtnum(argv[optind]);
954 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -0500955 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +0200956 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +0200957 }
958 optind++;
959
Kevin Wolf797ac582013-06-05 14:19:31 +0200960 nr_iov = argc - optind;
Max Reitz4c7b7e92015-02-05 13:58:22 -0500961 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
Kevin Wolf797ac582013-06-05 14:19:31 +0200962 if (buf == NULL) {
Max Reitzb32d7a32018-05-09 21:42:59 +0200963 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200964 }
965
Alex Bennée50290c02019-05-29 17:16:32 +0100966 clock_gettime(CLOCK_MONOTONIC, &t1);
Max Reitzb32d7a32018-05-09 21:42:59 +0200967 ret = do_aio_readv(blk, &qiov, offset, &total);
Alex Bennée50290c02019-05-29 17:16:32 +0100968 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +0200969
Max Reitzb32d7a32018-05-09 21:42:59 +0200970 if (ret < 0) {
971 printf("readv failed: %s\n", strerror(-ret));
Kevin Wolf797ac582013-06-05 14:19:31 +0200972 goto out;
973 }
Max Reitzb32d7a32018-05-09 21:42:59 +0200974 cnt = ret;
975
976 ret = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +0200977
978 if (Pflag) {
979 void *cmp_buf = g_malloc(qiov.size);
980 memset(cmp_buf, pattern, qiov.size);
981 if (memcmp(buf, cmp_buf, qiov.size)) {
982 printf("Pattern verification failed at offset %"
Stefan Weilcf67b692018-10-06 20:38:51 +0200983 PRId64 ", %zu bytes\n", offset, qiov.size);
Max Reitzb32d7a32018-05-09 21:42:59 +0200984 ret = -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +0200985 }
986 g_free(cmp_buf);
987 }
988
989 if (qflag) {
990 goto out;
991 }
992
993 if (vflag) {
994 dump_buffer(buf, offset, qiov.size);
995 }
996
997 /* Finally, report back -- -C gives a parsable format */
998 t2 = tsub(t2, t1);
999 print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
1000
1001out:
1002 qemu_iovec_destroy(&qiov);
1003 qemu_io_free(buf);
Max Reitzb32d7a32018-05-09 21:42:59 +02001004 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001005}
1006
1007static void write_help(void)
1008{
1009 printf(
1010"\n"
1011" writes a range of bytes from the given offset\n"
1012"\n"
1013" Example:\n"
1014" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
1015"\n"
1016" Writes into a segment of the currently open file, using a buffer\n"
1017" filled with a set pattern (0xcdcdcdcd).\n"
1018" -b, -- write to the VM state rather than the virtual disk\n"
Max Reitz4c7b7e92015-02-05 13:58:22 -05001019" -c, -- write compressed data with blk_write_compressed\n"
Eric Blake770e0e02016-05-07 21:16:44 -06001020" -f, -- use Force Unit Access semantics\n"
Kevin Wolfc6e3f522019-03-22 13:53:03 +01001021" -n, -- with -z, don't allow slow fallback\n"
Eric Blake093ea232016-05-07 21:16:43 -06001022" -p, -- ignored for backwards compatibility\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001023" -P, -- use different pattern to fill file\n"
Denis Plotnikov4d731512019-08-20 19:46:16 +03001024" -s, -- use a pattern file to fill the write buffer\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001025" -C, -- report statistics in a machine parsable format\n"
1026" -q, -- quiet mode, do not show I/O statistics\n"
Eric Blakec2e001c2016-05-07 21:16:45 -06001027" -u, -- with -z, allow unmapping\n"
Eric Blaked004bd52016-05-24 16:25:20 -06001028" -z, -- write zeroes using blk_co_pwrite_zeroes\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001029"\n");
1030}
1031
Max Reitzb32d7a32018-05-09 21:42:59 +02001032static int write_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001033
1034static const cmdinfo_t write_cmd = {
1035 .name = "write",
1036 .altname = "w",
1037 .cfunc = write_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001038 .perm = BLK_PERM_WRITE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001039 .argmin = 2,
1040 .argmax = -1,
Denis Plotnikov4d731512019-08-20 19:46:16 +03001041 .args = "[-bcCfnquz] [-P pattern | -s source_file] off len",
Kevin Wolf797ac582013-06-05 14:19:31 +02001042 .oneline = "writes a number of bytes at a specified offset",
1043 .help = write_help,
1044};
1045
Max Reitzb32d7a32018-05-09 21:42:59 +02001046static int write_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001047{
Alex Bennée50290c02019-05-29 17:16:32 +01001048 struct timespec t1, t2;
Eric Blake093ea232016-05-07 21:16:43 -06001049 bool Cflag = false, qflag = false, bflag = false;
Denis Plotnikov4d731512019-08-20 19:46:16 +03001050 bool Pflag = false, zflag = false, cflag = false, sflag = false;
Eric Blake770e0e02016-05-07 21:16:44 -06001051 int flags = 0;
Max Reitzb32d7a32018-05-09 21:42:59 +02001052 int c, cnt, ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001053 char *buf = NULL;
1054 int64_t offset;
John Snow9b0beaf2015-11-05 18:53:02 -05001055 int64_t count;
Kevin Wolf797ac582013-06-05 14:19:31 +02001056 /* Some compilers get confused and warn if this is not initialized. */
John Snow9b0beaf2015-11-05 18:53:02 -05001057 int64_t total = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001058 int pattern = 0xcd;
Denis Plotnikov4d731512019-08-20 19:46:16 +03001059 const char *file_name = NULL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001060
Denis Plotnikov4d731512019-08-20 19:46:16 +03001061 while ((c = getopt(argc, argv, "bcCfnpP:qs:uz")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001062 switch (c) {
1063 case 'b':
Eric Blakedc388522016-05-07 21:16:42 -06001064 bflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001065 break;
1066 case 'c':
Eric Blakedc388522016-05-07 21:16:42 -06001067 cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001068 break;
1069 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001070 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001071 break;
Eric Blake770e0e02016-05-07 21:16:44 -06001072 case 'f':
1073 flags |= BDRV_REQ_FUA;
1074 break;
Kevin Wolfc6e3f522019-03-22 13:53:03 +01001075 case 'n':
1076 flags |= BDRV_REQ_NO_FALLBACK;
1077 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001078 case 'p':
Eric Blake093ea232016-05-07 21:16:43 -06001079 /* Ignored for backwards compatibility */
Kevin Wolf797ac582013-06-05 14:19:31 +02001080 break;
1081 case 'P':
Eric Blakedc388522016-05-07 21:16:42 -06001082 Pflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001083 pattern = parse_pattern(optarg);
1084 if (pattern < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001085 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001086 }
1087 break;
1088 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001089 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001090 break;
Denis Plotnikov4d731512019-08-20 19:46:16 +03001091 case 's':
1092 sflag = true;
1093 file_name = optarg;
1094 break;
Eric Blakec2e001c2016-05-07 21:16:45 -06001095 case 'u':
1096 flags |= BDRV_REQ_MAY_UNMAP;
1097 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001098 case 'z':
Eric Blakedc388522016-05-07 21:16:42 -06001099 zflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001100 break;
1101 default:
Max Reitzb444d0e2018-05-09 21:42:58 +02001102 qemuio_command_usage(&write_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001103 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001104 }
1105 }
1106
1107 if (optind != argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +02001108 qemuio_command_usage(&write_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001109 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001110 }
1111
Eric Blake093ea232016-05-07 21:16:43 -06001112 if (bflag && zflag) {
1113 printf("-b and -z cannot be specified at the same time\n");
Max Reitzb32d7a32018-05-09 21:42:59 +02001114 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001115 }
1116
Eric Blake770e0e02016-05-07 21:16:44 -06001117 if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
1118 printf("-f and -b or -c cannot be specified at the same time\n");
Max Reitzb32d7a32018-05-09 21:42:59 +02001119 return -EINVAL;
Eric Blake770e0e02016-05-07 21:16:44 -06001120 }
1121
Kevin Wolfc6e3f522019-03-22 13:53:03 +01001122 if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
1123 printf("-n requires -z to be specified\n");
1124 return -EINVAL;
1125 }
1126
Eric Blakec2e001c2016-05-07 21:16:45 -06001127 if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
1128 printf("-u requires -z to be specified\n");
Max Reitzb32d7a32018-05-09 21:42:59 +02001129 return -EINVAL;
Eric Blakec2e001c2016-05-07 21:16:45 -06001130 }
1131
Denis Plotnikov4d731512019-08-20 19:46:16 +03001132 if (zflag + Pflag + sflag > 1) {
1133 printf("Only one of -z, -P, and -s "
1134 "can be specified at the same time\n");
Max Reitzb32d7a32018-05-09 21:42:59 +02001135 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001136 }
1137
1138 offset = cvtnum(argv[optind]);
1139 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001140 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001141 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001142 }
1143
1144 optind++;
1145 count = cvtnum(argv[optind]);
1146 if (count < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001147 print_cvtnum_err(count, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001148 return count;
Alberto Garcia3026c462017-01-31 18:09:54 +02001149 } else if (count > BDRV_REQUEST_MAX_BYTES) {
John Snow9b0beaf2015-11-05 18:53:02 -05001150 printf("length cannot exceed %" PRIu64 ", given %s\n",
Alberto Garcia3026c462017-01-31 18:09:54 +02001151 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001152 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001153 }
1154
Eric Blake093ea232016-05-07 21:16:43 -06001155 if (bflag || cflag) {
Eric Blake1bce6b42017-04-29 14:14:11 -05001156 if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
1157 printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
Kevin Wolf797ac582013-06-05 14:19:31 +02001158 offset);
Max Reitzb32d7a32018-05-09 21:42:59 +02001159 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001160 }
1161
Eric Blake1bce6b42017-04-29 14:14:11 -05001162 if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
1163 printf("%"PRId64" is not a sector-aligned value for 'count'\n",
Kevin Wolf797ac582013-06-05 14:19:31 +02001164 count);
Max Reitzb32d7a32018-05-09 21:42:59 +02001165 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001166 }
1167 }
1168
1169 if (!zflag) {
Denis Plotnikov4d731512019-08-20 19:46:16 +03001170 if (sflag) {
1171 buf = qemu_io_alloc_from_file(blk, count, file_name);
1172 if (!buf) {
1173 return -EINVAL;
1174 }
1175 } else {
1176 buf = qemu_io_alloc(blk, count, pattern);
1177 }
Kevin Wolf797ac582013-06-05 14:19:31 +02001178 }
1179
Alex Bennée50290c02019-05-29 17:16:32 +01001180 clock_gettime(CLOCK_MONOTONIC, &t1);
Eric Blake7b3f9712016-05-06 10:26:44 -06001181 if (bflag) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001182 ret = do_save_vmstate(blk, buf, offset, count, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +02001183 } else if (zflag) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001184 ret = do_co_pwrite_zeroes(blk, offset, count, flags, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +02001185 } else if (cflag) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001186 ret = do_write_compressed(blk, buf, offset, count, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +02001187 } else {
Max Reitzb32d7a32018-05-09 21:42:59 +02001188 ret = do_pwrite(blk, buf, offset, count, flags, &total);
Kevin Wolf797ac582013-06-05 14:19:31 +02001189 }
Alex Bennée50290c02019-05-29 17:16:32 +01001190 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001191
Max Reitzb32d7a32018-05-09 21:42:59 +02001192 if (ret < 0) {
1193 printf("write failed: %s\n", strerror(-ret));
Kevin Wolf797ac582013-06-05 14:19:31 +02001194 goto out;
1195 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001196 cnt = ret;
1197
1198 ret = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001199
1200 if (qflag) {
1201 goto out;
1202 }
1203
1204 /* Finally, report back -- -C gives a parsable format */
1205 t2 = tsub(t2, t1);
1206 print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1207
1208out:
1209 if (!zflag) {
1210 qemu_io_free(buf);
1211 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001212 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001213}
1214
1215static void
1216writev_help(void)
1217{
1218 printf(
1219"\n"
1220" writes a range of bytes from the given offset source from multiple buffers\n"
1221"\n"
1222" Example:\n"
Maria Kustova6e6507c2014-03-18 09:59:17 +04001223" 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001224"\n"
1225" Writes into a segment of the currently open file, using a buffer\n"
1226" filled with a set pattern (0xcdcdcdcd).\n"
1227" -P, -- use different pattern to fill file\n"
1228" -C, -- report statistics in a machine parsable format\n"
Eric Blake770e0e02016-05-07 21:16:44 -06001229" -f, -- use Force Unit Access semantics\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001230" -q, -- quiet mode, do not show I/O statistics\n"
1231"\n");
1232}
1233
Max Reitzb32d7a32018-05-09 21:42:59 +02001234static int writev_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001235
1236static const cmdinfo_t writev_cmd = {
1237 .name = "writev",
1238 .cfunc = writev_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001239 .perm = BLK_PERM_WRITE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001240 .argmin = 2,
1241 .argmax = -1,
Eric Blake770e0e02016-05-07 21:16:44 -06001242 .args = "[-Cfq] [-P pattern] off len [len..]",
Kevin Wolf797ac582013-06-05 14:19:31 +02001243 .oneline = "writes a number of bytes at a specified offset",
1244 .help = writev_help,
1245};
1246
Max Reitzb32d7a32018-05-09 21:42:59 +02001247static int writev_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001248{
Alex Bennée50290c02019-05-29 17:16:32 +01001249 struct timespec t1, t2;
Eric Blakedc388522016-05-07 21:16:42 -06001250 bool Cflag = false, qflag = false;
Eric Blake770e0e02016-05-07 21:16:44 -06001251 int flags = 0;
Max Reitzb32d7a32018-05-09 21:42:59 +02001252 int c, cnt, ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001253 char *buf;
1254 int64_t offset;
1255 /* Some compilers get confused and warn if this is not initialized. */
1256 int total = 0;
1257 int nr_iov;
1258 int pattern = 0xcd;
1259 QEMUIOVector qiov;
1260
Eric Blake4ca1d342016-05-16 10:43:01 -06001261 while ((c = getopt(argc, argv, "CfqP:")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001262 switch (c) {
1263 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001264 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001265 break;
Eric Blake770e0e02016-05-07 21:16:44 -06001266 case 'f':
1267 flags |= BDRV_REQ_FUA;
1268 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001269 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001270 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001271 break;
1272 case 'P':
1273 pattern = parse_pattern(optarg);
1274 if (pattern < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001275 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001276 }
1277 break;
1278 default:
Max Reitzb444d0e2018-05-09 21:42:58 +02001279 qemuio_command_usage(&writev_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001280 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001281 }
1282 }
1283
1284 if (optind > argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +02001285 qemuio_command_usage(&writev_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001286 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001287 }
1288
1289 offset = cvtnum(argv[optind]);
1290 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001291 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001292 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001293 }
1294 optind++;
1295
Kevin Wolf797ac582013-06-05 14:19:31 +02001296 nr_iov = argc - optind;
Max Reitz4c7b7e92015-02-05 13:58:22 -05001297 buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
Kevin Wolf797ac582013-06-05 14:19:31 +02001298 if (buf == NULL) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001299 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001300 }
1301
Alex Bennée50290c02019-05-29 17:16:32 +01001302 clock_gettime(CLOCK_MONOTONIC, &t1);
Max Reitzb32d7a32018-05-09 21:42:59 +02001303 ret = do_aio_writev(blk, &qiov, offset, flags, &total);
Alex Bennée50290c02019-05-29 17:16:32 +01001304 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001305
Max Reitzb32d7a32018-05-09 21:42:59 +02001306 if (ret < 0) {
1307 printf("writev failed: %s\n", strerror(-ret));
Kevin Wolf797ac582013-06-05 14:19:31 +02001308 goto out;
1309 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001310 cnt = ret;
1311
1312 ret = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001313
1314 if (qflag) {
1315 goto out;
1316 }
1317
1318 /* Finally, report back -- -C gives a parsable format */
1319 t2 = tsub(t2, t1);
1320 print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1321out:
1322 qemu_iovec_destroy(&qiov);
1323 qemu_io_free(buf);
Max Reitzb32d7a32018-05-09 21:42:59 +02001324 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001325}
1326
Kevin Wolf797ac582013-06-05 14:19:31 +02001327struct aio_ctx {
Max Reitz4c7b7e92015-02-05 13:58:22 -05001328 BlockBackend *blk;
Kevin Wolf797ac582013-06-05 14:19:31 +02001329 QEMUIOVector qiov;
1330 int64_t offset;
1331 char *buf;
Eric Blakedc388522016-05-07 21:16:42 -06001332 bool qflag;
1333 bool vflag;
1334 bool Cflag;
1335 bool Pflag;
1336 bool zflag;
Fam Zhenga91f9582015-01-30 10:49:42 +08001337 BlockAcctCookie acct;
Kevin Wolf797ac582013-06-05 14:19:31 +02001338 int pattern;
Alex Bennée50290c02019-05-29 17:16:32 +01001339 struct timespec t1;
Kevin Wolf797ac582013-06-05 14:19:31 +02001340};
1341
1342static void aio_write_done(void *opaque, int ret)
1343{
1344 struct aio_ctx *ctx = opaque;
Alex Bennée50290c02019-05-29 17:16:32 +01001345 struct timespec t2;
Kevin Wolf797ac582013-06-05 14:19:31 +02001346
Alex Bennée50290c02019-05-29 17:16:32 +01001347 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001348
1349
1350 if (ret < 0) {
1351 printf("aio_write failed: %s\n", strerror(-ret));
Alberto Garcia556c2b62015-10-28 17:33:08 +02001352 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
Kevin Wolf797ac582013-06-05 14:19:31 +02001353 goto out;
1354 }
1355
Max Reitz4c7b7e92015-02-05 13:58:22 -05001356 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
Fam Zhenga91f9582015-01-30 10:49:42 +08001357
Kevin Wolf797ac582013-06-05 14:19:31 +02001358 if (ctx->qflag) {
1359 goto out;
1360 }
1361
1362 /* Finally, report back -- -C gives a parsable format */
1363 t2 = tsub(t2, ctx->t1);
1364 print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1365 ctx->qiov.size, 1, ctx->Cflag);
1366out:
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001367 if (!ctx->zflag) {
1368 qemu_io_free(ctx->buf);
1369 qemu_iovec_destroy(&ctx->qiov);
1370 }
Kevin Wolf797ac582013-06-05 14:19:31 +02001371 g_free(ctx);
1372}
1373
1374static void aio_read_done(void *opaque, int ret)
1375{
1376 struct aio_ctx *ctx = opaque;
Alex Bennée50290c02019-05-29 17:16:32 +01001377 struct timespec t2;
Kevin Wolf797ac582013-06-05 14:19:31 +02001378
Alex Bennée50290c02019-05-29 17:16:32 +01001379 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001380
1381 if (ret < 0) {
1382 printf("readv failed: %s\n", strerror(-ret));
Alberto Garcia556c2b62015-10-28 17:33:08 +02001383 block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
Kevin Wolf797ac582013-06-05 14:19:31 +02001384 goto out;
1385 }
1386
1387 if (ctx->Pflag) {
1388 void *cmp_buf = g_malloc(ctx->qiov.size);
1389
1390 memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1391 if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1392 printf("Pattern verification failed at offset %"
Stefan Weilcf67b692018-10-06 20:38:51 +02001393 PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
Kevin Wolf797ac582013-06-05 14:19:31 +02001394 }
1395 g_free(cmp_buf);
1396 }
1397
Max Reitz4c7b7e92015-02-05 13:58:22 -05001398 block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
Fam Zhenga91f9582015-01-30 10:49:42 +08001399
Kevin Wolf797ac582013-06-05 14:19:31 +02001400 if (ctx->qflag) {
1401 goto out;
1402 }
1403
1404 if (ctx->vflag) {
1405 dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1406 }
1407
1408 /* Finally, report back -- -C gives a parsable format */
1409 t2 = tsub(t2, ctx->t1);
1410 print_report("read", &t2, ctx->offset, ctx->qiov.size,
1411 ctx->qiov.size, 1, ctx->Cflag);
1412out:
1413 qemu_io_free(ctx->buf);
1414 qemu_iovec_destroy(&ctx->qiov);
1415 g_free(ctx);
1416}
1417
1418static void aio_read_help(void)
1419{
1420 printf(
1421"\n"
1422" asynchronously reads a range of bytes from the given offset\n"
1423"\n"
1424" Example:\n"
1425" 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1426"\n"
1427" Reads a segment of the currently open file, optionally dumping it to the\n"
1428" standard output stream (with -v option) for subsequent inspection.\n"
1429" The read is performed asynchronously and the aio_flush command must be\n"
1430" used to ensure all outstanding aio requests have been completed.\n"
Max Reitzb32d7a32018-05-09 21:42:59 +02001431" Note that due to its asynchronous nature, this command will be\n"
1432" considered successful once the request is submitted, independently\n"
1433" of potential I/O errors or pattern mismatches.\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001434" -C, -- report statistics in a machine parsable format\n"
1435" -P, -- use a pattern to verify read data\n"
Eric Blake37546ff2016-05-16 10:43:03 -06001436" -i, -- treat request as invalid, for exercising stats\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001437" -v, -- dump buffer to standard output\n"
1438" -q, -- quiet mode, do not show I/O statistics\n"
1439"\n");
1440}
1441
Max Reitzb32d7a32018-05-09 21:42:59 +02001442static int aio_read_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001443
1444static const cmdinfo_t aio_read_cmd = {
1445 .name = "aio_read",
1446 .cfunc = aio_read_f,
1447 .argmin = 2,
1448 .argmax = -1,
Eric Blake37546ff2016-05-16 10:43:03 -06001449 .args = "[-Ciqv] [-P pattern] off len [len..]",
Kevin Wolf797ac582013-06-05 14:19:31 +02001450 .oneline = "asynchronously reads a number of bytes",
1451 .help = aio_read_help,
1452};
1453
Max Reitzb32d7a32018-05-09 21:42:59 +02001454static int aio_read_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001455{
1456 int nr_iov, c;
1457 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1458
Max Reitz4c7b7e92015-02-05 13:58:22 -05001459 ctx->blk = blk;
Eric Blake37546ff2016-05-16 10:43:03 -06001460 while ((c = getopt(argc, argv, "CP:iqv")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001461 switch (c) {
1462 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001463 ctx->Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001464 break;
1465 case 'P':
Eric Blakedc388522016-05-07 21:16:42 -06001466 ctx->Pflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001467 ctx->pattern = parse_pattern(optarg);
1468 if (ctx->pattern < 0) {
1469 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001470 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001471 }
1472 break;
Eric Blake37546ff2016-05-16 10:43:03 -06001473 case 'i':
1474 printf("injecting invalid read request\n");
1475 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
1476 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001477 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001478 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001479 ctx->qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001480 break;
1481 case 'v':
Eric Blakedc388522016-05-07 21:16:42 -06001482 ctx->vflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001483 break;
1484 default:
1485 g_free(ctx);
Max Reitzb444d0e2018-05-09 21:42:58 +02001486 qemuio_command_usage(&aio_read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001487 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001488 }
1489 }
1490
1491 if (optind > argc - 2) {
1492 g_free(ctx);
Max Reitzb444d0e2018-05-09 21:42:58 +02001493 qemuio_command_usage(&aio_read_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001494 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001495 }
1496
1497 ctx->offset = cvtnum(argv[optind]);
1498 if (ctx->offset < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001499 int ret = ctx->offset;
1500 print_cvtnum_err(ret, argv[optind]);
Kevin Wolf797ac582013-06-05 14:19:31 +02001501 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001502 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001503 }
1504 optind++;
1505
Kevin Wolf797ac582013-06-05 14:19:31 +02001506 nr_iov = argc - optind;
Max Reitz4c7b7e92015-02-05 13:58:22 -05001507 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
Kevin Wolf797ac582013-06-05 14:19:31 +02001508 if (ctx->buf == NULL) {
Alberto Garcia556c2b62015-10-28 17:33:08 +02001509 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
Kevin Wolf797ac582013-06-05 14:19:31 +02001510 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001511 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001512 }
1513
Alex Bennée50290c02019-05-29 17:16:32 +01001514 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
Max Reitz4c7b7e92015-02-05 13:58:22 -05001515 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1516 BLOCK_ACCT_READ);
Eric Blake7b3f9712016-05-06 10:26:44 -06001517 blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001518 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001519}
1520
1521static void aio_write_help(void)
1522{
1523 printf(
1524"\n"
1525" asynchronously writes a range of bytes from the given offset source\n"
1526" from multiple buffers\n"
1527"\n"
1528" Example:\n"
1529" 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1530"\n"
1531" Writes into a segment of the currently open file, using a buffer\n"
1532" filled with a set pattern (0xcdcdcdcd).\n"
1533" The write is performed asynchronously and the aio_flush command must be\n"
1534" used to ensure all outstanding aio requests have been completed.\n"
Max Reitzb32d7a32018-05-09 21:42:59 +02001535" Note that due to its asynchronous nature, this command will be\n"
1536" considered successful once the request is submitted, independently\n"
1537" of potential I/O errors or pattern mismatches.\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001538" -P, -- use different pattern to fill file\n"
1539" -C, -- report statistics in a machine parsable format\n"
Eric Blake770e0e02016-05-07 21:16:44 -06001540" -f, -- use Force Unit Access semantics\n"
Eric Blake37546ff2016-05-16 10:43:03 -06001541" -i, -- treat request as invalid, for exercising stats\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001542" -q, -- quiet mode, do not show I/O statistics\n"
Eric Blakec2e001c2016-05-07 21:16:45 -06001543" -u, -- with -z, allow unmapping\n"
Eric Blaked004bd52016-05-24 16:25:20 -06001544" -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
Kevin Wolf797ac582013-06-05 14:19:31 +02001545"\n");
1546}
1547
Max Reitzb32d7a32018-05-09 21:42:59 +02001548static int aio_write_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001549
1550static const cmdinfo_t aio_write_cmd = {
1551 .name = "aio_write",
1552 .cfunc = aio_write_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001553 .perm = BLK_PERM_WRITE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001554 .argmin = 2,
1555 .argmax = -1,
Eric Blake37546ff2016-05-16 10:43:03 -06001556 .args = "[-Cfiquz] [-P pattern] off len [len..]",
Kevin Wolf797ac582013-06-05 14:19:31 +02001557 .oneline = "asynchronously writes a number of bytes",
1558 .help = aio_write_help,
1559};
1560
Max Reitzb32d7a32018-05-09 21:42:59 +02001561static int aio_write_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001562{
1563 int nr_iov, c;
1564 int pattern = 0xcd;
1565 struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
Eric Blake770e0e02016-05-07 21:16:44 -06001566 int flags = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001567
Max Reitz4c7b7e92015-02-05 13:58:22 -05001568 ctx->blk = blk;
Eric Blake37546ff2016-05-16 10:43:03 -06001569 while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001570 switch (c) {
1571 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001572 ctx->Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001573 break;
Eric Blake770e0e02016-05-07 21:16:44 -06001574 case 'f':
1575 flags |= BDRV_REQ_FUA;
1576 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001577 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001578 ctx->qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001579 break;
Eric Blakec2e001c2016-05-07 21:16:45 -06001580 case 'u':
1581 flags |= BDRV_REQ_MAY_UNMAP;
1582 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001583 case 'P':
1584 pattern = parse_pattern(optarg);
1585 if (pattern < 0) {
1586 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001587 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001588 }
1589 break;
Eric Blake37546ff2016-05-16 10:43:03 -06001590 case 'i':
1591 printf("injecting invalid write request\n");
1592 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1593 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001594 return 0;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001595 case 'z':
Eric Blakedc388522016-05-07 21:16:42 -06001596 ctx->zflag = true;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001597 break;
Kevin Wolf797ac582013-06-05 14:19:31 +02001598 default:
1599 g_free(ctx);
Max Reitzb444d0e2018-05-09 21:42:58 +02001600 qemuio_command_usage(&aio_write_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001601 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001602 }
1603 }
1604
1605 if (optind > argc - 2) {
1606 g_free(ctx);
Max Reitzb444d0e2018-05-09 21:42:58 +02001607 qemuio_command_usage(&aio_write_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001608 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001609 }
1610
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001611 if (ctx->zflag && optind != argc - 2) {
1612 printf("-z supports only a single length parameter\n");
1613 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001614 return -EINVAL;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001615 }
1616
Eric Blakec2e001c2016-05-07 21:16:45 -06001617 if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
1618 printf("-u requires -z to be specified\n");
Eric Blake4ca1d342016-05-16 10:43:01 -06001619 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001620 return -EINVAL;
Eric Blakec2e001c2016-05-07 21:16:45 -06001621 }
1622
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001623 if (ctx->zflag && ctx->Pflag) {
1624 printf("-z and -P cannot be specified at the same time\n");
1625 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001626 return -EINVAL;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001627 }
1628
Kevin Wolf797ac582013-06-05 14:19:31 +02001629 ctx->offset = cvtnum(argv[optind]);
1630 if (ctx->offset < 0) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001631 int ret = ctx->offset;
1632 print_cvtnum_err(ret, argv[optind]);
Kevin Wolf797ac582013-06-05 14:19:31 +02001633 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001634 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001635 }
1636 optind++;
1637
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001638 if (ctx->zflag) {
1639 int64_t count = cvtnum(argv[optind]);
1640 if (count < 0) {
1641 print_cvtnum_err(count, argv[optind]);
Kevin Wolf0e01b762016-05-09 12:03:04 +02001642 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001643 return count;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001644 }
Kevin Wolf797ac582013-06-05 14:19:31 +02001645
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001646 ctx->qiov.size = count;
Eric Blaked004bd52016-05-24 16:25:20 -06001647 blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done,
1648 ctx);
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001649 } else {
1650 nr_iov = argc - optind;
1651 ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
1652 pattern);
1653 if (ctx->buf == NULL) {
1654 block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
1655 g_free(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02001656 return -EINVAL;
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001657 }
1658
Alex Bennée50290c02019-05-29 17:16:32 +01001659 clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001660 block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1661 BLOCK_ACCT_WRITE);
1662
Eric Blake770e0e02016-05-07 21:16:44 -06001663 blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
1664 ctx);
Kevin Wolf5ceb7762016-04-13 12:39:39 +02001665 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001666
1667 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001668}
1669
Max Reitzb32d7a32018-05-09 21:42:59 +02001670static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001671{
Alberto Garcia556c2b62015-10-28 17:33:08 +02001672 BlockAcctCookie cookie;
1673 block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
Max Reitz4c7b7e92015-02-05 13:58:22 -05001674 blk_drain_all();
Alberto Garcia556c2b62015-10-28 17:33:08 +02001675 block_acct_done(blk_get_stats(blk), &cookie);
Max Reitzb32d7a32018-05-09 21:42:59 +02001676 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001677}
1678
1679static const cmdinfo_t aio_flush_cmd = {
1680 .name = "aio_flush",
1681 .cfunc = aio_flush_f,
1682 .oneline = "completes all outstanding aio requests"
1683};
1684
Max Reitzb32d7a32018-05-09 21:42:59 +02001685static int flush_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001686{
Max Reitzb32d7a32018-05-09 21:42:59 +02001687 return blk_flush(blk);
Kevin Wolf797ac582013-06-05 14:19:31 +02001688}
1689
1690static const cmdinfo_t flush_cmd = {
1691 .name = "flush",
1692 .altname = "f",
1693 .cfunc = flush_f,
1694 .oneline = "flush all in-core file state to disk",
1695};
1696
Max Reitzb32d7a32018-05-09 21:42:59 +02001697static int truncate_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001698{
Max Reitzed3d2ec2017-03-28 22:51:27 +02001699 Error *local_err = NULL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001700 int64_t offset;
1701 int ret;
1702
1703 offset = cvtnum(argv[1]);
1704 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001705 print_cvtnum_err(offset, argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001706 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001707 }
1708
Max Reitz3a691c52017-06-13 22:20:54 +02001709 ret = blk_truncate(blk, offset, PREALLOC_MODE_OFF, &local_err);
Kevin Wolf797ac582013-06-05 14:19:31 +02001710 if (ret < 0) {
Max Reitzed3d2ec2017-03-28 22:51:27 +02001711 error_report_err(local_err);
Max Reitzb32d7a32018-05-09 21:42:59 +02001712 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001713 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001714
1715 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001716}
1717
1718static const cmdinfo_t truncate_cmd = {
1719 .name = "truncate",
1720 .altname = "t",
1721 .cfunc = truncate_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001722 .perm = BLK_PERM_WRITE | BLK_PERM_RESIZE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001723 .argmin = 1,
1724 .argmax = 1,
1725 .args = "off",
1726 .oneline = "truncates the current file at the given offset",
1727};
1728
Max Reitzb32d7a32018-05-09 21:42:59 +02001729static int length_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001730{
1731 int64_t size;
1732 char s1[64];
1733
Max Reitz4c7b7e92015-02-05 13:58:22 -05001734 size = blk_getlength(blk);
Kevin Wolf797ac582013-06-05 14:19:31 +02001735 if (size < 0) {
1736 printf("getlength: %s\n", strerror(-size));
Max Reitzb32d7a32018-05-09 21:42:59 +02001737 return size;
Kevin Wolf797ac582013-06-05 14:19:31 +02001738 }
1739
1740 cvtstr(size, s1, sizeof(s1));
1741 printf("%s\n", s1);
Max Reitzb32d7a32018-05-09 21:42:59 +02001742 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001743}
1744
1745
1746static const cmdinfo_t length_cmd = {
1747 .name = "length",
1748 .altname = "l",
1749 .cfunc = length_f,
1750 .oneline = "gets the length of the current file",
1751};
1752
1753
Max Reitzb32d7a32018-05-09 21:42:59 +02001754static int info_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001755{
Max Reitz4c7b7e92015-02-05 13:58:22 -05001756 BlockDriverState *bs = blk_bs(blk);
Kevin Wolf797ac582013-06-05 14:19:31 +02001757 BlockDriverInfo bdi;
Max Reitza8d8ecb2013-10-09 10:46:17 +02001758 ImageInfoSpecific *spec_info;
Andrey Shinkevich1bf6e9c2019-02-08 18:06:06 +03001759 Error *local_err = NULL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001760 char s1[64], s2[64];
1761 int ret;
1762
1763 if (bs->drv && bs->drv->format_name) {
1764 printf("format name: %s\n", bs->drv->format_name);
1765 }
1766 if (bs->drv && bs->drv->protocol_name) {
1767 printf("format name: %s\n", bs->drv->protocol_name);
1768 }
1769
1770 ret = bdrv_get_info(bs, &bdi);
1771 if (ret) {
Max Reitzb32d7a32018-05-09 21:42:59 +02001772 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001773 }
1774
1775 cvtstr(bdi.cluster_size, s1, sizeof(s1));
1776 cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1777
1778 printf("cluster size: %s\n", s1);
1779 printf("vm state offset: %s\n", s2);
1780
Andrey Shinkevich1bf6e9c2019-02-08 18:06:06 +03001781 spec_info = bdrv_get_specific_info(bs, &local_err);
1782 if (local_err) {
1783 error_report_err(local_err);
1784 return -EIO;
1785 }
Max Reitza8d8ecb2013-10-09 10:46:17 +02001786 if (spec_info) {
1787 printf("Format specific information:\n");
Markus Armbrustere1ce7d72019-04-17 21:17:55 +02001788 bdrv_image_info_specific_dump(spec_info);
Max Reitza8d8ecb2013-10-09 10:46:17 +02001789 qapi_free_ImageInfoSpecific(spec_info);
1790 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001791
1792 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001793}
1794
1795
1796
1797static const cmdinfo_t info_cmd = {
1798 .name = "info",
1799 .altname = "i",
1800 .cfunc = info_f,
1801 .oneline = "prints information about the current file",
1802};
1803
1804static void discard_help(void)
1805{
1806 printf(
1807"\n"
1808" discards a range of bytes from the given offset\n"
1809"\n"
1810" Example:\n"
1811" 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1812"\n"
1813" Discards a segment of the currently open file.\n"
1814" -C, -- report statistics in a machine parsable format\n"
1815" -q, -- quiet mode, do not show I/O statistics\n"
1816"\n");
1817}
1818
Max Reitzb32d7a32018-05-09 21:42:59 +02001819static int discard_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf797ac582013-06-05 14:19:31 +02001820
1821static const cmdinfo_t discard_cmd = {
1822 .name = "discard",
1823 .altname = "d",
1824 .cfunc = discard_f,
Kevin Wolf887354b2017-02-10 16:24:56 +01001825 .perm = BLK_PERM_WRITE,
Kevin Wolf797ac582013-06-05 14:19:31 +02001826 .argmin = 2,
1827 .argmax = -1,
1828 .args = "[-Cq] off len",
1829 .oneline = "discards a number of bytes at a specified offset",
1830 .help = discard_help,
1831};
1832
Max Reitzb32d7a32018-05-09 21:42:59 +02001833static int discard_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001834{
Alex Bennée50290c02019-05-29 17:16:32 +01001835 struct timespec t1, t2;
Eric Blakedc388522016-05-07 21:16:42 -06001836 bool Cflag = false, qflag = false;
Kevin Wolf797ac582013-06-05 14:19:31 +02001837 int c, ret;
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +03001838 int64_t offset, bytes;
Kevin Wolf797ac582013-06-05 14:19:31 +02001839
Eric Blakeb062ad82015-05-12 09:10:56 -06001840 while ((c = getopt(argc, argv, "Cq")) != -1) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001841 switch (c) {
1842 case 'C':
Eric Blakedc388522016-05-07 21:16:42 -06001843 Cflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001844 break;
1845 case 'q':
Eric Blakedc388522016-05-07 21:16:42 -06001846 qflag = true;
Kevin Wolf797ac582013-06-05 14:19:31 +02001847 break;
1848 default:
Max Reitzb444d0e2018-05-09 21:42:58 +02001849 qemuio_command_usage(&discard_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001850 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001851 }
1852 }
1853
1854 if (optind != argc - 2) {
Max Reitzb444d0e2018-05-09 21:42:58 +02001855 qemuio_command_usage(&discard_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02001856 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001857 }
1858
1859 offset = cvtnum(argv[optind]);
1860 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001861 print_cvtnum_err(offset, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001862 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001863 }
1864
1865 optind++;
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +03001866 bytes = cvtnum(argv[optind]);
1867 if (bytes < 0) {
1868 print_cvtnum_err(bytes, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001869 return bytes;
Alberto Garcia41ae31e2019-05-14 16:57:35 +03001870 } else if (bytes > BDRV_REQUEST_MAX_BYTES) {
John Snow9b0beaf2015-11-05 18:53:02 -05001871 printf("length cannot exceed %"PRIu64", given %s\n",
Alberto Garcia41ae31e2019-05-14 16:57:35 +03001872 (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001873 return -EINVAL;
Kevin Wolf797ac582013-06-05 14:19:31 +02001874 }
1875
Alex Bennée50290c02019-05-29 17:16:32 +01001876 clock_gettime(CLOCK_MONOTONIC, &t1);
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +03001877 ret = blk_pdiscard(blk, offset, bytes);
Alex Bennée50290c02019-05-29 17:16:32 +01001878 clock_gettime(CLOCK_MONOTONIC, &t2);
Kevin Wolf797ac582013-06-05 14:19:31 +02001879
1880 if (ret < 0) {
1881 printf("discard failed: %s\n", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02001882 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02001883 }
1884
1885 /* Finally, report back -- -C gives a parsable format */
1886 if (!qflag) {
1887 t2 = tsub(t2, t1);
Manos Pitsidianakisf5a5ca72017-06-09 13:18:08 +03001888 print_report("discard", &t2, offset, bytes, bytes, 1, Cflag);
Kevin Wolf797ac582013-06-05 14:19:31 +02001889 }
Max Reitzb32d7a32018-05-09 21:42:59 +02001890
1891 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001892}
1893
Max Reitzb32d7a32018-05-09 21:42:59 +02001894static int alloc_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001895{
Max Reitz4c7b7e92015-02-05 13:58:22 -05001896 BlockDriverState *bs = blk_bs(blk);
Eric Blaked6a644b2017-07-07 07:44:57 -05001897 int64_t offset, start, remaining, count;
Kevin Wolf797ac582013-06-05 14:19:31 +02001898 char s1[64];
Eric Blaked6a644b2017-07-07 07:44:57 -05001899 int ret;
1900 int64_t num, sum_alloc;
Kevin Wolf797ac582013-06-05 14:19:31 +02001901
Eric Blaked6a644b2017-07-07 07:44:57 -05001902 start = offset = cvtnum(argv[1]);
Kevin Wolf797ac582013-06-05 14:19:31 +02001903 if (offset < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05001904 print_cvtnum_err(offset, argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001905 return offset;
Kevin Wolf797ac582013-06-05 14:19:31 +02001906 }
1907
1908 if (argc == 3) {
Eric Blake4401fdc2017-04-29 14:14:12 -05001909 count = cvtnum(argv[2]);
1910 if (count < 0) {
1911 print_cvtnum_err(count, argv[2]);
Max Reitzb32d7a32018-05-09 21:42:59 +02001912 return count;
Kevin Wolf797ac582013-06-05 14:19:31 +02001913 }
1914 } else {
Eric Blake4401fdc2017-04-29 14:14:12 -05001915 count = BDRV_SECTOR_SIZE;
Kevin Wolf797ac582013-06-05 14:19:31 +02001916 }
1917
Eric Blaked6a644b2017-07-07 07:44:57 -05001918 remaining = count;
Kevin Wolf797ac582013-06-05 14:19:31 +02001919 sum_alloc = 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001920 while (remaining) {
Eric Blaked6a644b2017-07-07 07:44:57 -05001921 ret = bdrv_is_allocated(bs, offset, remaining, &num);
Paolo Bonzinid6636402013-09-04 19:00:25 +02001922 if (ret < 0) {
1923 printf("is_allocated failed: %s\n", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02001924 return ret;
Paolo Bonzinid6636402013-09-04 19:00:25 +02001925 }
Eric Blaked6a644b2017-07-07 07:44:57 -05001926 offset += num;
Kevin Wolf797ac582013-06-05 14:19:31 +02001927 remaining -= num;
1928 if (ret) {
1929 sum_alloc += num;
1930 }
1931 if (num == 0) {
Eric Blaked6a644b2017-07-07 07:44:57 -05001932 count -= remaining;
Kevin Wolf797ac582013-06-05 14:19:31 +02001933 remaining = 0;
1934 }
1935 }
1936
Eric Blaked6a644b2017-07-07 07:44:57 -05001937 cvtstr(start, s1, sizeof(s1));
Kevin Wolf797ac582013-06-05 14:19:31 +02001938
Eric Blake4401fdc2017-04-29 14:14:12 -05001939 printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
Eric Blaked6a644b2017-07-07 07:44:57 -05001940 sum_alloc, count, s1);
Max Reitzb32d7a32018-05-09 21:42:59 +02001941 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02001942}
1943
1944static const cmdinfo_t alloc_cmd = {
1945 .name = "alloc",
1946 .altname = "a",
1947 .argmin = 1,
1948 .argmax = 2,
1949 .cfunc = alloc_f,
Eric Blake4401fdc2017-04-29 14:14:12 -05001950 .args = "offset [count]",
1951 .oneline = "checks if offset is allocated in the file",
Kevin Wolf797ac582013-06-05 14:19:31 +02001952};
1953
1954
Eric Blaked6a644b2017-07-07 07:44:57 -05001955static int map_is_allocated(BlockDriverState *bs, int64_t offset,
1956 int64_t bytes, int64_t *pnum)
Kevin Wolf797ac582013-06-05 14:19:31 +02001957{
Eric Blaked6a644b2017-07-07 07:44:57 -05001958 int64_t num;
1959 int num_checked;
Kevin Wolf797ac582013-06-05 14:19:31 +02001960 int ret, firstret;
1961
Eric Blaked6a644b2017-07-07 07:44:57 -05001962 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1963 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
Kevin Wolf797ac582013-06-05 14:19:31 +02001964 if (ret < 0) {
1965 return ret;
1966 }
1967
1968 firstret = ret;
1969 *pnum = num;
1970
Eric Blaked6a644b2017-07-07 07:44:57 -05001971 while (bytes > 0 && ret == firstret) {
1972 offset += num;
1973 bytes -= num;
Kevin Wolf797ac582013-06-05 14:19:31 +02001974
Eric Blaked6a644b2017-07-07 07:44:57 -05001975 num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
1976 ret = bdrv_is_allocated(bs, offset, num_checked, &num);
Max Reitz4b25bbc2014-10-22 17:00:16 +02001977 if (ret == firstret && num) {
Kevin Wolf797ac582013-06-05 14:19:31 +02001978 *pnum += num;
1979 } else {
1980 break;
1981 }
1982 }
1983
1984 return firstret;
1985}
1986
Max Reitzb32d7a32018-05-09 21:42:59 +02001987static int map_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02001988{
Eric Blaked6a644b2017-07-07 07:44:57 -05001989 int64_t offset, bytes;
Eric Blake6f3c90a2017-04-29 14:14:13 -05001990 char s1[64], s2[64];
Kevin Wolf797ac582013-06-05 14:19:31 +02001991 int64_t num;
1992 int ret;
1993 const char *retstr;
1994
1995 offset = 0;
Eric Blaked6a644b2017-07-07 07:44:57 -05001996 bytes = blk_getlength(blk);
1997 if (bytes < 0) {
1998 error_report("Failed to query image length: %s", strerror(-bytes));
Max Reitzb32d7a32018-05-09 21:42:59 +02001999 return bytes;
Max Reitz4c7b7e92015-02-05 13:58:22 -05002000 }
2001
Eric Blaked6a644b2017-07-07 07:44:57 -05002002 while (bytes) {
2003 ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
Kevin Wolf797ac582013-06-05 14:19:31 +02002004 if (ret < 0) {
2005 error_report("Failed to get allocation status: %s", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02002006 return ret;
Max Reitz4b25bbc2014-10-22 17:00:16 +02002007 } else if (!num) {
2008 error_report("Unexpected end of image");
Max Reitzb32d7a32018-05-09 21:42:59 +02002009 return -EIO;
Kevin Wolf797ac582013-06-05 14:19:31 +02002010 }
2011
2012 retstr = ret ? " allocated" : "not allocated";
Eric Blaked6a644b2017-07-07 07:44:57 -05002013 cvtstr(num, s1, sizeof(s1));
2014 cvtstr(offset, s2, sizeof(s2));
Eric Blake6f3c90a2017-04-29 14:14:13 -05002015 printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
Eric Blaked6a644b2017-07-07 07:44:57 -05002016 s1, num, retstr, s2, offset);
Kevin Wolf797ac582013-06-05 14:19:31 +02002017
2018 offset += num;
Eric Blaked6a644b2017-07-07 07:44:57 -05002019 bytes -= num;
2020 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002021
2022 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02002023}
2024
2025static const cmdinfo_t map_cmd = {
2026 .name = "map",
2027 .argmin = 0,
2028 .argmax = 0,
2029 .cfunc = map_f,
2030 .args = "",
2031 .oneline = "prints the allocated areas of a file",
2032};
2033
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002034static void reopen_help(void)
2035{
2036 printf(
2037"\n"
2038" Changes the open options of an already opened image\n"
2039"\n"
2040" Example:\n"
2041" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2042"\n"
2043" -r, -- Reopen the image read-only\n"
Kevin Wolfea922032017-08-03 17:03:00 +02002044" -w, -- Reopen the image read-write\n"
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002045" -c, -- Change the cache mode to the given value\n"
2046" -o, -- Changes block driver options (cf. 'open' command)\n"
2047"\n");
2048}
2049
Max Reitzb32d7a32018-05-09 21:42:59 +02002050static int reopen_f(BlockBackend *blk, int argc, char **argv);
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002051
2052static QemuOptsList reopen_opts = {
2053 .name = "reopen",
2054 .merge_lists = true,
2055 .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2056 .desc = {
2057 /* no elements => accept any params */
2058 { /* end of list */ }
2059 },
2060};
2061
2062static const cmdinfo_t reopen_cmd = {
2063 .name = "reopen",
2064 .argmin = 0,
2065 .argmax = -1,
2066 .cfunc = reopen_f,
Kevin Wolfea922032017-08-03 17:03:00 +02002067 .args = "[(-r|-w)] [-c cache] [-o options]",
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002068 .oneline = "reopens an image with new options",
2069 .help = reopen_help,
2070};
2071
Max Reitzb32d7a32018-05-09 21:42:59 +02002072static int reopen_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002073{
2074 BlockDriverState *bs = blk_bs(blk);
2075 QemuOpts *qopts;
2076 QDict *opts;
2077 int c;
2078 int flags = bs->open_flags;
Kevin Wolf19dbecd2016-03-18 15:36:31 +01002079 bool writethrough = !blk_enable_write_cache(blk);
Kevin Wolfea922032017-08-03 17:03:00 +02002080 bool has_rw_option = false;
Alberto Garciadc900c32018-11-12 16:00:42 +02002081 bool has_cache_option = false;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002082
2083 BlockReopenQueue *brq;
2084 Error *local_err = NULL;
2085
Kevin Wolfea922032017-08-03 17:03:00 +02002086 while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002087 switch (c) {
2088 case 'c':
Kevin Wolf19dbecd2016-03-18 15:36:31 +01002089 if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002090 error_report("Invalid cache option: %s", optarg);
Max Reitzb32d7a32018-05-09 21:42:59 +02002091 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002092 }
Alberto Garciadc900c32018-11-12 16:00:42 +02002093 has_cache_option = true;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002094 break;
2095 case 'o':
2096 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2097 qemu_opts_reset(&reopen_opts);
Max Reitzb32d7a32018-05-09 21:42:59 +02002098 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002099 }
2100 break;
2101 case 'r':
Kevin Wolfea922032017-08-03 17:03:00 +02002102 if (has_rw_option) {
2103 error_report("Only one -r/-w option may be given");
Max Reitzb32d7a32018-05-09 21:42:59 +02002104 return -EINVAL;
Kevin Wolfea922032017-08-03 17:03:00 +02002105 }
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002106 flags &= ~BDRV_O_RDWR;
Kevin Wolfea922032017-08-03 17:03:00 +02002107 has_rw_option = true;
2108 break;
2109 case 'w':
2110 if (has_rw_option) {
2111 error_report("Only one -r/-w option may be given");
Max Reitzb32d7a32018-05-09 21:42:59 +02002112 return -EINVAL;
Kevin Wolfea922032017-08-03 17:03:00 +02002113 }
2114 flags |= BDRV_O_RDWR;
2115 has_rw_option = true;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002116 break;
2117 default:
2118 qemu_opts_reset(&reopen_opts);
Max Reitzb444d0e2018-05-09 21:42:58 +02002119 qemuio_command_usage(&reopen_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02002120 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002121 }
2122 }
2123
2124 if (optind != argc) {
2125 qemu_opts_reset(&reopen_opts);
Max Reitzb444d0e2018-05-09 21:42:58 +02002126 qemuio_command_usage(&reopen_cmd);
Max Reitzb32d7a32018-05-09 21:42:59 +02002127 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002128 }
2129
Alberto Garciaa8003ec2018-09-06 12:37:01 +03002130 if (!writethrough != blk_enable_write_cache(blk) &&
Kevin Wolf19dbecd2016-03-18 15:36:31 +01002131 blk_get_attached_dev(blk))
2132 {
2133 error_report("Cannot change cache.writeback: Device attached");
2134 qemu_opts_reset(&reopen_opts);
Max Reitzb32d7a32018-05-09 21:42:59 +02002135 return -EBUSY;
Kevin Wolf19dbecd2016-03-18 15:36:31 +01002136 }
2137
Kevin Wolff3adefb2017-09-22 14:50:12 +02002138 if (!(flags & BDRV_O_RDWR)) {
2139 uint64_t orig_perm, orig_shared_perm;
2140
2141 bdrv_drain(bs);
2142
2143 blk_get_perm(blk, &orig_perm, &orig_shared_perm);
2144 blk_set_perm(blk,
2145 orig_perm & ~(BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED),
2146 orig_shared_perm,
2147 &error_abort);
2148 }
2149
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002150 qopts = qemu_opts_find(&reopen_opts, NULL);
Alberto Garciadc900c32018-11-12 16:00:42 +02002151 opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002152 qemu_opts_reset(&reopen_opts);
2153
Alberto Garciadc900c32018-11-12 16:00:42 +02002154 if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
2155 if (has_rw_option) {
2156 error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
2157 qobject_unref(opts);
2158 return -EINVAL;
2159 }
2160 } else {
2161 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
2162 }
2163
2164 if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
2165 qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
2166 if (has_cache_option) {
2167 error_report("Cannot set both -c and the cache options");
2168 qobject_unref(opts);
2169 return -EINVAL;
2170 }
2171 } else {
2172 qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
2173 qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
2174 }
2175
Kevin Wolf1a63a902017-12-06 20:24:44 +01002176 bdrv_subtree_drained_begin(bs);
Alberto Garcia077e8e22019-03-12 18:48:44 +02002177 brq = bdrv_reopen_queue(NULL, bs, opts, true);
Alberto Garcia5019aec2019-03-12 18:48:50 +02002178 bdrv_reopen_multiple(brq, &local_err);
Kevin Wolf1a63a902017-12-06 20:24:44 +01002179 bdrv_subtree_drained_end(bs);
2180
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002181 if (local_err) {
2182 error_report_err(local_err);
Max Reitzb32d7a32018-05-09 21:42:59 +02002183 return -EINVAL;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002184 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002185
2186 blk_set_enable_write_cache(blk, !writethrough);
2187 return 0;
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002188}
2189
Max Reitzb32d7a32018-05-09 21:42:59 +02002190static int break_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02002191{
2192 int ret;
2193
Max Reitz4c7b7e92015-02-05 13:58:22 -05002194 ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
Kevin Wolf797ac582013-06-05 14:19:31 +02002195 if (ret < 0) {
2196 printf("Could not set breakpoint: %s\n", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02002197 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02002198 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002199
2200 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02002201}
2202
Max Reitzb32d7a32018-05-09 21:42:59 +02002203static int remove_break_f(BlockBackend *blk, int argc, char **argv)
Fam Zheng4cc70e92013-11-20 10:01:54 +08002204{
2205 int ret;
2206
Max Reitz4c7b7e92015-02-05 13:58:22 -05002207 ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
Fam Zheng4cc70e92013-11-20 10:01:54 +08002208 if (ret < 0) {
2209 printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02002210 return ret;
Fam Zheng4cc70e92013-11-20 10:01:54 +08002211 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002212
2213 return 0;
Fam Zheng4cc70e92013-11-20 10:01:54 +08002214}
2215
Kevin Wolf797ac582013-06-05 14:19:31 +02002216static const cmdinfo_t break_cmd = {
2217 .name = "break",
2218 .argmin = 2,
2219 .argmax = 2,
2220 .cfunc = break_f,
2221 .args = "event tag",
2222 .oneline = "sets a breakpoint on event and tags the stopped "
2223 "request as tag",
2224};
2225
Fam Zheng4cc70e92013-11-20 10:01:54 +08002226static const cmdinfo_t remove_break_cmd = {
2227 .name = "remove_break",
2228 .argmin = 1,
2229 .argmax = 1,
2230 .cfunc = remove_break_f,
2231 .args = "tag",
2232 .oneline = "remove a breakpoint by tag",
2233};
2234
Max Reitzb32d7a32018-05-09 21:42:59 +02002235static int resume_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02002236{
2237 int ret;
2238
Max Reitz4c7b7e92015-02-05 13:58:22 -05002239 ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
Kevin Wolf797ac582013-06-05 14:19:31 +02002240 if (ret < 0) {
2241 printf("Could not resume request: %s\n", strerror(-ret));
Max Reitzb32d7a32018-05-09 21:42:59 +02002242 return ret;
Kevin Wolf797ac582013-06-05 14:19:31 +02002243 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002244
2245 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02002246}
2247
2248static const cmdinfo_t resume_cmd = {
2249 .name = "resume",
2250 .argmin = 1,
2251 .argmax = 1,
2252 .cfunc = resume_f,
2253 .args = "tag",
2254 .oneline = "resumes the request tagged as tag",
2255};
2256
Max Reitzb32d7a32018-05-09 21:42:59 +02002257static int wait_break_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02002258{
Max Reitz4c7b7e92015-02-05 13:58:22 -05002259 while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2260 aio_poll(blk_get_aio_context(blk), true);
Kevin Wolf797ac582013-06-05 14:19:31 +02002261 }
Max Reitzb32d7a32018-05-09 21:42:59 +02002262 return 0;
Kevin Wolf797ac582013-06-05 14:19:31 +02002263}
2264
2265static const cmdinfo_t wait_break_cmd = {
2266 .name = "wait_break",
2267 .argmin = 1,
2268 .argmax = 1,
2269 .cfunc = wait_break_f,
2270 .args = "tag",
2271 .oneline = "waits for the suspension of a request",
2272};
2273
Max Reitzb32d7a32018-05-09 21:42:59 +02002274static int abort_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolf797ac582013-06-05 14:19:31 +02002275{
2276 abort();
2277}
2278
2279static const cmdinfo_t abort_cmd = {
2280 .name = "abort",
2281 .cfunc = abort_f,
2282 .flags = CMD_NOFILE_OK,
2283 .oneline = "simulate a program crash using abort(3)",
2284};
2285
Max Reitz0e82dc72014-12-08 10:48:10 +01002286static void sigraise_help(void)
2287{
2288 printf(
2289"\n"
2290" raises the given signal\n"
2291"\n"
2292" Example:\n"
2293" 'sigraise %i' - raises SIGTERM\n"
2294"\n"
2295" Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2296" given to sigraise.\n"
2297"\n", SIGTERM);
2298}
2299
Max Reitzb32d7a32018-05-09 21:42:59 +02002300static int sigraise_f(BlockBackend *blk, int argc, char **argv);
Max Reitz0e82dc72014-12-08 10:48:10 +01002301
2302static const cmdinfo_t sigraise_cmd = {
2303 .name = "sigraise",
2304 .cfunc = sigraise_f,
2305 .argmin = 1,
2306 .argmax = 1,
2307 .flags = CMD_NOFILE_OK,
2308 .args = "signal",
2309 .oneline = "raises a signal",
2310 .help = sigraise_help,
2311};
2312
Max Reitzb32d7a32018-05-09 21:42:59 +02002313static int sigraise_f(BlockBackend *blk, int argc, char **argv)
Max Reitz0e82dc72014-12-08 10:48:10 +01002314{
John Snow9b0beaf2015-11-05 18:53:02 -05002315 int64_t sig = cvtnum(argv[1]);
Max Reitz0e82dc72014-12-08 10:48:10 +01002316 if (sig < 0) {
John Snowa9ecfa02015-11-05 18:53:04 -05002317 print_cvtnum_err(sig, argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002318 return sig;
John Snow9b0beaf2015-11-05 18:53:02 -05002319 } else if (sig > NSIG) {
2320 printf("signal argument '%s' is too large to be a valid signal\n",
2321 argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002322 return -EINVAL;
Max Reitz0e82dc72014-12-08 10:48:10 +01002323 }
2324
2325 /* Using raise() to kill this process does not necessarily flush all open
2326 * streams. At least stdout and stderr (although the latter should be
2327 * non-buffered anyway) should be flushed, though. */
2328 fflush(stdout);
2329 fflush(stderr);
2330
2331 raise(sig);
Max Reitzb32d7a32018-05-09 21:42:59 +02002332
2333 return 0;
Max Reitz0e82dc72014-12-08 10:48:10 +01002334}
2335
Kevin Wolfcd33d022014-01-15 15:39:10 +01002336static void sleep_cb(void *opaque)
2337{
2338 bool *expired = opaque;
2339 *expired = true;
2340}
2341
Max Reitzb32d7a32018-05-09 21:42:59 +02002342static int sleep_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolfcd33d022014-01-15 15:39:10 +01002343{
2344 char *endptr;
2345 long ms;
2346 struct QEMUTimer *timer;
2347 bool expired = false;
2348
2349 ms = strtol(argv[1], &endptr, 0);
2350 if (ms < 0 || *endptr != '\0') {
2351 printf("%s is not a valid number\n", argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002352 return -EINVAL;
Kevin Wolfcd33d022014-01-15 15:39:10 +01002353 }
2354
2355 timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2356 timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2357
2358 while (!expired) {
2359 main_loop_wait(false);
2360 }
2361
2362 timer_free(timer);
Max Reitzb32d7a32018-05-09 21:42:59 +02002363 return 0;
Kevin Wolfcd33d022014-01-15 15:39:10 +01002364}
2365
2366static const cmdinfo_t sleep_cmd = {
2367 .name = "sleep",
2368 .argmin = 1,
2369 .argmax = 1,
2370 .cfunc = sleep_f,
2371 .flags = CMD_NOFILE_OK,
2372 .oneline = "waits for the given value in milliseconds",
2373};
2374
Kevin Wolff18a8342013-06-05 14:19:33 +02002375static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2376{
2377 if (cmd) {
2378 printf("%s ", cmd);
2379 } else {
2380 printf("%s ", ct->name);
2381 if (ct->altname) {
2382 printf("(or %s) ", ct->altname);
2383 }
2384 }
2385
2386 if (ct->args) {
2387 printf("%s ", ct->args);
2388 }
2389 printf("-- %s\n", ct->oneline);
2390}
2391
2392static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2393{
2394 help_oneline(cmd, ct);
2395 if (ct->help) {
2396 ct->help();
2397 }
2398}
2399
2400static void help_all(void)
2401{
2402 const cmdinfo_t *ct;
2403
2404 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2405 help_oneline(ct->name, ct);
2406 }
2407 printf("\nUse 'help commandname' for extended help.\n");
2408}
2409
Max Reitzb32d7a32018-05-09 21:42:59 +02002410static int help_f(BlockBackend *blk, int argc, char **argv)
Kevin Wolff18a8342013-06-05 14:19:33 +02002411{
2412 const cmdinfo_t *ct;
2413
2414 if (argc == 1) {
2415 help_all();
Max Reitzb32d7a32018-05-09 21:42:59 +02002416 return 0;
Kevin Wolff18a8342013-06-05 14:19:33 +02002417 }
2418
2419 ct = find_command(argv[1]);
2420 if (ct == NULL) {
2421 printf("command %s not found\n", argv[1]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002422 return -EINVAL;
Kevin Wolff18a8342013-06-05 14:19:33 +02002423 }
2424
2425 help_onecmd(argv[1], ct);
Max Reitzb32d7a32018-05-09 21:42:59 +02002426 return 0;
Kevin Wolff18a8342013-06-05 14:19:33 +02002427}
2428
2429static const cmdinfo_t help_cmd = {
2430 .name = "help",
2431 .altname = "?",
2432 .cfunc = help_f,
2433 .argmin = 0,
2434 .argmax = 1,
2435 .flags = CMD_FLAG_GLOBAL,
2436 .args = "[command]",
2437 .oneline = "help for one or all commands",
2438};
2439
Max Reitzb32d7a32018-05-09 21:42:59 +02002440int qemuio_command(BlockBackend *blk, const char *cmd)
Kevin Wolfdd583292013-06-05 14:19:32 +02002441{
Paolo Bonzini15afd942016-10-27 12:49:03 +02002442 AioContext *ctx;
Kevin Wolfdd583292013-06-05 14:19:32 +02002443 char *input;
2444 const cmdinfo_t *ct;
2445 char **v;
2446 int c;
Max Reitzb32d7a32018-05-09 21:42:59 +02002447 int ret = 0;
Kevin Wolfdd583292013-06-05 14:19:32 +02002448
2449 input = g_strdup(cmd);
2450 v = breakline(input, &c);
2451 if (c) {
2452 ct = find_command(v[0]);
2453 if (ct) {
Paolo Bonzini15afd942016-10-27 12:49:03 +02002454 ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context();
2455 aio_context_acquire(ctx);
Max Reitzb32d7a32018-05-09 21:42:59 +02002456 ret = command(blk, ct, c, v);
Paolo Bonzini15afd942016-10-27 12:49:03 +02002457 aio_context_release(ctx);
Kevin Wolfdd583292013-06-05 14:19:32 +02002458 } else {
2459 fprintf(stderr, "command \"%s\" not found\n", v[0]);
Max Reitzb32d7a32018-05-09 21:42:59 +02002460 ret = -EINVAL;
Kevin Wolfdd583292013-06-05 14:19:32 +02002461 }
2462 }
2463 g_free(input);
2464 g_free(v);
Max Reitzb32d7a32018-05-09 21:42:59 +02002465
2466 return ret;
Kevin Wolfdd583292013-06-05 14:19:32 +02002467}
2468
Kevin Wolf797ac582013-06-05 14:19:31 +02002469static void __attribute((constructor)) init_qemuio_commands(void)
2470{
2471 /* initialize commands */
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +02002472 qemuio_add_command(&help_cmd);
2473 qemuio_add_command(&read_cmd);
2474 qemuio_add_command(&readv_cmd);
2475 qemuio_add_command(&write_cmd);
2476 qemuio_add_command(&writev_cmd);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +02002477 qemuio_add_command(&aio_read_cmd);
2478 qemuio_add_command(&aio_write_cmd);
2479 qemuio_add_command(&aio_flush_cmd);
2480 qemuio_add_command(&flush_cmd);
2481 qemuio_add_command(&truncate_cmd);
2482 qemuio_add_command(&length_cmd);
2483 qemuio_add_command(&info_cmd);
2484 qemuio_add_command(&discard_cmd);
2485 qemuio_add_command(&alloc_cmd);
2486 qemuio_add_command(&map_cmd);
Kevin Wolf5bbd2e52014-12-08 17:37:28 +01002487 qemuio_add_command(&reopen_cmd);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +02002488 qemuio_add_command(&break_cmd);
Fam Zheng4cc70e92013-11-20 10:01:54 +08002489 qemuio_add_command(&remove_break_cmd);
Kevin Wolfc2cdf5c2013-06-05 14:19:36 +02002490 qemuio_add_command(&resume_cmd);
2491 qemuio_add_command(&wait_break_cmd);
2492 qemuio_add_command(&abort_cmd);
Kevin Wolfcd33d022014-01-15 15:39:10 +01002493 qemuio_add_command(&sleep_cmd);
Max Reitz0e82dc72014-12-08 10:48:10 +01002494 qemuio_add_command(&sigraise_cmd);
Kevin Wolf797ac582013-06-05 14:19:31 +02002495}