xref: /qemu/qemu-io-cmds.c (revision 797ac58c)
1*797ac58cSKevin Wolf /*
2*797ac58cSKevin Wolf  * Command line utility to exercise the QEMU I/O path.
3*797ac58cSKevin Wolf  *
4*797ac58cSKevin Wolf  * Copyright (C) 2009 Red Hat, Inc.
5*797ac58cSKevin Wolf  * Copyright (c) 2003-2005 Silicon Graphics, Inc.
6*797ac58cSKevin Wolf  *
7*797ac58cSKevin Wolf  * This work is licensed under the terms of the GNU GPL, version 2 or later.
8*797ac58cSKevin Wolf  * See the COPYING file in the top-level directory.
9*797ac58cSKevin Wolf  */
10*797ac58cSKevin Wolf 
11*797ac58cSKevin Wolf #include "qemu-common.h"
12*797ac58cSKevin Wolf #include "block/block_int.h"
13*797ac58cSKevin Wolf #include "cmd.h"
14*797ac58cSKevin Wolf 
15*797ac58cSKevin Wolf #define CMD_NOFILE_OK   0x01
16*797ac58cSKevin Wolf 
17*797ac58cSKevin Wolf int qemuio_misalign;
18*797ac58cSKevin Wolf 
19*797ac58cSKevin Wolf static int64_t cvtnum(const char *s)
20*797ac58cSKevin Wolf {
21*797ac58cSKevin Wolf     char *end;
22*797ac58cSKevin Wolf     return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B);
23*797ac58cSKevin Wolf }
24*797ac58cSKevin Wolf 
25*797ac58cSKevin Wolf /*
26*797ac58cSKevin Wolf  * Parse the pattern argument to various sub-commands.
27*797ac58cSKevin Wolf  *
28*797ac58cSKevin Wolf  * Because the pattern is used as an argument to memset it must evaluate
29*797ac58cSKevin Wolf  * to an unsigned integer that fits into a single byte.
30*797ac58cSKevin Wolf  */
31*797ac58cSKevin Wolf static int parse_pattern(const char *arg)
32*797ac58cSKevin Wolf {
33*797ac58cSKevin Wolf     char *endptr = NULL;
34*797ac58cSKevin Wolf     long pattern;
35*797ac58cSKevin Wolf 
36*797ac58cSKevin Wolf     pattern = strtol(arg, &endptr, 0);
37*797ac58cSKevin Wolf     if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
38*797ac58cSKevin Wolf         printf("%s is not a valid pattern byte\n", arg);
39*797ac58cSKevin Wolf         return -1;
40*797ac58cSKevin Wolf     }
41*797ac58cSKevin Wolf 
42*797ac58cSKevin Wolf     return pattern;
43*797ac58cSKevin Wolf }
44*797ac58cSKevin Wolf 
45*797ac58cSKevin Wolf /*
46*797ac58cSKevin Wolf  * Memory allocation helpers.
47*797ac58cSKevin Wolf  *
48*797ac58cSKevin Wolf  * Make sure memory is aligned by default, or purposefully misaligned if
49*797ac58cSKevin Wolf  * that is specified on the command line.
50*797ac58cSKevin Wolf  */
51*797ac58cSKevin Wolf 
52*797ac58cSKevin Wolf #define MISALIGN_OFFSET     16
53*797ac58cSKevin Wolf static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern)
54*797ac58cSKevin Wolf {
55*797ac58cSKevin Wolf     void *buf;
56*797ac58cSKevin Wolf 
57*797ac58cSKevin Wolf     if (qemuio_misalign) {
58*797ac58cSKevin Wolf         len += MISALIGN_OFFSET;
59*797ac58cSKevin Wolf     }
60*797ac58cSKevin Wolf     buf = qemu_blockalign(bs, len);
61*797ac58cSKevin Wolf     memset(buf, pattern, len);
62*797ac58cSKevin Wolf     if (qemuio_misalign) {
63*797ac58cSKevin Wolf         buf += MISALIGN_OFFSET;
64*797ac58cSKevin Wolf     }
65*797ac58cSKevin Wolf     return buf;
66*797ac58cSKevin Wolf }
67*797ac58cSKevin Wolf 
68*797ac58cSKevin Wolf static void qemu_io_free(void *p)
69*797ac58cSKevin Wolf {
70*797ac58cSKevin Wolf     if (qemuio_misalign) {
71*797ac58cSKevin Wolf         p -= MISALIGN_OFFSET;
72*797ac58cSKevin Wolf     }
73*797ac58cSKevin Wolf     qemu_vfree(p);
74*797ac58cSKevin Wolf }
75*797ac58cSKevin Wolf 
76*797ac58cSKevin Wolf static void dump_buffer(const void *buffer, int64_t offset, int len)
77*797ac58cSKevin Wolf {
78*797ac58cSKevin Wolf     int i, j;
79*797ac58cSKevin Wolf     const uint8_t *p;
80*797ac58cSKevin Wolf 
81*797ac58cSKevin Wolf     for (i = 0, p = buffer; i < len; i += 16) {
82*797ac58cSKevin Wolf         const uint8_t *s = p;
83*797ac58cSKevin Wolf 
84*797ac58cSKevin Wolf         printf("%08" PRIx64 ":  ", offset + i);
85*797ac58cSKevin Wolf         for (j = 0; j < 16 && i + j < len; j++, p++) {
86*797ac58cSKevin Wolf             printf("%02x ", *p);
87*797ac58cSKevin Wolf         }
88*797ac58cSKevin Wolf         printf(" ");
89*797ac58cSKevin Wolf         for (j = 0; j < 16 && i + j < len; j++, s++) {
90*797ac58cSKevin Wolf             if (isalnum(*s)) {
91*797ac58cSKevin Wolf                 printf("%c", *s);
92*797ac58cSKevin Wolf             } else {
93*797ac58cSKevin Wolf                 printf(".");
94*797ac58cSKevin Wolf             }
95*797ac58cSKevin Wolf         }
96*797ac58cSKevin Wolf         printf("\n");
97*797ac58cSKevin Wolf     }
98*797ac58cSKevin Wolf }
99*797ac58cSKevin Wolf 
100*797ac58cSKevin Wolf static void print_report(const char *op, struct timeval *t, int64_t offset,
101*797ac58cSKevin Wolf                          int count, int total, int cnt, int Cflag)
102*797ac58cSKevin Wolf {
103*797ac58cSKevin Wolf     char s1[64], s2[64], ts[64];
104*797ac58cSKevin Wolf 
105*797ac58cSKevin Wolf     timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
106*797ac58cSKevin Wolf     if (!Cflag) {
107*797ac58cSKevin Wolf         cvtstr((double)total, s1, sizeof(s1));
108*797ac58cSKevin Wolf         cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
109*797ac58cSKevin Wolf         printf("%s %d/%d bytes at offset %" PRId64 "\n",
110*797ac58cSKevin Wolf                op, total, count, offset);
111*797ac58cSKevin Wolf         printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
112*797ac58cSKevin Wolf                s1, cnt, ts, s2, tdiv((double)cnt, *t));
113*797ac58cSKevin Wolf     } else {/* bytes,ops,time,bytes/sec,ops/sec */
114*797ac58cSKevin Wolf         printf("%d,%d,%s,%.3f,%.3f\n",
115*797ac58cSKevin Wolf             total, cnt, ts,
116*797ac58cSKevin Wolf             tdiv((double)total, *t),
117*797ac58cSKevin Wolf             tdiv((double)cnt, *t));
118*797ac58cSKevin Wolf     }
119*797ac58cSKevin Wolf }
120*797ac58cSKevin Wolf 
121*797ac58cSKevin Wolf /*
122*797ac58cSKevin Wolf  * Parse multiple length statements for vectored I/O, and construct an I/O
123*797ac58cSKevin Wolf  * vector matching it.
124*797ac58cSKevin Wolf  */
125*797ac58cSKevin Wolf static void *
126*797ac58cSKevin Wolf create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
127*797ac58cSKevin Wolf              int pattern)
128*797ac58cSKevin Wolf {
129*797ac58cSKevin Wolf     size_t *sizes = g_new0(size_t, nr_iov);
130*797ac58cSKevin Wolf     size_t count = 0;
131*797ac58cSKevin Wolf     void *buf = NULL;
132*797ac58cSKevin Wolf     void *p;
133*797ac58cSKevin Wolf     int i;
134*797ac58cSKevin Wolf 
135*797ac58cSKevin Wolf     for (i = 0; i < nr_iov; i++) {
136*797ac58cSKevin Wolf         char *arg = argv[i];
137*797ac58cSKevin Wolf         int64_t len;
138*797ac58cSKevin Wolf 
139*797ac58cSKevin Wolf         len = cvtnum(arg);
140*797ac58cSKevin Wolf         if (len < 0) {
141*797ac58cSKevin Wolf             printf("non-numeric length argument -- %s\n", arg);
142*797ac58cSKevin Wolf             goto fail;
143*797ac58cSKevin Wolf         }
144*797ac58cSKevin Wolf 
145*797ac58cSKevin Wolf         /* should be SIZE_T_MAX, but that doesn't exist */
146*797ac58cSKevin Wolf         if (len > INT_MAX) {
147*797ac58cSKevin Wolf             printf("too large length argument -- %s\n", arg);
148*797ac58cSKevin Wolf             goto fail;
149*797ac58cSKevin Wolf         }
150*797ac58cSKevin Wolf 
151*797ac58cSKevin Wolf         if (len & 0x1ff) {
152*797ac58cSKevin Wolf             printf("length argument %" PRId64
153*797ac58cSKevin Wolf                    " is not sector aligned\n", len);
154*797ac58cSKevin Wolf             goto fail;
155*797ac58cSKevin Wolf         }
156*797ac58cSKevin Wolf 
157*797ac58cSKevin Wolf         sizes[i] = len;
158*797ac58cSKevin Wolf         count += len;
159*797ac58cSKevin Wolf     }
160*797ac58cSKevin Wolf 
161*797ac58cSKevin Wolf     qemu_iovec_init(qiov, nr_iov);
162*797ac58cSKevin Wolf 
163*797ac58cSKevin Wolf     buf = p = qemu_io_alloc(bs, count, pattern);
164*797ac58cSKevin Wolf 
165*797ac58cSKevin Wolf     for (i = 0; i < nr_iov; i++) {
166*797ac58cSKevin Wolf         qemu_iovec_add(qiov, p, sizes[i]);
167*797ac58cSKevin Wolf         p += sizes[i];
168*797ac58cSKevin Wolf     }
169*797ac58cSKevin Wolf 
170*797ac58cSKevin Wolf fail:
171*797ac58cSKevin Wolf     g_free(sizes);
172*797ac58cSKevin Wolf     return buf;
173*797ac58cSKevin Wolf }
174*797ac58cSKevin Wolf 
175*797ac58cSKevin Wolf static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count,
176*797ac58cSKevin Wolf                    int *total)
177*797ac58cSKevin Wolf {
178*797ac58cSKevin Wolf     int ret;
179*797ac58cSKevin Wolf 
180*797ac58cSKevin Wolf     ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
181*797ac58cSKevin Wolf     if (ret < 0) {
182*797ac58cSKevin Wolf         return ret;
183*797ac58cSKevin Wolf     }
184*797ac58cSKevin Wolf     *total = count;
185*797ac58cSKevin Wolf     return 1;
186*797ac58cSKevin Wolf }
187*797ac58cSKevin Wolf 
188*797ac58cSKevin Wolf static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count,
189*797ac58cSKevin Wolf                     int *total)
190*797ac58cSKevin Wolf {
191*797ac58cSKevin Wolf     int ret;
192*797ac58cSKevin Wolf 
193*797ac58cSKevin Wolf     ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
194*797ac58cSKevin Wolf     if (ret < 0) {
195*797ac58cSKevin Wolf         return ret;
196*797ac58cSKevin Wolf     }
197*797ac58cSKevin Wolf     *total = count;
198*797ac58cSKevin Wolf     return 1;
199*797ac58cSKevin Wolf }
200*797ac58cSKevin Wolf 
201*797ac58cSKevin Wolf static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count,
202*797ac58cSKevin Wolf                     int *total)
203*797ac58cSKevin Wolf {
204*797ac58cSKevin Wolf     *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
205*797ac58cSKevin Wolf     if (*total < 0) {
206*797ac58cSKevin Wolf         return *total;
207*797ac58cSKevin Wolf     }
208*797ac58cSKevin Wolf     return 1;
209*797ac58cSKevin Wolf }
210*797ac58cSKevin Wolf 
211*797ac58cSKevin Wolf static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count,
212*797ac58cSKevin Wolf                      int *total)
213*797ac58cSKevin Wolf {
214*797ac58cSKevin Wolf     *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
215*797ac58cSKevin Wolf     if (*total < 0) {
216*797ac58cSKevin Wolf         return *total;
217*797ac58cSKevin Wolf     }
218*797ac58cSKevin Wolf     return 1;
219*797ac58cSKevin Wolf }
220*797ac58cSKevin Wolf 
221*797ac58cSKevin Wolf typedef struct {
222*797ac58cSKevin Wolf     BlockDriverState *bs;
223*797ac58cSKevin Wolf     int64_t offset;
224*797ac58cSKevin Wolf     int count;
225*797ac58cSKevin Wolf     int *total;
226*797ac58cSKevin Wolf     int ret;
227*797ac58cSKevin Wolf     bool done;
228*797ac58cSKevin Wolf } CoWriteZeroes;
229*797ac58cSKevin Wolf 
230*797ac58cSKevin Wolf static void coroutine_fn co_write_zeroes_entry(void *opaque)
231*797ac58cSKevin Wolf {
232*797ac58cSKevin Wolf     CoWriteZeroes *data = opaque;
233*797ac58cSKevin Wolf 
234*797ac58cSKevin Wolf     data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE,
235*797ac58cSKevin Wolf                                      data->count / BDRV_SECTOR_SIZE);
236*797ac58cSKevin Wolf     data->done = true;
237*797ac58cSKevin Wolf     if (data->ret < 0) {
238*797ac58cSKevin Wolf         *data->total = data->ret;
239*797ac58cSKevin Wolf         return;
240*797ac58cSKevin Wolf     }
241*797ac58cSKevin Wolf 
242*797ac58cSKevin Wolf     *data->total = data->count;
243*797ac58cSKevin Wolf }
244*797ac58cSKevin Wolf 
245*797ac58cSKevin Wolf static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
246*797ac58cSKevin Wolf                               int *total)
247*797ac58cSKevin Wolf {
248*797ac58cSKevin Wolf     Coroutine *co;
249*797ac58cSKevin Wolf     CoWriteZeroes data = {
250*797ac58cSKevin Wolf         .bs     = bs,
251*797ac58cSKevin Wolf         .offset = offset,
252*797ac58cSKevin Wolf         .count  = count,
253*797ac58cSKevin Wolf         .total  = total,
254*797ac58cSKevin Wolf         .done   = false,
255*797ac58cSKevin Wolf     };
256*797ac58cSKevin Wolf 
257*797ac58cSKevin Wolf     co = qemu_coroutine_create(co_write_zeroes_entry);
258*797ac58cSKevin Wolf     qemu_coroutine_enter(co, &data);
259*797ac58cSKevin Wolf     while (!data.done) {
260*797ac58cSKevin Wolf         qemu_aio_wait();
261*797ac58cSKevin Wolf     }
262*797ac58cSKevin Wolf     if (data.ret < 0) {
263*797ac58cSKevin Wolf         return data.ret;
264*797ac58cSKevin Wolf     } else {
265*797ac58cSKevin Wolf         return 1;
266*797ac58cSKevin Wolf     }
267*797ac58cSKevin Wolf }
268*797ac58cSKevin Wolf 
269*797ac58cSKevin Wolf static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset,
270*797ac58cSKevin Wolf                                int count, int *total)
271*797ac58cSKevin Wolf {
272*797ac58cSKevin Wolf     int ret;
273*797ac58cSKevin Wolf 
274*797ac58cSKevin Wolf     ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9);
275*797ac58cSKevin Wolf     if (ret < 0) {
276*797ac58cSKevin Wolf         return ret;
277*797ac58cSKevin Wolf     }
278*797ac58cSKevin Wolf     *total = count;
279*797ac58cSKevin Wolf     return 1;
280*797ac58cSKevin Wolf }
281*797ac58cSKevin Wolf 
282*797ac58cSKevin Wolf static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
283*797ac58cSKevin Wolf                            int count, int *total)
284*797ac58cSKevin Wolf {
285*797ac58cSKevin Wolf     *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
286*797ac58cSKevin Wolf     if (*total < 0) {
287*797ac58cSKevin Wolf         return *total;
288*797ac58cSKevin Wolf     }
289*797ac58cSKevin Wolf     return 1;
290*797ac58cSKevin Wolf }
291*797ac58cSKevin Wolf 
292*797ac58cSKevin Wolf static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset,
293*797ac58cSKevin Wolf                            int count, int *total)
294*797ac58cSKevin Wolf {
295*797ac58cSKevin Wolf     *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
296*797ac58cSKevin Wolf     if (*total < 0) {
297*797ac58cSKevin Wolf         return *total;
298*797ac58cSKevin Wolf     }
299*797ac58cSKevin Wolf     return 1;
300*797ac58cSKevin Wolf }
301*797ac58cSKevin Wolf 
302*797ac58cSKevin Wolf #define NOT_DONE 0x7fffffff
303*797ac58cSKevin Wolf static void aio_rw_done(void *opaque, int ret)
304*797ac58cSKevin Wolf {
305*797ac58cSKevin Wolf     *(int *)opaque = ret;
306*797ac58cSKevin Wolf }
307*797ac58cSKevin Wolf 
308*797ac58cSKevin Wolf static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov,
309*797ac58cSKevin Wolf                         int64_t offset, int *total)
310*797ac58cSKevin Wolf {
311*797ac58cSKevin Wolf     int async_ret = NOT_DONE;
312*797ac58cSKevin Wolf 
313*797ac58cSKevin Wolf     bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
314*797ac58cSKevin Wolf                    aio_rw_done, &async_ret);
315*797ac58cSKevin Wolf     while (async_ret == NOT_DONE) {
316*797ac58cSKevin Wolf         main_loop_wait(false);
317*797ac58cSKevin Wolf     }
318*797ac58cSKevin Wolf 
319*797ac58cSKevin Wolf     *total = qiov->size;
320*797ac58cSKevin Wolf     return async_ret < 0 ? async_ret : 1;
321*797ac58cSKevin Wolf }
322*797ac58cSKevin Wolf 
323*797ac58cSKevin Wolf static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov,
324*797ac58cSKevin Wolf                          int64_t offset, int *total)
325*797ac58cSKevin Wolf {
326*797ac58cSKevin Wolf     int async_ret = NOT_DONE;
327*797ac58cSKevin Wolf 
328*797ac58cSKevin Wolf     bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
329*797ac58cSKevin Wolf                     aio_rw_done, &async_ret);
330*797ac58cSKevin Wolf     while (async_ret == NOT_DONE) {
331*797ac58cSKevin Wolf         main_loop_wait(false);
332*797ac58cSKevin Wolf     }
333*797ac58cSKevin Wolf 
334*797ac58cSKevin Wolf     *total = qiov->size;
335*797ac58cSKevin Wolf     return async_ret < 0 ? async_ret : 1;
336*797ac58cSKevin Wolf }
337*797ac58cSKevin Wolf 
338*797ac58cSKevin Wolf struct multiwrite_async_ret {
339*797ac58cSKevin Wolf     int num_done;
340*797ac58cSKevin Wolf     int error;
341*797ac58cSKevin Wolf };
342*797ac58cSKevin Wolf 
343*797ac58cSKevin Wolf static void multiwrite_cb(void *opaque, int ret)
344*797ac58cSKevin Wolf {
345*797ac58cSKevin Wolf     struct multiwrite_async_ret *async_ret = opaque;
346*797ac58cSKevin Wolf 
347*797ac58cSKevin Wolf     async_ret->num_done++;
348*797ac58cSKevin Wolf     if (ret < 0) {
349*797ac58cSKevin Wolf         async_ret->error = ret;
350*797ac58cSKevin Wolf     }
351*797ac58cSKevin Wolf }
352*797ac58cSKevin Wolf 
353*797ac58cSKevin Wolf static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs,
354*797ac58cSKevin Wolf                              int num_reqs, int *total)
355*797ac58cSKevin Wolf {
356*797ac58cSKevin Wolf     int i, ret;
357*797ac58cSKevin Wolf     struct multiwrite_async_ret async_ret = {
358*797ac58cSKevin Wolf         .num_done = 0,
359*797ac58cSKevin Wolf         .error = 0,
360*797ac58cSKevin Wolf     };
361*797ac58cSKevin Wolf 
362*797ac58cSKevin Wolf     *total = 0;
363*797ac58cSKevin Wolf     for (i = 0; i < num_reqs; i++) {
364*797ac58cSKevin Wolf         reqs[i].cb = multiwrite_cb;
365*797ac58cSKevin Wolf         reqs[i].opaque = &async_ret;
366*797ac58cSKevin Wolf         *total += reqs[i].qiov->size;
367*797ac58cSKevin Wolf     }
368*797ac58cSKevin Wolf 
369*797ac58cSKevin Wolf     ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
370*797ac58cSKevin Wolf     if (ret < 0) {
371*797ac58cSKevin Wolf         return ret;
372*797ac58cSKevin Wolf     }
373*797ac58cSKevin Wolf 
374*797ac58cSKevin Wolf     while (async_ret.num_done < num_reqs) {
375*797ac58cSKevin Wolf         main_loop_wait(false);
376*797ac58cSKevin Wolf     }
377*797ac58cSKevin Wolf 
378*797ac58cSKevin Wolf     return async_ret.error < 0 ? async_ret.error : 1;
379*797ac58cSKevin Wolf }
380*797ac58cSKevin Wolf 
381*797ac58cSKevin Wolf static void read_help(void)
382*797ac58cSKevin Wolf {
383*797ac58cSKevin Wolf     printf(
384*797ac58cSKevin Wolf "\n"
385*797ac58cSKevin Wolf " reads a range of bytes from the given offset\n"
386*797ac58cSKevin Wolf "\n"
387*797ac58cSKevin Wolf " Example:\n"
388*797ac58cSKevin Wolf " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
389*797ac58cSKevin Wolf "\n"
390*797ac58cSKevin Wolf " Reads a segment of the currently open file, optionally dumping it to the\n"
391*797ac58cSKevin Wolf " standard output stream (with -v option) for subsequent inspection.\n"
392*797ac58cSKevin Wolf " -b, -- read from the VM state rather than the virtual disk\n"
393*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n"
394*797ac58cSKevin Wolf " -l, -- length for pattern verification (only with -P)\n"
395*797ac58cSKevin Wolf " -p, -- use bdrv_pread to read the file\n"
396*797ac58cSKevin Wolf " -P, -- use a pattern to verify read data\n"
397*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n"
398*797ac58cSKevin Wolf " -s, -- start offset for pattern verification (only with -P)\n"
399*797ac58cSKevin Wolf " -v, -- dump buffer to standard output\n"
400*797ac58cSKevin Wolf "\n");
401*797ac58cSKevin Wolf }
402*797ac58cSKevin Wolf 
403*797ac58cSKevin Wolf static int read_f(BlockDriverState *bs, int argc, char **argv);
404*797ac58cSKevin Wolf 
405*797ac58cSKevin Wolf static const cmdinfo_t read_cmd = {
406*797ac58cSKevin Wolf     .name       = "read",
407*797ac58cSKevin Wolf     .altname    = "r",
408*797ac58cSKevin Wolf     .cfunc      = read_f,
409*797ac58cSKevin Wolf     .argmin     = 2,
410*797ac58cSKevin Wolf     .argmax     = -1,
411*797ac58cSKevin Wolf     .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
412*797ac58cSKevin Wolf     .oneline    = "reads a number of bytes at a specified offset",
413*797ac58cSKevin Wolf     .help       = read_help,
414*797ac58cSKevin Wolf };
415*797ac58cSKevin Wolf 
416*797ac58cSKevin Wolf static int read_f(BlockDriverState *bs, int argc, char **argv)
417*797ac58cSKevin Wolf {
418*797ac58cSKevin Wolf     struct timeval t1, t2;
419*797ac58cSKevin Wolf     int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
420*797ac58cSKevin Wolf     int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
421*797ac58cSKevin Wolf     int c, cnt;
422*797ac58cSKevin Wolf     char *buf;
423*797ac58cSKevin Wolf     int64_t offset;
424*797ac58cSKevin Wolf     int count;
425*797ac58cSKevin Wolf     /* Some compilers get confused and warn if this is not initialized.  */
426*797ac58cSKevin Wolf     int total = 0;
427*797ac58cSKevin Wolf     int pattern = 0, pattern_offset = 0, pattern_count = 0;
428*797ac58cSKevin Wolf 
429*797ac58cSKevin Wolf     while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
430*797ac58cSKevin Wolf         switch (c) {
431*797ac58cSKevin Wolf         case 'b':
432*797ac58cSKevin Wolf             bflag = 1;
433*797ac58cSKevin Wolf             break;
434*797ac58cSKevin Wolf         case 'C':
435*797ac58cSKevin Wolf             Cflag = 1;
436*797ac58cSKevin Wolf             break;
437*797ac58cSKevin Wolf         case 'l':
438*797ac58cSKevin Wolf             lflag = 1;
439*797ac58cSKevin Wolf             pattern_count = cvtnum(optarg);
440*797ac58cSKevin Wolf             if (pattern_count < 0) {
441*797ac58cSKevin Wolf                 printf("non-numeric length argument -- %s\n", optarg);
442*797ac58cSKevin Wolf                 return 0;
443*797ac58cSKevin Wolf             }
444*797ac58cSKevin Wolf             break;
445*797ac58cSKevin Wolf         case 'p':
446*797ac58cSKevin Wolf             pflag = 1;
447*797ac58cSKevin Wolf             break;
448*797ac58cSKevin Wolf         case 'P':
449*797ac58cSKevin Wolf             Pflag = 1;
450*797ac58cSKevin Wolf             pattern = parse_pattern(optarg);
451*797ac58cSKevin Wolf             if (pattern < 0) {
452*797ac58cSKevin Wolf                 return 0;
453*797ac58cSKevin Wolf             }
454*797ac58cSKevin Wolf             break;
455*797ac58cSKevin Wolf         case 'q':
456*797ac58cSKevin Wolf             qflag = 1;
457*797ac58cSKevin Wolf             break;
458*797ac58cSKevin Wolf         case 's':
459*797ac58cSKevin Wolf             sflag = 1;
460*797ac58cSKevin Wolf             pattern_offset = cvtnum(optarg);
461*797ac58cSKevin Wolf             if (pattern_offset < 0) {
462*797ac58cSKevin Wolf                 printf("non-numeric length argument -- %s\n", optarg);
463*797ac58cSKevin Wolf                 return 0;
464*797ac58cSKevin Wolf             }
465*797ac58cSKevin Wolf             break;
466*797ac58cSKevin Wolf         case 'v':
467*797ac58cSKevin Wolf             vflag = 1;
468*797ac58cSKevin Wolf             break;
469*797ac58cSKevin Wolf         default:
470*797ac58cSKevin Wolf             return command_usage(&read_cmd);
471*797ac58cSKevin Wolf         }
472*797ac58cSKevin Wolf     }
473*797ac58cSKevin Wolf 
474*797ac58cSKevin Wolf     if (optind != argc - 2) {
475*797ac58cSKevin Wolf         return command_usage(&read_cmd);
476*797ac58cSKevin Wolf     }
477*797ac58cSKevin Wolf 
478*797ac58cSKevin Wolf     if (bflag && pflag) {
479*797ac58cSKevin Wolf         printf("-b and -p cannot be specified at the same time\n");
480*797ac58cSKevin Wolf         return 0;
481*797ac58cSKevin Wolf     }
482*797ac58cSKevin Wolf 
483*797ac58cSKevin Wolf     offset = cvtnum(argv[optind]);
484*797ac58cSKevin Wolf     if (offset < 0) {
485*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
486*797ac58cSKevin Wolf         return 0;
487*797ac58cSKevin Wolf     }
488*797ac58cSKevin Wolf 
489*797ac58cSKevin Wolf     optind++;
490*797ac58cSKevin Wolf     count = cvtnum(argv[optind]);
491*797ac58cSKevin Wolf     if (count < 0) {
492*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
493*797ac58cSKevin Wolf         return 0;
494*797ac58cSKevin Wolf     }
495*797ac58cSKevin Wolf 
496*797ac58cSKevin Wolf     if (!Pflag && (lflag || sflag)) {
497*797ac58cSKevin Wolf         return command_usage(&read_cmd);
498*797ac58cSKevin Wolf     }
499*797ac58cSKevin Wolf 
500*797ac58cSKevin Wolf     if (!lflag) {
501*797ac58cSKevin Wolf         pattern_count = count - pattern_offset;
502*797ac58cSKevin Wolf     }
503*797ac58cSKevin Wolf 
504*797ac58cSKevin Wolf     if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
505*797ac58cSKevin Wolf         printf("pattern verification range exceeds end of read data\n");
506*797ac58cSKevin Wolf         return 0;
507*797ac58cSKevin Wolf     }
508*797ac58cSKevin Wolf 
509*797ac58cSKevin Wolf     if (!pflag) {
510*797ac58cSKevin Wolf         if (offset & 0x1ff) {
511*797ac58cSKevin Wolf             printf("offset %" PRId64 " is not sector aligned\n",
512*797ac58cSKevin Wolf                    offset);
513*797ac58cSKevin Wolf             return 0;
514*797ac58cSKevin Wolf         }
515*797ac58cSKevin Wolf         if (count & 0x1ff) {
516*797ac58cSKevin Wolf             printf("count %d is not sector aligned\n",
517*797ac58cSKevin Wolf                    count);
518*797ac58cSKevin Wolf             return 0;
519*797ac58cSKevin Wolf         }
520*797ac58cSKevin Wolf     }
521*797ac58cSKevin Wolf 
522*797ac58cSKevin Wolf     buf = qemu_io_alloc(bs, count, 0xab);
523*797ac58cSKevin Wolf 
524*797ac58cSKevin Wolf     gettimeofday(&t1, NULL);
525*797ac58cSKevin Wolf     if (pflag) {
526*797ac58cSKevin Wolf         cnt = do_pread(bs, buf, offset, count, &total);
527*797ac58cSKevin Wolf     } else if (bflag) {
528*797ac58cSKevin Wolf         cnt = do_load_vmstate(bs, buf, offset, count, &total);
529*797ac58cSKevin Wolf     } else {
530*797ac58cSKevin Wolf         cnt = do_read(bs, buf, offset, count, &total);
531*797ac58cSKevin Wolf     }
532*797ac58cSKevin Wolf     gettimeofday(&t2, NULL);
533*797ac58cSKevin Wolf 
534*797ac58cSKevin Wolf     if (cnt < 0) {
535*797ac58cSKevin Wolf         printf("read failed: %s\n", strerror(-cnt));
536*797ac58cSKevin Wolf         goto out;
537*797ac58cSKevin Wolf     }
538*797ac58cSKevin Wolf 
539*797ac58cSKevin Wolf     if (Pflag) {
540*797ac58cSKevin Wolf         void *cmp_buf = g_malloc(pattern_count);
541*797ac58cSKevin Wolf         memset(cmp_buf, pattern, pattern_count);
542*797ac58cSKevin Wolf         if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
543*797ac58cSKevin Wolf             printf("Pattern verification failed at offset %"
544*797ac58cSKevin Wolf                    PRId64 ", %d bytes\n",
545*797ac58cSKevin Wolf                    offset + pattern_offset, pattern_count);
546*797ac58cSKevin Wolf         }
547*797ac58cSKevin Wolf         g_free(cmp_buf);
548*797ac58cSKevin Wolf     }
549*797ac58cSKevin Wolf 
550*797ac58cSKevin Wolf     if (qflag) {
551*797ac58cSKevin Wolf         goto out;
552*797ac58cSKevin Wolf     }
553*797ac58cSKevin Wolf 
554*797ac58cSKevin Wolf     if (vflag) {
555*797ac58cSKevin Wolf         dump_buffer(buf, offset, count);
556*797ac58cSKevin Wolf     }
557*797ac58cSKevin Wolf 
558*797ac58cSKevin Wolf     /* Finally, report back -- -C gives a parsable format */
559*797ac58cSKevin Wolf     t2 = tsub(t2, t1);
560*797ac58cSKevin Wolf     print_report("read", &t2, offset, count, total, cnt, Cflag);
561*797ac58cSKevin Wolf 
562*797ac58cSKevin Wolf out:
563*797ac58cSKevin Wolf     qemu_io_free(buf);
564*797ac58cSKevin Wolf 
565*797ac58cSKevin Wolf     return 0;
566*797ac58cSKevin Wolf }
567*797ac58cSKevin Wolf 
568*797ac58cSKevin Wolf static void readv_help(void)
569*797ac58cSKevin Wolf {
570*797ac58cSKevin Wolf     printf(
571*797ac58cSKevin Wolf "\n"
572*797ac58cSKevin Wolf " reads a range of bytes from the given offset into multiple buffers\n"
573*797ac58cSKevin Wolf "\n"
574*797ac58cSKevin Wolf " Example:\n"
575*797ac58cSKevin Wolf " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
576*797ac58cSKevin Wolf "\n"
577*797ac58cSKevin Wolf " Reads a segment of the currently open file, optionally dumping it to the\n"
578*797ac58cSKevin Wolf " standard output stream (with -v option) for subsequent inspection.\n"
579*797ac58cSKevin Wolf " Uses multiple iovec buffers if more than one byte range is specified.\n"
580*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n"
581*797ac58cSKevin Wolf " -P, -- use a pattern to verify read data\n"
582*797ac58cSKevin Wolf " -v, -- dump buffer to standard output\n"
583*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n"
584*797ac58cSKevin Wolf "\n");
585*797ac58cSKevin Wolf }
586*797ac58cSKevin Wolf 
587*797ac58cSKevin Wolf static int readv_f(BlockDriverState *bs, int argc, char **argv);
588*797ac58cSKevin Wolf 
589*797ac58cSKevin Wolf static const cmdinfo_t readv_cmd = {
590*797ac58cSKevin Wolf     .name       = "readv",
591*797ac58cSKevin Wolf     .cfunc      = readv_f,
592*797ac58cSKevin Wolf     .argmin     = 2,
593*797ac58cSKevin Wolf     .argmax     = -1,
594*797ac58cSKevin Wolf     .args       = "[-Cqv] [-P pattern ] off len [len..]",
595*797ac58cSKevin Wolf     .oneline    = "reads a number of bytes at a specified offset",
596*797ac58cSKevin Wolf     .help       = readv_help,
597*797ac58cSKevin Wolf };
598*797ac58cSKevin Wolf 
599*797ac58cSKevin Wolf static int readv_f(BlockDriverState *bs, int argc, char **argv)
600*797ac58cSKevin Wolf {
601*797ac58cSKevin Wolf     struct timeval t1, t2;
602*797ac58cSKevin Wolf     int Cflag = 0, qflag = 0, vflag = 0;
603*797ac58cSKevin Wolf     int c, cnt;
604*797ac58cSKevin Wolf     char *buf;
605*797ac58cSKevin Wolf     int64_t offset;
606*797ac58cSKevin Wolf     /* Some compilers get confused and warn if this is not initialized.  */
607*797ac58cSKevin Wolf     int total = 0;
608*797ac58cSKevin Wolf     int nr_iov;
609*797ac58cSKevin Wolf     QEMUIOVector qiov;
610*797ac58cSKevin Wolf     int pattern = 0;
611*797ac58cSKevin Wolf     int Pflag = 0;
612*797ac58cSKevin Wolf 
613*797ac58cSKevin Wolf     while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
614*797ac58cSKevin Wolf         switch (c) {
615*797ac58cSKevin Wolf         case 'C':
616*797ac58cSKevin Wolf             Cflag = 1;
617*797ac58cSKevin Wolf             break;
618*797ac58cSKevin Wolf         case 'P':
619*797ac58cSKevin Wolf             Pflag = 1;
620*797ac58cSKevin Wolf             pattern = parse_pattern(optarg);
621*797ac58cSKevin Wolf             if (pattern < 0) {
622*797ac58cSKevin Wolf                 return 0;
623*797ac58cSKevin Wolf             }
624*797ac58cSKevin Wolf             break;
625*797ac58cSKevin Wolf         case 'q':
626*797ac58cSKevin Wolf             qflag = 1;
627*797ac58cSKevin Wolf             break;
628*797ac58cSKevin Wolf         case 'v':
629*797ac58cSKevin Wolf             vflag = 1;
630*797ac58cSKevin Wolf             break;
631*797ac58cSKevin Wolf         default:
632*797ac58cSKevin Wolf             return command_usage(&readv_cmd);
633*797ac58cSKevin Wolf         }
634*797ac58cSKevin Wolf     }
635*797ac58cSKevin Wolf 
636*797ac58cSKevin Wolf     if (optind > argc - 2) {
637*797ac58cSKevin Wolf         return command_usage(&readv_cmd);
638*797ac58cSKevin Wolf     }
639*797ac58cSKevin Wolf 
640*797ac58cSKevin Wolf 
641*797ac58cSKevin Wolf     offset = cvtnum(argv[optind]);
642*797ac58cSKevin Wolf     if (offset < 0) {
643*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
644*797ac58cSKevin Wolf         return 0;
645*797ac58cSKevin Wolf     }
646*797ac58cSKevin Wolf     optind++;
647*797ac58cSKevin Wolf 
648*797ac58cSKevin Wolf     if (offset & 0x1ff) {
649*797ac58cSKevin Wolf         printf("offset %" PRId64 " is not sector aligned\n",
650*797ac58cSKevin Wolf                offset);
651*797ac58cSKevin Wolf         return 0;
652*797ac58cSKevin Wolf     }
653*797ac58cSKevin Wolf 
654*797ac58cSKevin Wolf     nr_iov = argc - optind;
655*797ac58cSKevin Wolf     buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab);
656*797ac58cSKevin Wolf     if (buf == NULL) {
657*797ac58cSKevin Wolf         return 0;
658*797ac58cSKevin Wolf     }
659*797ac58cSKevin Wolf 
660*797ac58cSKevin Wolf     gettimeofday(&t1, NULL);
661*797ac58cSKevin Wolf     cnt = do_aio_readv(bs, &qiov, offset, &total);
662*797ac58cSKevin Wolf     gettimeofday(&t2, NULL);
663*797ac58cSKevin Wolf 
664*797ac58cSKevin Wolf     if (cnt < 0) {
665*797ac58cSKevin Wolf         printf("readv failed: %s\n", strerror(-cnt));
666*797ac58cSKevin Wolf         goto out;
667*797ac58cSKevin Wolf     }
668*797ac58cSKevin Wolf 
669*797ac58cSKevin Wolf     if (Pflag) {
670*797ac58cSKevin Wolf         void *cmp_buf = g_malloc(qiov.size);
671*797ac58cSKevin Wolf         memset(cmp_buf, pattern, qiov.size);
672*797ac58cSKevin Wolf         if (memcmp(buf, cmp_buf, qiov.size)) {
673*797ac58cSKevin Wolf             printf("Pattern verification failed at offset %"
674*797ac58cSKevin Wolf                    PRId64 ", %zd bytes\n", offset, qiov.size);
675*797ac58cSKevin Wolf         }
676*797ac58cSKevin Wolf         g_free(cmp_buf);
677*797ac58cSKevin Wolf     }
678*797ac58cSKevin Wolf 
679*797ac58cSKevin Wolf     if (qflag) {
680*797ac58cSKevin Wolf         goto out;
681*797ac58cSKevin Wolf     }
682*797ac58cSKevin Wolf 
683*797ac58cSKevin Wolf     if (vflag) {
684*797ac58cSKevin Wolf         dump_buffer(buf, offset, qiov.size);
685*797ac58cSKevin Wolf     }
686*797ac58cSKevin Wolf 
687*797ac58cSKevin Wolf     /* Finally, report back -- -C gives a parsable format */
688*797ac58cSKevin Wolf     t2 = tsub(t2, t1);
689*797ac58cSKevin Wolf     print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
690*797ac58cSKevin Wolf 
691*797ac58cSKevin Wolf out:
692*797ac58cSKevin Wolf     qemu_iovec_destroy(&qiov);
693*797ac58cSKevin Wolf     qemu_io_free(buf);
694*797ac58cSKevin Wolf     return 0;
695*797ac58cSKevin Wolf }
696*797ac58cSKevin Wolf 
697*797ac58cSKevin Wolf static void write_help(void)
698*797ac58cSKevin Wolf {
699*797ac58cSKevin Wolf     printf(
700*797ac58cSKevin Wolf "\n"
701*797ac58cSKevin Wolf " writes a range of bytes from the given offset\n"
702*797ac58cSKevin Wolf "\n"
703*797ac58cSKevin Wolf " Example:\n"
704*797ac58cSKevin Wolf " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
705*797ac58cSKevin Wolf "\n"
706*797ac58cSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n"
707*797ac58cSKevin Wolf " filled with a set pattern (0xcdcdcdcd).\n"
708*797ac58cSKevin Wolf " -b, -- write to the VM state rather than the virtual disk\n"
709*797ac58cSKevin Wolf " -c, -- write compressed data with bdrv_write_compressed\n"
710*797ac58cSKevin Wolf " -p, -- use bdrv_pwrite to write the file\n"
711*797ac58cSKevin Wolf " -P, -- use different pattern to fill file\n"
712*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n"
713*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n"
714*797ac58cSKevin Wolf " -z, -- write zeroes using bdrv_co_write_zeroes\n"
715*797ac58cSKevin Wolf "\n");
716*797ac58cSKevin Wolf }
717*797ac58cSKevin Wolf 
718*797ac58cSKevin Wolf static int write_f(BlockDriverState *bs, int argc, char **argv);
719*797ac58cSKevin Wolf 
720*797ac58cSKevin Wolf static const cmdinfo_t write_cmd = {
721*797ac58cSKevin Wolf     .name       = "write",
722*797ac58cSKevin Wolf     .altname    = "w",
723*797ac58cSKevin Wolf     .cfunc      = write_f,
724*797ac58cSKevin Wolf     .argmin     = 2,
725*797ac58cSKevin Wolf     .argmax     = -1,
726*797ac58cSKevin Wolf     .args       = "[-bcCpqz] [-P pattern ] off len",
727*797ac58cSKevin Wolf     .oneline    = "writes a number of bytes at a specified offset",
728*797ac58cSKevin Wolf     .help       = write_help,
729*797ac58cSKevin Wolf };
730*797ac58cSKevin Wolf 
731*797ac58cSKevin Wolf static int write_f(BlockDriverState *bs, int argc, char **argv)
732*797ac58cSKevin Wolf {
733*797ac58cSKevin Wolf     struct timeval t1, t2;
734*797ac58cSKevin Wolf     int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
735*797ac58cSKevin Wolf     int cflag = 0;
736*797ac58cSKevin Wolf     int c, cnt;
737*797ac58cSKevin Wolf     char *buf = NULL;
738*797ac58cSKevin Wolf     int64_t offset;
739*797ac58cSKevin Wolf     int count;
740*797ac58cSKevin Wolf     /* Some compilers get confused and warn if this is not initialized.  */
741*797ac58cSKevin Wolf     int total = 0;
742*797ac58cSKevin Wolf     int pattern = 0xcd;
743*797ac58cSKevin Wolf 
744*797ac58cSKevin Wolf     while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
745*797ac58cSKevin Wolf         switch (c) {
746*797ac58cSKevin Wolf         case 'b':
747*797ac58cSKevin Wolf             bflag = 1;
748*797ac58cSKevin Wolf             break;
749*797ac58cSKevin Wolf         case 'c':
750*797ac58cSKevin Wolf             cflag = 1;
751*797ac58cSKevin Wolf             break;
752*797ac58cSKevin Wolf         case 'C':
753*797ac58cSKevin Wolf             Cflag = 1;
754*797ac58cSKevin Wolf             break;
755*797ac58cSKevin Wolf         case 'p':
756*797ac58cSKevin Wolf             pflag = 1;
757*797ac58cSKevin Wolf             break;
758*797ac58cSKevin Wolf         case 'P':
759*797ac58cSKevin Wolf             Pflag = 1;
760*797ac58cSKevin Wolf             pattern = parse_pattern(optarg);
761*797ac58cSKevin Wolf             if (pattern < 0) {
762*797ac58cSKevin Wolf                 return 0;
763*797ac58cSKevin Wolf             }
764*797ac58cSKevin Wolf             break;
765*797ac58cSKevin Wolf         case 'q':
766*797ac58cSKevin Wolf             qflag = 1;
767*797ac58cSKevin Wolf             break;
768*797ac58cSKevin Wolf         case 'z':
769*797ac58cSKevin Wolf             zflag = 1;
770*797ac58cSKevin Wolf             break;
771*797ac58cSKevin Wolf         default:
772*797ac58cSKevin Wolf             return command_usage(&write_cmd);
773*797ac58cSKevin Wolf         }
774*797ac58cSKevin Wolf     }
775*797ac58cSKevin Wolf 
776*797ac58cSKevin Wolf     if (optind != argc - 2) {
777*797ac58cSKevin Wolf         return command_usage(&write_cmd);
778*797ac58cSKevin Wolf     }
779*797ac58cSKevin Wolf 
780*797ac58cSKevin Wolf     if (bflag + pflag + zflag > 1) {
781*797ac58cSKevin Wolf         printf("-b, -p, or -z cannot be specified at the same time\n");
782*797ac58cSKevin Wolf         return 0;
783*797ac58cSKevin Wolf     }
784*797ac58cSKevin Wolf 
785*797ac58cSKevin Wolf     if (zflag && Pflag) {
786*797ac58cSKevin Wolf         printf("-z and -P cannot be specified at the same time\n");
787*797ac58cSKevin Wolf         return 0;
788*797ac58cSKevin Wolf     }
789*797ac58cSKevin Wolf 
790*797ac58cSKevin Wolf     offset = cvtnum(argv[optind]);
791*797ac58cSKevin Wolf     if (offset < 0) {
792*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
793*797ac58cSKevin Wolf         return 0;
794*797ac58cSKevin Wolf     }
795*797ac58cSKevin Wolf 
796*797ac58cSKevin Wolf     optind++;
797*797ac58cSKevin Wolf     count = cvtnum(argv[optind]);
798*797ac58cSKevin Wolf     if (count < 0) {
799*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
800*797ac58cSKevin Wolf         return 0;
801*797ac58cSKevin Wolf     }
802*797ac58cSKevin Wolf 
803*797ac58cSKevin Wolf     if (!pflag) {
804*797ac58cSKevin Wolf         if (offset & 0x1ff) {
805*797ac58cSKevin Wolf             printf("offset %" PRId64 " is not sector aligned\n",
806*797ac58cSKevin Wolf                    offset);
807*797ac58cSKevin Wolf             return 0;
808*797ac58cSKevin Wolf         }
809*797ac58cSKevin Wolf 
810*797ac58cSKevin Wolf         if (count & 0x1ff) {
811*797ac58cSKevin Wolf             printf("count %d is not sector aligned\n",
812*797ac58cSKevin Wolf                    count);
813*797ac58cSKevin Wolf             return 0;
814*797ac58cSKevin Wolf         }
815*797ac58cSKevin Wolf     }
816*797ac58cSKevin Wolf 
817*797ac58cSKevin Wolf     if (!zflag) {
818*797ac58cSKevin Wolf         buf = qemu_io_alloc(bs, count, pattern);
819*797ac58cSKevin Wolf     }
820*797ac58cSKevin Wolf 
821*797ac58cSKevin Wolf     gettimeofday(&t1, NULL);
822*797ac58cSKevin Wolf     if (pflag) {
823*797ac58cSKevin Wolf         cnt = do_pwrite(bs, buf, offset, count, &total);
824*797ac58cSKevin Wolf     } else if (bflag) {
825*797ac58cSKevin Wolf         cnt = do_save_vmstate(bs, buf, offset, count, &total);
826*797ac58cSKevin Wolf     } else if (zflag) {
827*797ac58cSKevin Wolf         cnt = do_co_write_zeroes(bs, offset, count, &total);
828*797ac58cSKevin Wolf     } else if (cflag) {
829*797ac58cSKevin Wolf         cnt = do_write_compressed(bs, buf, offset, count, &total);
830*797ac58cSKevin Wolf     } else {
831*797ac58cSKevin Wolf         cnt = do_write(bs, buf, offset, count, &total);
832*797ac58cSKevin Wolf     }
833*797ac58cSKevin Wolf     gettimeofday(&t2, NULL);
834*797ac58cSKevin Wolf 
835*797ac58cSKevin Wolf     if (cnt < 0) {
836*797ac58cSKevin Wolf         printf("write failed: %s\n", strerror(-cnt));
837*797ac58cSKevin Wolf         goto out;
838*797ac58cSKevin Wolf     }
839*797ac58cSKevin Wolf 
840*797ac58cSKevin Wolf     if (qflag) {
841*797ac58cSKevin Wolf         goto out;
842*797ac58cSKevin Wolf     }
843*797ac58cSKevin Wolf 
844*797ac58cSKevin Wolf     /* Finally, report back -- -C gives a parsable format */
845*797ac58cSKevin Wolf     t2 = tsub(t2, t1);
846*797ac58cSKevin Wolf     print_report("wrote", &t2, offset, count, total, cnt, Cflag);
847*797ac58cSKevin Wolf 
848*797ac58cSKevin Wolf out:
849*797ac58cSKevin Wolf     if (!zflag) {
850*797ac58cSKevin Wolf         qemu_io_free(buf);
851*797ac58cSKevin Wolf     }
852*797ac58cSKevin Wolf 
853*797ac58cSKevin Wolf     return 0;
854*797ac58cSKevin Wolf }
855*797ac58cSKevin Wolf 
856*797ac58cSKevin Wolf static void
857*797ac58cSKevin Wolf writev_help(void)
858*797ac58cSKevin Wolf {
859*797ac58cSKevin Wolf     printf(
860*797ac58cSKevin Wolf "\n"
861*797ac58cSKevin Wolf " writes a range of bytes from the given offset source from multiple buffers\n"
862*797ac58cSKevin Wolf "\n"
863*797ac58cSKevin Wolf " Example:\n"
864*797ac58cSKevin Wolf " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
865*797ac58cSKevin Wolf "\n"
866*797ac58cSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n"
867*797ac58cSKevin Wolf " filled with a set pattern (0xcdcdcdcd).\n"
868*797ac58cSKevin Wolf " -P, -- use different pattern to fill file\n"
869*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n"
870*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n"
871*797ac58cSKevin Wolf "\n");
872*797ac58cSKevin Wolf }
873*797ac58cSKevin Wolf 
874*797ac58cSKevin Wolf static int writev_f(BlockDriverState *bs, int argc, char **argv);
875*797ac58cSKevin Wolf 
876*797ac58cSKevin Wolf static const cmdinfo_t writev_cmd = {
877*797ac58cSKevin Wolf     .name       = "writev",
878*797ac58cSKevin Wolf     .cfunc      = writev_f,
879*797ac58cSKevin Wolf     .argmin     = 2,
880*797ac58cSKevin Wolf     .argmax     = -1,
881*797ac58cSKevin Wolf     .args       = "[-Cq] [-P pattern ] off len [len..]",
882*797ac58cSKevin Wolf     .oneline    = "writes a number of bytes at a specified offset",
883*797ac58cSKevin Wolf     .help       = writev_help,
884*797ac58cSKevin Wolf };
885*797ac58cSKevin Wolf 
886*797ac58cSKevin Wolf static int writev_f(BlockDriverState *bs, int argc, char **argv)
887*797ac58cSKevin Wolf {
888*797ac58cSKevin Wolf     struct timeval t1, t2;
889*797ac58cSKevin Wolf     int Cflag = 0, qflag = 0;
890*797ac58cSKevin Wolf     int c, cnt;
891*797ac58cSKevin Wolf     char *buf;
892*797ac58cSKevin Wolf     int64_t offset;
893*797ac58cSKevin Wolf     /* Some compilers get confused and warn if this is not initialized.  */
894*797ac58cSKevin Wolf     int total = 0;
895*797ac58cSKevin Wolf     int nr_iov;
896*797ac58cSKevin Wolf     int pattern = 0xcd;
897*797ac58cSKevin Wolf     QEMUIOVector qiov;
898*797ac58cSKevin Wolf 
899*797ac58cSKevin Wolf     while ((c = getopt(argc, argv, "CqP:")) != EOF) {
900*797ac58cSKevin Wolf         switch (c) {
901*797ac58cSKevin Wolf         case 'C':
902*797ac58cSKevin Wolf             Cflag = 1;
903*797ac58cSKevin Wolf             break;
904*797ac58cSKevin Wolf         case 'q':
905*797ac58cSKevin Wolf             qflag = 1;
906*797ac58cSKevin Wolf             break;
907*797ac58cSKevin Wolf         case 'P':
908*797ac58cSKevin Wolf             pattern = parse_pattern(optarg);
909*797ac58cSKevin Wolf             if (pattern < 0) {
910*797ac58cSKevin Wolf                 return 0;
911*797ac58cSKevin Wolf             }
912*797ac58cSKevin Wolf             break;
913*797ac58cSKevin Wolf         default:
914*797ac58cSKevin Wolf             return command_usage(&writev_cmd);
915*797ac58cSKevin Wolf         }
916*797ac58cSKevin Wolf     }
917*797ac58cSKevin Wolf 
918*797ac58cSKevin Wolf     if (optind > argc - 2) {
919*797ac58cSKevin Wolf         return command_usage(&writev_cmd);
920*797ac58cSKevin Wolf     }
921*797ac58cSKevin Wolf 
922*797ac58cSKevin Wolf     offset = cvtnum(argv[optind]);
923*797ac58cSKevin Wolf     if (offset < 0) {
924*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
925*797ac58cSKevin Wolf         return 0;
926*797ac58cSKevin Wolf     }
927*797ac58cSKevin Wolf     optind++;
928*797ac58cSKevin Wolf 
929*797ac58cSKevin Wolf     if (offset & 0x1ff) {
930*797ac58cSKevin Wolf         printf("offset %" PRId64 " is not sector aligned\n",
931*797ac58cSKevin Wolf                offset);
932*797ac58cSKevin Wolf         return 0;
933*797ac58cSKevin Wolf     }
934*797ac58cSKevin Wolf 
935*797ac58cSKevin Wolf     nr_iov = argc - optind;
936*797ac58cSKevin Wolf     buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern);
937*797ac58cSKevin Wolf     if (buf == NULL) {
938*797ac58cSKevin Wolf         return 0;
939*797ac58cSKevin Wolf     }
940*797ac58cSKevin Wolf 
941*797ac58cSKevin Wolf     gettimeofday(&t1, NULL);
942*797ac58cSKevin Wolf     cnt = do_aio_writev(bs, &qiov, offset, &total);
943*797ac58cSKevin Wolf     gettimeofday(&t2, NULL);
944*797ac58cSKevin Wolf 
945*797ac58cSKevin Wolf     if (cnt < 0) {
946*797ac58cSKevin Wolf         printf("writev failed: %s\n", strerror(-cnt));
947*797ac58cSKevin Wolf         goto out;
948*797ac58cSKevin Wolf     }
949*797ac58cSKevin Wolf 
950*797ac58cSKevin Wolf     if (qflag) {
951*797ac58cSKevin Wolf         goto out;
952*797ac58cSKevin Wolf     }
953*797ac58cSKevin Wolf 
954*797ac58cSKevin Wolf     /* Finally, report back -- -C gives a parsable format */
955*797ac58cSKevin Wolf     t2 = tsub(t2, t1);
956*797ac58cSKevin Wolf     print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
957*797ac58cSKevin Wolf out:
958*797ac58cSKevin Wolf     qemu_iovec_destroy(&qiov);
959*797ac58cSKevin Wolf     qemu_io_free(buf);
960*797ac58cSKevin Wolf     return 0;
961*797ac58cSKevin Wolf }
962*797ac58cSKevin Wolf 
963*797ac58cSKevin Wolf static void multiwrite_help(void)
964*797ac58cSKevin Wolf {
965*797ac58cSKevin Wolf     printf(
966*797ac58cSKevin Wolf "\n"
967*797ac58cSKevin Wolf " writes a range of bytes from the given offset source from multiple buffers,\n"
968*797ac58cSKevin Wolf " in a batch of requests that may be merged by qemu\n"
969*797ac58cSKevin Wolf "\n"
970*797ac58cSKevin Wolf " Example:\n"
971*797ac58cSKevin Wolf " 'multiwrite 512 1k 1k ; 4k 1k'\n"
972*797ac58cSKevin Wolf "  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
973*797ac58cSKevin Wolf "\n"
974*797ac58cSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n"
975*797ac58cSKevin Wolf " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
976*797ac58cSKevin Wolf " by one for each request contained in the multiwrite command.\n"
977*797ac58cSKevin Wolf " -P, -- use different pattern to fill file\n"
978*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n"
979*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n"
980*797ac58cSKevin Wolf "\n");
981*797ac58cSKevin Wolf }
982*797ac58cSKevin Wolf 
983*797ac58cSKevin Wolf static int multiwrite_f(BlockDriverState *bs, int argc, char **argv);
984*797ac58cSKevin Wolf 
985*797ac58cSKevin Wolf static const cmdinfo_t multiwrite_cmd = {
986*797ac58cSKevin Wolf     .name       = "multiwrite",
987*797ac58cSKevin Wolf     .cfunc      = multiwrite_f,
988*797ac58cSKevin Wolf     .argmin     = 2,
989*797ac58cSKevin Wolf     .argmax     = -1,
990*797ac58cSKevin Wolf     .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
991*797ac58cSKevin Wolf     .oneline    = "issues multiple write requests at once",
992*797ac58cSKevin Wolf     .help       = multiwrite_help,
993*797ac58cSKevin Wolf };
994*797ac58cSKevin Wolf 
995*797ac58cSKevin Wolf static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
996*797ac58cSKevin Wolf {
997*797ac58cSKevin Wolf     struct timeval t1, t2;
998*797ac58cSKevin Wolf     int Cflag = 0, qflag = 0;
999*797ac58cSKevin Wolf     int c, cnt;
1000*797ac58cSKevin Wolf     char **buf;
1001*797ac58cSKevin Wolf     int64_t offset, first_offset = 0;
1002*797ac58cSKevin Wolf     /* Some compilers get confused and warn if this is not initialized.  */
1003*797ac58cSKevin Wolf     int total = 0;
1004*797ac58cSKevin Wolf     int nr_iov;
1005*797ac58cSKevin Wolf     int nr_reqs;
1006*797ac58cSKevin Wolf     int pattern = 0xcd;
1007*797ac58cSKevin Wolf     QEMUIOVector *qiovs;
1008*797ac58cSKevin Wolf     int i;
1009*797ac58cSKevin Wolf     BlockRequest *reqs;
1010*797ac58cSKevin Wolf 
1011*797ac58cSKevin Wolf     while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1012*797ac58cSKevin Wolf         switch (c) {
1013*797ac58cSKevin Wolf         case 'C':
1014*797ac58cSKevin Wolf             Cflag = 1;
1015*797ac58cSKevin Wolf             break;
1016*797ac58cSKevin Wolf         case 'q':
1017*797ac58cSKevin Wolf             qflag = 1;
1018*797ac58cSKevin Wolf             break;
1019*797ac58cSKevin Wolf         case 'P':
1020*797ac58cSKevin Wolf             pattern = parse_pattern(optarg);
1021*797ac58cSKevin Wolf             if (pattern < 0) {
1022*797ac58cSKevin Wolf                 return 0;
1023*797ac58cSKevin Wolf             }
1024*797ac58cSKevin Wolf             break;
1025*797ac58cSKevin Wolf         default:
1026*797ac58cSKevin Wolf             return command_usage(&writev_cmd);
1027*797ac58cSKevin Wolf         }
1028*797ac58cSKevin Wolf     }
1029*797ac58cSKevin Wolf 
1030*797ac58cSKevin Wolf     if (optind > argc - 2) {
1031*797ac58cSKevin Wolf         return command_usage(&writev_cmd);
1032*797ac58cSKevin Wolf     }
1033*797ac58cSKevin Wolf 
1034*797ac58cSKevin Wolf     nr_reqs = 1;
1035*797ac58cSKevin Wolf     for (i = optind; i < argc; i++) {
1036*797ac58cSKevin Wolf         if (!strcmp(argv[i], ";")) {
1037*797ac58cSKevin Wolf             nr_reqs++;
1038*797ac58cSKevin Wolf         }
1039*797ac58cSKevin Wolf     }
1040*797ac58cSKevin Wolf 
1041*797ac58cSKevin Wolf     reqs = g_malloc0(nr_reqs * sizeof(*reqs));
1042*797ac58cSKevin Wolf     buf = g_malloc0(nr_reqs * sizeof(*buf));
1043*797ac58cSKevin Wolf     qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
1044*797ac58cSKevin Wolf 
1045*797ac58cSKevin Wolf     for (i = 0; i < nr_reqs && optind < argc; i++) {
1046*797ac58cSKevin Wolf         int j;
1047*797ac58cSKevin Wolf 
1048*797ac58cSKevin Wolf         /* Read the offset of the request */
1049*797ac58cSKevin Wolf         offset = cvtnum(argv[optind]);
1050*797ac58cSKevin Wolf         if (offset < 0) {
1051*797ac58cSKevin Wolf             printf("non-numeric offset argument -- %s\n", argv[optind]);
1052*797ac58cSKevin Wolf             goto out;
1053*797ac58cSKevin Wolf         }
1054*797ac58cSKevin Wolf         optind++;
1055*797ac58cSKevin Wolf 
1056*797ac58cSKevin Wolf         if (offset & 0x1ff) {
1057*797ac58cSKevin Wolf             printf("offset %lld is not sector aligned\n",
1058*797ac58cSKevin Wolf                    (long long)offset);
1059*797ac58cSKevin Wolf             goto out;
1060*797ac58cSKevin Wolf         }
1061*797ac58cSKevin Wolf 
1062*797ac58cSKevin Wolf         if (i == 0) {
1063*797ac58cSKevin Wolf             first_offset = offset;
1064*797ac58cSKevin Wolf         }
1065*797ac58cSKevin Wolf 
1066*797ac58cSKevin Wolf         /* Read lengths for qiov entries */
1067*797ac58cSKevin Wolf         for (j = optind; j < argc; j++) {
1068*797ac58cSKevin Wolf             if (!strcmp(argv[j], ";")) {
1069*797ac58cSKevin Wolf                 break;
1070*797ac58cSKevin Wolf             }
1071*797ac58cSKevin Wolf         }
1072*797ac58cSKevin Wolf 
1073*797ac58cSKevin Wolf         nr_iov = j - optind;
1074*797ac58cSKevin Wolf 
1075*797ac58cSKevin Wolf         /* Build request */
1076*797ac58cSKevin Wolf         buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern);
1077*797ac58cSKevin Wolf         if (buf[i] == NULL) {
1078*797ac58cSKevin Wolf             goto out;
1079*797ac58cSKevin Wolf         }
1080*797ac58cSKevin Wolf 
1081*797ac58cSKevin Wolf         reqs[i].qiov = &qiovs[i];
1082*797ac58cSKevin Wolf         reqs[i].sector = offset >> 9;
1083*797ac58cSKevin Wolf         reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1084*797ac58cSKevin Wolf 
1085*797ac58cSKevin Wolf         optind = j + 1;
1086*797ac58cSKevin Wolf 
1087*797ac58cSKevin Wolf         pattern++;
1088*797ac58cSKevin Wolf     }
1089*797ac58cSKevin Wolf 
1090*797ac58cSKevin Wolf     /* If there were empty requests at the end, ignore them */
1091*797ac58cSKevin Wolf     nr_reqs = i;
1092*797ac58cSKevin Wolf 
1093*797ac58cSKevin Wolf     gettimeofday(&t1, NULL);
1094*797ac58cSKevin Wolf     cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total);
1095*797ac58cSKevin Wolf     gettimeofday(&t2, NULL);
1096*797ac58cSKevin Wolf 
1097*797ac58cSKevin Wolf     if (cnt < 0) {
1098*797ac58cSKevin Wolf         printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1099*797ac58cSKevin Wolf         goto out;
1100*797ac58cSKevin Wolf     }
1101*797ac58cSKevin Wolf 
1102*797ac58cSKevin Wolf     if (qflag) {
1103*797ac58cSKevin Wolf         goto out;
1104*797ac58cSKevin Wolf     }
1105*797ac58cSKevin Wolf 
1106*797ac58cSKevin Wolf     /* Finally, report back -- -C gives a parsable format */
1107*797ac58cSKevin Wolf     t2 = tsub(t2, t1);
1108*797ac58cSKevin Wolf     print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1109*797ac58cSKevin Wolf out:
1110*797ac58cSKevin Wolf     for (i = 0; i < nr_reqs; i++) {
1111*797ac58cSKevin Wolf         qemu_io_free(buf[i]);
1112*797ac58cSKevin Wolf         if (reqs[i].qiov != NULL) {
1113*797ac58cSKevin Wolf             qemu_iovec_destroy(&qiovs[i]);
1114*797ac58cSKevin Wolf         }
1115*797ac58cSKevin Wolf     }
1116*797ac58cSKevin Wolf     g_free(buf);
1117*797ac58cSKevin Wolf     g_free(reqs);
1118*797ac58cSKevin Wolf     g_free(qiovs);
1119*797ac58cSKevin Wolf     return 0;
1120*797ac58cSKevin Wolf }
1121*797ac58cSKevin Wolf 
1122*797ac58cSKevin Wolf struct aio_ctx {
1123*797ac58cSKevin Wolf     QEMUIOVector qiov;
1124*797ac58cSKevin Wolf     int64_t offset;
1125*797ac58cSKevin Wolf     char *buf;
1126*797ac58cSKevin Wolf     int qflag;
1127*797ac58cSKevin Wolf     int vflag;
1128*797ac58cSKevin Wolf     int Cflag;
1129*797ac58cSKevin Wolf     int Pflag;
1130*797ac58cSKevin Wolf     int pattern;
1131*797ac58cSKevin Wolf     struct timeval t1;
1132*797ac58cSKevin Wolf };
1133*797ac58cSKevin Wolf 
1134*797ac58cSKevin Wolf static void aio_write_done(void *opaque, int ret)
1135*797ac58cSKevin Wolf {
1136*797ac58cSKevin Wolf     struct aio_ctx *ctx = opaque;
1137*797ac58cSKevin Wolf     struct timeval t2;
1138*797ac58cSKevin Wolf 
1139*797ac58cSKevin Wolf     gettimeofday(&t2, NULL);
1140*797ac58cSKevin Wolf 
1141*797ac58cSKevin Wolf 
1142*797ac58cSKevin Wolf     if (ret < 0) {
1143*797ac58cSKevin Wolf         printf("aio_write failed: %s\n", strerror(-ret));
1144*797ac58cSKevin Wolf         goto out;
1145*797ac58cSKevin Wolf     }
1146*797ac58cSKevin Wolf 
1147*797ac58cSKevin Wolf     if (ctx->qflag) {
1148*797ac58cSKevin Wolf         goto out;
1149*797ac58cSKevin Wolf     }
1150*797ac58cSKevin Wolf 
1151*797ac58cSKevin Wolf     /* Finally, report back -- -C gives a parsable format */
1152*797ac58cSKevin Wolf     t2 = tsub(t2, ctx->t1);
1153*797ac58cSKevin Wolf     print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1154*797ac58cSKevin Wolf                  ctx->qiov.size, 1, ctx->Cflag);
1155*797ac58cSKevin Wolf out:
1156*797ac58cSKevin Wolf     qemu_io_free(ctx->buf);
1157*797ac58cSKevin Wolf     qemu_iovec_destroy(&ctx->qiov);
1158*797ac58cSKevin Wolf     g_free(ctx);
1159*797ac58cSKevin Wolf }
1160*797ac58cSKevin Wolf 
1161*797ac58cSKevin Wolf static void aio_read_done(void *opaque, int ret)
1162*797ac58cSKevin Wolf {
1163*797ac58cSKevin Wolf     struct aio_ctx *ctx = opaque;
1164*797ac58cSKevin Wolf     struct timeval t2;
1165*797ac58cSKevin Wolf 
1166*797ac58cSKevin Wolf     gettimeofday(&t2, NULL);
1167*797ac58cSKevin Wolf 
1168*797ac58cSKevin Wolf     if (ret < 0) {
1169*797ac58cSKevin Wolf         printf("readv failed: %s\n", strerror(-ret));
1170*797ac58cSKevin Wolf         goto out;
1171*797ac58cSKevin Wolf     }
1172*797ac58cSKevin Wolf 
1173*797ac58cSKevin Wolf     if (ctx->Pflag) {
1174*797ac58cSKevin Wolf         void *cmp_buf = g_malloc(ctx->qiov.size);
1175*797ac58cSKevin Wolf 
1176*797ac58cSKevin Wolf         memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1177*797ac58cSKevin Wolf         if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1178*797ac58cSKevin Wolf             printf("Pattern verification failed at offset %"
1179*797ac58cSKevin Wolf                    PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1180*797ac58cSKevin Wolf         }
1181*797ac58cSKevin Wolf         g_free(cmp_buf);
1182*797ac58cSKevin Wolf     }
1183*797ac58cSKevin Wolf 
1184*797ac58cSKevin Wolf     if (ctx->qflag) {
1185*797ac58cSKevin Wolf         goto out;
1186*797ac58cSKevin Wolf     }
1187*797ac58cSKevin Wolf 
1188*797ac58cSKevin Wolf     if (ctx->vflag) {
1189*797ac58cSKevin Wolf         dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1190*797ac58cSKevin Wolf     }
1191*797ac58cSKevin Wolf 
1192*797ac58cSKevin Wolf     /* Finally, report back -- -C gives a parsable format */
1193*797ac58cSKevin Wolf     t2 = tsub(t2, ctx->t1);
1194*797ac58cSKevin Wolf     print_report("read", &t2, ctx->offset, ctx->qiov.size,
1195*797ac58cSKevin Wolf                  ctx->qiov.size, 1, ctx->Cflag);
1196*797ac58cSKevin Wolf out:
1197*797ac58cSKevin Wolf     qemu_io_free(ctx->buf);
1198*797ac58cSKevin Wolf     qemu_iovec_destroy(&ctx->qiov);
1199*797ac58cSKevin Wolf     g_free(ctx);
1200*797ac58cSKevin Wolf }
1201*797ac58cSKevin Wolf 
1202*797ac58cSKevin Wolf static void aio_read_help(void)
1203*797ac58cSKevin Wolf {
1204*797ac58cSKevin Wolf     printf(
1205*797ac58cSKevin Wolf "\n"
1206*797ac58cSKevin Wolf " asynchronously reads a range of bytes from the given offset\n"
1207*797ac58cSKevin Wolf "\n"
1208*797ac58cSKevin Wolf " Example:\n"
1209*797ac58cSKevin Wolf " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1210*797ac58cSKevin Wolf "\n"
1211*797ac58cSKevin Wolf " Reads a segment of the currently open file, optionally dumping it to the\n"
1212*797ac58cSKevin Wolf " standard output stream (with -v option) for subsequent inspection.\n"
1213*797ac58cSKevin Wolf " The read is performed asynchronously and the aio_flush command must be\n"
1214*797ac58cSKevin Wolf " used to ensure all outstanding aio requests have been completed.\n"
1215*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n"
1216*797ac58cSKevin Wolf " -P, -- use a pattern to verify read data\n"
1217*797ac58cSKevin Wolf " -v, -- dump buffer to standard output\n"
1218*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n"
1219*797ac58cSKevin Wolf "\n");
1220*797ac58cSKevin Wolf }
1221*797ac58cSKevin Wolf 
1222*797ac58cSKevin Wolf static int aio_read_f(BlockDriverState *bs, int argc, char **argv);
1223*797ac58cSKevin Wolf 
1224*797ac58cSKevin Wolf static const cmdinfo_t aio_read_cmd = {
1225*797ac58cSKevin Wolf     .name       = "aio_read",
1226*797ac58cSKevin Wolf     .cfunc      = aio_read_f,
1227*797ac58cSKevin Wolf     .argmin     = 2,
1228*797ac58cSKevin Wolf     .argmax     = -1,
1229*797ac58cSKevin Wolf     .args       = "[-Cqv] [-P pattern ] off len [len..]",
1230*797ac58cSKevin Wolf     .oneline    = "asynchronously reads a number of bytes",
1231*797ac58cSKevin Wolf     .help       = aio_read_help,
1232*797ac58cSKevin Wolf };
1233*797ac58cSKevin Wolf 
1234*797ac58cSKevin Wolf static int aio_read_f(BlockDriverState *bs, int argc, char **argv)
1235*797ac58cSKevin Wolf {
1236*797ac58cSKevin Wolf     int nr_iov, c;
1237*797ac58cSKevin Wolf     struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1238*797ac58cSKevin Wolf 
1239*797ac58cSKevin Wolf     while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
1240*797ac58cSKevin Wolf         switch (c) {
1241*797ac58cSKevin Wolf         case 'C':
1242*797ac58cSKevin Wolf             ctx->Cflag = 1;
1243*797ac58cSKevin Wolf             break;
1244*797ac58cSKevin Wolf         case 'P':
1245*797ac58cSKevin Wolf             ctx->Pflag = 1;
1246*797ac58cSKevin Wolf             ctx->pattern = parse_pattern(optarg);
1247*797ac58cSKevin Wolf             if (ctx->pattern < 0) {
1248*797ac58cSKevin Wolf                 g_free(ctx);
1249*797ac58cSKevin Wolf                 return 0;
1250*797ac58cSKevin Wolf             }
1251*797ac58cSKevin Wolf             break;
1252*797ac58cSKevin Wolf         case 'q':
1253*797ac58cSKevin Wolf             ctx->qflag = 1;
1254*797ac58cSKevin Wolf             break;
1255*797ac58cSKevin Wolf         case 'v':
1256*797ac58cSKevin Wolf             ctx->vflag = 1;
1257*797ac58cSKevin Wolf             break;
1258*797ac58cSKevin Wolf         default:
1259*797ac58cSKevin Wolf             g_free(ctx);
1260*797ac58cSKevin Wolf             return command_usage(&aio_read_cmd);
1261*797ac58cSKevin Wolf         }
1262*797ac58cSKevin Wolf     }
1263*797ac58cSKevin Wolf 
1264*797ac58cSKevin Wolf     if (optind > argc - 2) {
1265*797ac58cSKevin Wolf         g_free(ctx);
1266*797ac58cSKevin Wolf         return command_usage(&aio_read_cmd);
1267*797ac58cSKevin Wolf     }
1268*797ac58cSKevin Wolf 
1269*797ac58cSKevin Wolf     ctx->offset = cvtnum(argv[optind]);
1270*797ac58cSKevin Wolf     if (ctx->offset < 0) {
1271*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
1272*797ac58cSKevin Wolf         g_free(ctx);
1273*797ac58cSKevin Wolf         return 0;
1274*797ac58cSKevin Wolf     }
1275*797ac58cSKevin Wolf     optind++;
1276*797ac58cSKevin Wolf 
1277*797ac58cSKevin Wolf     if (ctx->offset & 0x1ff) {
1278*797ac58cSKevin Wolf         printf("offset %" PRId64 " is not sector aligned\n",
1279*797ac58cSKevin Wolf                ctx->offset);
1280*797ac58cSKevin Wolf         g_free(ctx);
1281*797ac58cSKevin Wolf         return 0;
1282*797ac58cSKevin Wolf     }
1283*797ac58cSKevin Wolf 
1284*797ac58cSKevin Wolf     nr_iov = argc - optind;
1285*797ac58cSKevin Wolf     ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1286*797ac58cSKevin Wolf     if (ctx->buf == NULL) {
1287*797ac58cSKevin Wolf         g_free(ctx);
1288*797ac58cSKevin Wolf         return 0;
1289*797ac58cSKevin Wolf     }
1290*797ac58cSKevin Wolf 
1291*797ac58cSKevin Wolf     gettimeofday(&ctx->t1, NULL);
1292*797ac58cSKevin Wolf     bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
1293*797ac58cSKevin Wolf                    ctx->qiov.size >> 9, aio_read_done, ctx);
1294*797ac58cSKevin Wolf     return 0;
1295*797ac58cSKevin Wolf }
1296*797ac58cSKevin Wolf 
1297*797ac58cSKevin Wolf static void aio_write_help(void)
1298*797ac58cSKevin Wolf {
1299*797ac58cSKevin Wolf     printf(
1300*797ac58cSKevin Wolf "\n"
1301*797ac58cSKevin Wolf " asynchronously writes a range of bytes from the given offset source\n"
1302*797ac58cSKevin Wolf " from multiple buffers\n"
1303*797ac58cSKevin Wolf "\n"
1304*797ac58cSKevin Wolf " Example:\n"
1305*797ac58cSKevin Wolf " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1306*797ac58cSKevin Wolf "\n"
1307*797ac58cSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n"
1308*797ac58cSKevin Wolf " filled with a set pattern (0xcdcdcdcd).\n"
1309*797ac58cSKevin Wolf " The write is performed asynchronously and the aio_flush command must be\n"
1310*797ac58cSKevin Wolf " used to ensure all outstanding aio requests have been completed.\n"
1311*797ac58cSKevin Wolf " -P, -- use different pattern to fill file\n"
1312*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n"
1313*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n"
1314*797ac58cSKevin Wolf "\n");
1315*797ac58cSKevin Wolf }
1316*797ac58cSKevin Wolf 
1317*797ac58cSKevin Wolf static int aio_write_f(BlockDriverState *bs, int argc, char **argv);
1318*797ac58cSKevin Wolf 
1319*797ac58cSKevin Wolf static const cmdinfo_t aio_write_cmd = {
1320*797ac58cSKevin Wolf     .name       = "aio_write",
1321*797ac58cSKevin Wolf     .cfunc      = aio_write_f,
1322*797ac58cSKevin Wolf     .argmin     = 2,
1323*797ac58cSKevin Wolf     .argmax     = -1,
1324*797ac58cSKevin Wolf     .args       = "[-Cq] [-P pattern ] off len [len..]",
1325*797ac58cSKevin Wolf     .oneline    = "asynchronously writes a number of bytes",
1326*797ac58cSKevin Wolf     .help       = aio_write_help,
1327*797ac58cSKevin Wolf };
1328*797ac58cSKevin Wolf 
1329*797ac58cSKevin Wolf static int aio_write_f(BlockDriverState *bs, int argc, char **argv)
1330*797ac58cSKevin Wolf {
1331*797ac58cSKevin Wolf     int nr_iov, c;
1332*797ac58cSKevin Wolf     int pattern = 0xcd;
1333*797ac58cSKevin Wolf     struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1334*797ac58cSKevin Wolf 
1335*797ac58cSKevin Wolf     while ((c = getopt(argc, argv, "CqP:")) != EOF) {
1336*797ac58cSKevin Wolf         switch (c) {
1337*797ac58cSKevin Wolf         case 'C':
1338*797ac58cSKevin Wolf             ctx->Cflag = 1;
1339*797ac58cSKevin Wolf             break;
1340*797ac58cSKevin Wolf         case 'q':
1341*797ac58cSKevin Wolf             ctx->qflag = 1;
1342*797ac58cSKevin Wolf             break;
1343*797ac58cSKevin Wolf         case 'P':
1344*797ac58cSKevin Wolf             pattern = parse_pattern(optarg);
1345*797ac58cSKevin Wolf             if (pattern < 0) {
1346*797ac58cSKevin Wolf                 g_free(ctx);
1347*797ac58cSKevin Wolf                 return 0;
1348*797ac58cSKevin Wolf             }
1349*797ac58cSKevin Wolf             break;
1350*797ac58cSKevin Wolf         default:
1351*797ac58cSKevin Wolf             g_free(ctx);
1352*797ac58cSKevin Wolf             return command_usage(&aio_write_cmd);
1353*797ac58cSKevin Wolf         }
1354*797ac58cSKevin Wolf     }
1355*797ac58cSKevin Wolf 
1356*797ac58cSKevin Wolf     if (optind > argc - 2) {
1357*797ac58cSKevin Wolf         g_free(ctx);
1358*797ac58cSKevin Wolf         return command_usage(&aio_write_cmd);
1359*797ac58cSKevin Wolf     }
1360*797ac58cSKevin Wolf 
1361*797ac58cSKevin Wolf     ctx->offset = cvtnum(argv[optind]);
1362*797ac58cSKevin Wolf     if (ctx->offset < 0) {
1363*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
1364*797ac58cSKevin Wolf         g_free(ctx);
1365*797ac58cSKevin Wolf         return 0;
1366*797ac58cSKevin Wolf     }
1367*797ac58cSKevin Wolf     optind++;
1368*797ac58cSKevin Wolf 
1369*797ac58cSKevin Wolf     if (ctx->offset & 0x1ff) {
1370*797ac58cSKevin Wolf         printf("offset %" PRId64 " is not sector aligned\n",
1371*797ac58cSKevin Wolf                ctx->offset);
1372*797ac58cSKevin Wolf         g_free(ctx);
1373*797ac58cSKevin Wolf         return 0;
1374*797ac58cSKevin Wolf     }
1375*797ac58cSKevin Wolf 
1376*797ac58cSKevin Wolf     nr_iov = argc - optind;
1377*797ac58cSKevin Wolf     ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern);
1378*797ac58cSKevin Wolf     if (ctx->buf == NULL) {
1379*797ac58cSKevin Wolf         g_free(ctx);
1380*797ac58cSKevin Wolf         return 0;
1381*797ac58cSKevin Wolf     }
1382*797ac58cSKevin Wolf 
1383*797ac58cSKevin Wolf     gettimeofday(&ctx->t1, NULL);
1384*797ac58cSKevin Wolf     bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
1385*797ac58cSKevin Wolf                     ctx->qiov.size >> 9, aio_write_done, ctx);
1386*797ac58cSKevin Wolf     return 0;
1387*797ac58cSKevin Wolf }
1388*797ac58cSKevin Wolf 
1389*797ac58cSKevin Wolf static int aio_flush_f(BlockDriverState *bs, int argc, char **argv)
1390*797ac58cSKevin Wolf {
1391*797ac58cSKevin Wolf     bdrv_drain_all();
1392*797ac58cSKevin Wolf     return 0;
1393*797ac58cSKevin Wolf }
1394*797ac58cSKevin Wolf 
1395*797ac58cSKevin Wolf static const cmdinfo_t aio_flush_cmd = {
1396*797ac58cSKevin Wolf     .name       = "aio_flush",
1397*797ac58cSKevin Wolf     .cfunc      = aio_flush_f,
1398*797ac58cSKevin Wolf     .oneline    = "completes all outstanding aio requests"
1399*797ac58cSKevin Wolf };
1400*797ac58cSKevin Wolf 
1401*797ac58cSKevin Wolf static int flush_f(BlockDriverState *bs, int argc, char **argv)
1402*797ac58cSKevin Wolf {
1403*797ac58cSKevin Wolf     bdrv_flush(bs);
1404*797ac58cSKevin Wolf     return 0;
1405*797ac58cSKevin Wolf }
1406*797ac58cSKevin Wolf 
1407*797ac58cSKevin Wolf static const cmdinfo_t flush_cmd = {
1408*797ac58cSKevin Wolf     .name       = "flush",
1409*797ac58cSKevin Wolf     .altname    = "f",
1410*797ac58cSKevin Wolf     .cfunc      = flush_f,
1411*797ac58cSKevin Wolf     .oneline    = "flush all in-core file state to disk",
1412*797ac58cSKevin Wolf };
1413*797ac58cSKevin Wolf 
1414*797ac58cSKevin Wolf static int truncate_f(BlockDriverState *bs, int argc, char **argv)
1415*797ac58cSKevin Wolf {
1416*797ac58cSKevin Wolf     int64_t offset;
1417*797ac58cSKevin Wolf     int ret;
1418*797ac58cSKevin Wolf 
1419*797ac58cSKevin Wolf     offset = cvtnum(argv[1]);
1420*797ac58cSKevin Wolf     if (offset < 0) {
1421*797ac58cSKevin Wolf         printf("non-numeric truncate argument -- %s\n", argv[1]);
1422*797ac58cSKevin Wolf         return 0;
1423*797ac58cSKevin Wolf     }
1424*797ac58cSKevin Wolf 
1425*797ac58cSKevin Wolf     ret = bdrv_truncate(bs, offset);
1426*797ac58cSKevin Wolf     if (ret < 0) {
1427*797ac58cSKevin Wolf         printf("truncate: %s\n", strerror(-ret));
1428*797ac58cSKevin Wolf         return 0;
1429*797ac58cSKevin Wolf     }
1430*797ac58cSKevin Wolf 
1431*797ac58cSKevin Wolf     return 0;
1432*797ac58cSKevin Wolf }
1433*797ac58cSKevin Wolf 
1434*797ac58cSKevin Wolf static const cmdinfo_t truncate_cmd = {
1435*797ac58cSKevin Wolf     .name       = "truncate",
1436*797ac58cSKevin Wolf     .altname    = "t",
1437*797ac58cSKevin Wolf     .cfunc      = truncate_f,
1438*797ac58cSKevin Wolf     .argmin     = 1,
1439*797ac58cSKevin Wolf     .argmax     = 1,
1440*797ac58cSKevin Wolf     .args       = "off",
1441*797ac58cSKevin Wolf     .oneline    = "truncates the current file at the given offset",
1442*797ac58cSKevin Wolf };
1443*797ac58cSKevin Wolf 
1444*797ac58cSKevin Wolf static int length_f(BlockDriverState *bs, int argc, char **argv)
1445*797ac58cSKevin Wolf {
1446*797ac58cSKevin Wolf     int64_t size;
1447*797ac58cSKevin Wolf     char s1[64];
1448*797ac58cSKevin Wolf 
1449*797ac58cSKevin Wolf     size = bdrv_getlength(bs);
1450*797ac58cSKevin Wolf     if (size < 0) {
1451*797ac58cSKevin Wolf         printf("getlength: %s\n", strerror(-size));
1452*797ac58cSKevin Wolf         return 0;
1453*797ac58cSKevin Wolf     }
1454*797ac58cSKevin Wolf 
1455*797ac58cSKevin Wolf     cvtstr(size, s1, sizeof(s1));
1456*797ac58cSKevin Wolf     printf("%s\n", s1);
1457*797ac58cSKevin Wolf     return 0;
1458*797ac58cSKevin Wolf }
1459*797ac58cSKevin Wolf 
1460*797ac58cSKevin Wolf 
1461*797ac58cSKevin Wolf static const cmdinfo_t length_cmd = {
1462*797ac58cSKevin Wolf     .name   = "length",
1463*797ac58cSKevin Wolf     .altname    = "l",
1464*797ac58cSKevin Wolf     .cfunc      = length_f,
1465*797ac58cSKevin Wolf     .oneline    = "gets the length of the current file",
1466*797ac58cSKevin Wolf };
1467*797ac58cSKevin Wolf 
1468*797ac58cSKevin Wolf 
1469*797ac58cSKevin Wolf static int info_f(BlockDriverState *bs, int argc, char **argv)
1470*797ac58cSKevin Wolf {
1471*797ac58cSKevin Wolf     BlockDriverInfo bdi;
1472*797ac58cSKevin Wolf     char s1[64], s2[64];
1473*797ac58cSKevin Wolf     int ret;
1474*797ac58cSKevin Wolf 
1475*797ac58cSKevin Wolf     if (bs->drv && bs->drv->format_name) {
1476*797ac58cSKevin Wolf         printf("format name: %s\n", bs->drv->format_name);
1477*797ac58cSKevin Wolf     }
1478*797ac58cSKevin Wolf     if (bs->drv && bs->drv->protocol_name) {
1479*797ac58cSKevin Wolf         printf("format name: %s\n", bs->drv->protocol_name);
1480*797ac58cSKevin Wolf     }
1481*797ac58cSKevin Wolf 
1482*797ac58cSKevin Wolf     ret = bdrv_get_info(bs, &bdi);
1483*797ac58cSKevin Wolf     if (ret) {
1484*797ac58cSKevin Wolf         return 0;
1485*797ac58cSKevin Wolf     }
1486*797ac58cSKevin Wolf 
1487*797ac58cSKevin Wolf     cvtstr(bdi.cluster_size, s1, sizeof(s1));
1488*797ac58cSKevin Wolf     cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1489*797ac58cSKevin Wolf 
1490*797ac58cSKevin Wolf     printf("cluster size: %s\n", s1);
1491*797ac58cSKevin Wolf     printf("vm state offset: %s\n", s2);
1492*797ac58cSKevin Wolf 
1493*797ac58cSKevin Wolf     return 0;
1494*797ac58cSKevin Wolf }
1495*797ac58cSKevin Wolf 
1496*797ac58cSKevin Wolf 
1497*797ac58cSKevin Wolf 
1498*797ac58cSKevin Wolf static const cmdinfo_t info_cmd = {
1499*797ac58cSKevin Wolf     .name       = "info",
1500*797ac58cSKevin Wolf     .altname    = "i",
1501*797ac58cSKevin Wolf     .cfunc      = info_f,
1502*797ac58cSKevin Wolf     .oneline    = "prints information about the current file",
1503*797ac58cSKevin Wolf };
1504*797ac58cSKevin Wolf 
1505*797ac58cSKevin Wolf static void discard_help(void)
1506*797ac58cSKevin Wolf {
1507*797ac58cSKevin Wolf     printf(
1508*797ac58cSKevin Wolf "\n"
1509*797ac58cSKevin Wolf " discards a range of bytes from the given offset\n"
1510*797ac58cSKevin Wolf "\n"
1511*797ac58cSKevin Wolf " Example:\n"
1512*797ac58cSKevin Wolf " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1513*797ac58cSKevin Wolf "\n"
1514*797ac58cSKevin Wolf " Discards a segment of the currently open file.\n"
1515*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n"
1516*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n"
1517*797ac58cSKevin Wolf "\n");
1518*797ac58cSKevin Wolf }
1519*797ac58cSKevin Wolf 
1520*797ac58cSKevin Wolf static int discard_f(BlockDriverState *bs, int argc, char **argv);
1521*797ac58cSKevin Wolf 
1522*797ac58cSKevin Wolf static const cmdinfo_t discard_cmd = {
1523*797ac58cSKevin Wolf     .name       = "discard",
1524*797ac58cSKevin Wolf     .altname    = "d",
1525*797ac58cSKevin Wolf     .cfunc      = discard_f,
1526*797ac58cSKevin Wolf     .argmin     = 2,
1527*797ac58cSKevin Wolf     .argmax     = -1,
1528*797ac58cSKevin Wolf     .args       = "[-Cq] off len",
1529*797ac58cSKevin Wolf     .oneline    = "discards a number of bytes at a specified offset",
1530*797ac58cSKevin Wolf     .help       = discard_help,
1531*797ac58cSKevin Wolf };
1532*797ac58cSKevin Wolf 
1533*797ac58cSKevin Wolf static int discard_f(BlockDriverState *bs, int argc, char **argv)
1534*797ac58cSKevin Wolf {
1535*797ac58cSKevin Wolf     struct timeval t1, t2;
1536*797ac58cSKevin Wolf     int Cflag = 0, qflag = 0;
1537*797ac58cSKevin Wolf     int c, ret;
1538*797ac58cSKevin Wolf     int64_t offset;
1539*797ac58cSKevin Wolf     int count;
1540*797ac58cSKevin Wolf 
1541*797ac58cSKevin Wolf     while ((c = getopt(argc, argv, "Cq")) != EOF) {
1542*797ac58cSKevin Wolf         switch (c) {
1543*797ac58cSKevin Wolf         case 'C':
1544*797ac58cSKevin Wolf             Cflag = 1;
1545*797ac58cSKevin Wolf             break;
1546*797ac58cSKevin Wolf         case 'q':
1547*797ac58cSKevin Wolf             qflag = 1;
1548*797ac58cSKevin Wolf             break;
1549*797ac58cSKevin Wolf         default:
1550*797ac58cSKevin Wolf             return command_usage(&discard_cmd);
1551*797ac58cSKevin Wolf         }
1552*797ac58cSKevin Wolf     }
1553*797ac58cSKevin Wolf 
1554*797ac58cSKevin Wolf     if (optind != argc - 2) {
1555*797ac58cSKevin Wolf         return command_usage(&discard_cmd);
1556*797ac58cSKevin Wolf     }
1557*797ac58cSKevin Wolf 
1558*797ac58cSKevin Wolf     offset = cvtnum(argv[optind]);
1559*797ac58cSKevin Wolf     if (offset < 0) {
1560*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
1561*797ac58cSKevin Wolf         return 0;
1562*797ac58cSKevin Wolf     }
1563*797ac58cSKevin Wolf 
1564*797ac58cSKevin Wolf     optind++;
1565*797ac58cSKevin Wolf     count = cvtnum(argv[optind]);
1566*797ac58cSKevin Wolf     if (count < 0) {
1567*797ac58cSKevin Wolf         printf("non-numeric length argument -- %s\n", argv[optind]);
1568*797ac58cSKevin Wolf         return 0;
1569*797ac58cSKevin Wolf     }
1570*797ac58cSKevin Wolf 
1571*797ac58cSKevin Wolf     gettimeofday(&t1, NULL);
1572*797ac58cSKevin Wolf     ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
1573*797ac58cSKevin Wolf                        count >> BDRV_SECTOR_BITS);
1574*797ac58cSKevin Wolf     gettimeofday(&t2, NULL);
1575*797ac58cSKevin Wolf 
1576*797ac58cSKevin Wolf     if (ret < 0) {
1577*797ac58cSKevin Wolf         printf("discard failed: %s\n", strerror(-ret));
1578*797ac58cSKevin Wolf         goto out;
1579*797ac58cSKevin Wolf     }
1580*797ac58cSKevin Wolf 
1581*797ac58cSKevin Wolf     /* Finally, report back -- -C gives a parsable format */
1582*797ac58cSKevin Wolf     if (!qflag) {
1583*797ac58cSKevin Wolf         t2 = tsub(t2, t1);
1584*797ac58cSKevin Wolf         print_report("discard", &t2, offset, count, count, 1, Cflag);
1585*797ac58cSKevin Wolf     }
1586*797ac58cSKevin Wolf 
1587*797ac58cSKevin Wolf out:
1588*797ac58cSKevin Wolf     return 0;
1589*797ac58cSKevin Wolf }
1590*797ac58cSKevin Wolf 
1591*797ac58cSKevin Wolf static int alloc_f(BlockDriverState *bs, int argc, char **argv)
1592*797ac58cSKevin Wolf {
1593*797ac58cSKevin Wolf     int64_t offset, sector_num;
1594*797ac58cSKevin Wolf     int nb_sectors, remaining;
1595*797ac58cSKevin Wolf     char s1[64];
1596*797ac58cSKevin Wolf     int num, sum_alloc;
1597*797ac58cSKevin Wolf     int ret;
1598*797ac58cSKevin Wolf 
1599*797ac58cSKevin Wolf     offset = cvtnum(argv[1]);
1600*797ac58cSKevin Wolf     if (offset < 0) {
1601*797ac58cSKevin Wolf         printf("non-numeric offset argument -- %s\n", argv[1]);
1602*797ac58cSKevin Wolf         return 0;
1603*797ac58cSKevin Wolf     } else if (offset & 0x1ff) {
1604*797ac58cSKevin Wolf         printf("offset %" PRId64 " is not sector aligned\n",
1605*797ac58cSKevin Wolf                offset);
1606*797ac58cSKevin Wolf         return 0;
1607*797ac58cSKevin Wolf     }
1608*797ac58cSKevin Wolf 
1609*797ac58cSKevin Wolf     if (argc == 3) {
1610*797ac58cSKevin Wolf         nb_sectors = cvtnum(argv[2]);
1611*797ac58cSKevin Wolf         if (nb_sectors < 0) {
1612*797ac58cSKevin Wolf             printf("non-numeric length argument -- %s\n", argv[2]);
1613*797ac58cSKevin Wolf             return 0;
1614*797ac58cSKevin Wolf         }
1615*797ac58cSKevin Wolf     } else {
1616*797ac58cSKevin Wolf         nb_sectors = 1;
1617*797ac58cSKevin Wolf     }
1618*797ac58cSKevin Wolf 
1619*797ac58cSKevin Wolf     remaining = nb_sectors;
1620*797ac58cSKevin Wolf     sum_alloc = 0;
1621*797ac58cSKevin Wolf     sector_num = offset >> 9;
1622*797ac58cSKevin Wolf     while (remaining) {
1623*797ac58cSKevin Wolf         ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1624*797ac58cSKevin Wolf         sector_num += num;
1625*797ac58cSKevin Wolf         remaining -= num;
1626*797ac58cSKevin Wolf         if (ret) {
1627*797ac58cSKevin Wolf             sum_alloc += num;
1628*797ac58cSKevin Wolf         }
1629*797ac58cSKevin Wolf         if (num == 0) {
1630*797ac58cSKevin Wolf             nb_sectors -= remaining;
1631*797ac58cSKevin Wolf             remaining = 0;
1632*797ac58cSKevin Wolf         }
1633*797ac58cSKevin Wolf     }
1634*797ac58cSKevin Wolf 
1635*797ac58cSKevin Wolf     cvtstr(offset, s1, sizeof(s1));
1636*797ac58cSKevin Wolf 
1637*797ac58cSKevin Wolf     printf("%d/%d sectors allocated at offset %s\n",
1638*797ac58cSKevin Wolf            sum_alloc, nb_sectors, s1);
1639*797ac58cSKevin Wolf     return 0;
1640*797ac58cSKevin Wolf }
1641*797ac58cSKevin Wolf 
1642*797ac58cSKevin Wolf static const cmdinfo_t alloc_cmd = {
1643*797ac58cSKevin Wolf     .name       = "alloc",
1644*797ac58cSKevin Wolf     .altname    = "a",
1645*797ac58cSKevin Wolf     .argmin     = 1,
1646*797ac58cSKevin Wolf     .argmax     = 2,
1647*797ac58cSKevin Wolf     .cfunc      = alloc_f,
1648*797ac58cSKevin Wolf     .args       = "off [sectors]",
1649*797ac58cSKevin Wolf     .oneline    = "checks if a sector is present in the file",
1650*797ac58cSKevin Wolf };
1651*797ac58cSKevin Wolf 
1652*797ac58cSKevin Wolf 
1653*797ac58cSKevin Wolf static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
1654*797ac58cSKevin Wolf                             int64_t nb_sectors, int64_t *pnum)
1655*797ac58cSKevin Wolf {
1656*797ac58cSKevin Wolf     int num, num_checked;
1657*797ac58cSKevin Wolf     int ret, firstret;
1658*797ac58cSKevin Wolf 
1659*797ac58cSKevin Wolf     num_checked = MIN(nb_sectors, INT_MAX);
1660*797ac58cSKevin Wolf     ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1661*797ac58cSKevin Wolf     if (ret < 0) {
1662*797ac58cSKevin Wolf         return ret;
1663*797ac58cSKevin Wolf     }
1664*797ac58cSKevin Wolf 
1665*797ac58cSKevin Wolf     firstret = ret;
1666*797ac58cSKevin Wolf     *pnum = num;
1667*797ac58cSKevin Wolf 
1668*797ac58cSKevin Wolf     while (nb_sectors > 0 && ret == firstret) {
1669*797ac58cSKevin Wolf         sector_num += num;
1670*797ac58cSKevin Wolf         nb_sectors -= num;
1671*797ac58cSKevin Wolf 
1672*797ac58cSKevin Wolf         num_checked = MIN(nb_sectors, INT_MAX);
1673*797ac58cSKevin Wolf         ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1674*797ac58cSKevin Wolf         if (ret == firstret) {
1675*797ac58cSKevin Wolf             *pnum += num;
1676*797ac58cSKevin Wolf         } else {
1677*797ac58cSKevin Wolf             break;
1678*797ac58cSKevin Wolf         }
1679*797ac58cSKevin Wolf     }
1680*797ac58cSKevin Wolf 
1681*797ac58cSKevin Wolf     return firstret;
1682*797ac58cSKevin Wolf }
1683*797ac58cSKevin Wolf 
1684*797ac58cSKevin Wolf static int map_f(BlockDriverState *bs, int argc, char **argv)
1685*797ac58cSKevin Wolf {
1686*797ac58cSKevin Wolf     int64_t offset;
1687*797ac58cSKevin Wolf     int64_t nb_sectors;
1688*797ac58cSKevin Wolf     char s1[64];
1689*797ac58cSKevin Wolf     int64_t num;
1690*797ac58cSKevin Wolf     int ret;
1691*797ac58cSKevin Wolf     const char *retstr;
1692*797ac58cSKevin Wolf 
1693*797ac58cSKevin Wolf     offset = 0;
1694*797ac58cSKevin Wolf     nb_sectors = bs->total_sectors;
1695*797ac58cSKevin Wolf 
1696*797ac58cSKevin Wolf     do {
1697*797ac58cSKevin Wolf         ret = map_is_allocated(bs, offset, nb_sectors, &num);
1698*797ac58cSKevin Wolf         if (ret < 0) {
1699*797ac58cSKevin Wolf             error_report("Failed to get allocation status: %s", strerror(-ret));
1700*797ac58cSKevin Wolf             return 0;
1701*797ac58cSKevin Wolf         }
1702*797ac58cSKevin Wolf 
1703*797ac58cSKevin Wolf         retstr = ret ? "    allocated" : "not allocated";
1704*797ac58cSKevin Wolf         cvtstr(offset << 9ULL, s1, sizeof(s1));
1705*797ac58cSKevin Wolf         printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
1706*797ac58cSKevin Wolf                "at offset %s (%d)\n",
1707*797ac58cSKevin Wolf                offset << 9ULL, num, nb_sectors, retstr, s1, ret);
1708*797ac58cSKevin Wolf 
1709*797ac58cSKevin Wolf         offset += num;
1710*797ac58cSKevin Wolf         nb_sectors -= num;
1711*797ac58cSKevin Wolf     } while (offset < bs->total_sectors);
1712*797ac58cSKevin Wolf 
1713*797ac58cSKevin Wolf     return 0;
1714*797ac58cSKevin Wolf }
1715*797ac58cSKevin Wolf 
1716*797ac58cSKevin Wolf static const cmdinfo_t map_cmd = {
1717*797ac58cSKevin Wolf        .name           = "map",
1718*797ac58cSKevin Wolf        .argmin         = 0,
1719*797ac58cSKevin Wolf        .argmax         = 0,
1720*797ac58cSKevin Wolf        .cfunc          = map_f,
1721*797ac58cSKevin Wolf        .args           = "",
1722*797ac58cSKevin Wolf        .oneline        = "prints the allocated areas of a file",
1723*797ac58cSKevin Wolf };
1724*797ac58cSKevin Wolf 
1725*797ac58cSKevin Wolf static int break_f(BlockDriverState *bs, int argc, char **argv)
1726*797ac58cSKevin Wolf {
1727*797ac58cSKevin Wolf     int ret;
1728*797ac58cSKevin Wolf 
1729*797ac58cSKevin Wolf     ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]);
1730*797ac58cSKevin Wolf     if (ret < 0) {
1731*797ac58cSKevin Wolf         printf("Could not set breakpoint: %s\n", strerror(-ret));
1732*797ac58cSKevin Wolf     }
1733*797ac58cSKevin Wolf 
1734*797ac58cSKevin Wolf     return 0;
1735*797ac58cSKevin Wolf }
1736*797ac58cSKevin Wolf 
1737*797ac58cSKevin Wolf static const cmdinfo_t break_cmd = {
1738*797ac58cSKevin Wolf        .name           = "break",
1739*797ac58cSKevin Wolf        .argmin         = 2,
1740*797ac58cSKevin Wolf        .argmax         = 2,
1741*797ac58cSKevin Wolf        .cfunc          = break_f,
1742*797ac58cSKevin Wolf        .args           = "event tag",
1743*797ac58cSKevin Wolf        .oneline        = "sets a breakpoint on event and tags the stopped "
1744*797ac58cSKevin Wolf                          "request as tag",
1745*797ac58cSKevin Wolf };
1746*797ac58cSKevin Wolf 
1747*797ac58cSKevin Wolf static int resume_f(BlockDriverState *bs, int argc, char **argv)
1748*797ac58cSKevin Wolf {
1749*797ac58cSKevin Wolf     int ret;
1750*797ac58cSKevin Wolf 
1751*797ac58cSKevin Wolf     ret = bdrv_debug_resume(bs, argv[1]);
1752*797ac58cSKevin Wolf     if (ret < 0) {
1753*797ac58cSKevin Wolf         printf("Could not resume request: %s\n", strerror(-ret));
1754*797ac58cSKevin Wolf     }
1755*797ac58cSKevin Wolf 
1756*797ac58cSKevin Wolf     return 0;
1757*797ac58cSKevin Wolf }
1758*797ac58cSKevin Wolf 
1759*797ac58cSKevin Wolf static const cmdinfo_t resume_cmd = {
1760*797ac58cSKevin Wolf        .name           = "resume",
1761*797ac58cSKevin Wolf        .argmin         = 1,
1762*797ac58cSKevin Wolf        .argmax         = 1,
1763*797ac58cSKevin Wolf        .cfunc          = resume_f,
1764*797ac58cSKevin Wolf        .args           = "tag",
1765*797ac58cSKevin Wolf        .oneline        = "resumes the request tagged as tag",
1766*797ac58cSKevin Wolf };
1767*797ac58cSKevin Wolf 
1768*797ac58cSKevin Wolf static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
1769*797ac58cSKevin Wolf {
1770*797ac58cSKevin Wolf     while (!bdrv_debug_is_suspended(bs, argv[1])) {
1771*797ac58cSKevin Wolf         qemu_aio_wait();
1772*797ac58cSKevin Wolf     }
1773*797ac58cSKevin Wolf 
1774*797ac58cSKevin Wolf     return 0;
1775*797ac58cSKevin Wolf }
1776*797ac58cSKevin Wolf 
1777*797ac58cSKevin Wolf static const cmdinfo_t wait_break_cmd = {
1778*797ac58cSKevin Wolf        .name           = "wait_break",
1779*797ac58cSKevin Wolf        .argmin         = 1,
1780*797ac58cSKevin Wolf        .argmax         = 1,
1781*797ac58cSKevin Wolf        .cfunc          = wait_break_f,
1782*797ac58cSKevin Wolf        .args           = "tag",
1783*797ac58cSKevin Wolf        .oneline        = "waits for the suspension of a request",
1784*797ac58cSKevin Wolf };
1785*797ac58cSKevin Wolf 
1786*797ac58cSKevin Wolf static int abort_f(BlockDriverState *bs, int argc, char **argv)
1787*797ac58cSKevin Wolf {
1788*797ac58cSKevin Wolf     abort();
1789*797ac58cSKevin Wolf }
1790*797ac58cSKevin Wolf 
1791*797ac58cSKevin Wolf static const cmdinfo_t abort_cmd = {
1792*797ac58cSKevin Wolf        .name           = "abort",
1793*797ac58cSKevin Wolf        .cfunc          = abort_f,
1794*797ac58cSKevin Wolf        .flags          = CMD_NOFILE_OK,
1795*797ac58cSKevin Wolf        .oneline        = "simulate a program crash using abort(3)",
1796*797ac58cSKevin Wolf };
1797*797ac58cSKevin Wolf 
1798*797ac58cSKevin Wolf static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct)
1799*797ac58cSKevin Wolf {
1800*797ac58cSKevin Wolf     if (ct->flags & CMD_FLAG_GLOBAL) {
1801*797ac58cSKevin Wolf         return 1;
1802*797ac58cSKevin Wolf     }
1803*797ac58cSKevin Wolf     if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
1804*797ac58cSKevin Wolf         fprintf(stderr, "no file open, try 'help open'\n");
1805*797ac58cSKevin Wolf         return 0;
1806*797ac58cSKevin Wolf     }
1807*797ac58cSKevin Wolf     return 1;
1808*797ac58cSKevin Wolf }
1809*797ac58cSKevin Wolf 
1810*797ac58cSKevin Wolf static void __attribute((constructor)) init_qemuio_commands(void)
1811*797ac58cSKevin Wolf {
1812*797ac58cSKevin Wolf     /* initialize commands */
1813*797ac58cSKevin Wolf     help_init();
1814*797ac58cSKevin Wolf     add_command(&read_cmd);
1815*797ac58cSKevin Wolf     add_command(&readv_cmd);
1816*797ac58cSKevin Wolf     add_command(&write_cmd);
1817*797ac58cSKevin Wolf     add_command(&writev_cmd);
1818*797ac58cSKevin Wolf     add_command(&multiwrite_cmd);
1819*797ac58cSKevin Wolf     add_command(&aio_read_cmd);
1820*797ac58cSKevin Wolf     add_command(&aio_write_cmd);
1821*797ac58cSKevin Wolf     add_command(&aio_flush_cmd);
1822*797ac58cSKevin Wolf     add_command(&flush_cmd);
1823*797ac58cSKevin Wolf     add_command(&truncate_cmd);
1824*797ac58cSKevin Wolf     add_command(&length_cmd);
1825*797ac58cSKevin Wolf     add_command(&info_cmd);
1826*797ac58cSKevin Wolf     add_command(&discard_cmd);
1827*797ac58cSKevin Wolf     add_command(&alloc_cmd);
1828*797ac58cSKevin Wolf     add_command(&map_cmd);
1829*797ac58cSKevin Wolf     add_command(&break_cmd);
1830*797ac58cSKevin Wolf     add_command(&resume_cmd);
1831*797ac58cSKevin Wolf     add_command(&wait_break_cmd);
1832*797ac58cSKevin Wolf     add_command(&abort_cmd);
1833*797ac58cSKevin Wolf 
1834*797ac58cSKevin Wolf     add_check_command(init_check_command);
1835*797ac58cSKevin Wolf }
1836