1e3aff4f6Saliguori /* 2e3aff4f6Saliguori * Command line utility to exercise the QEMU I/O path. 3e3aff4f6Saliguori * 4e3aff4f6Saliguori * Copyright (C) 2009 Red Hat, Inc. 5e3aff4f6Saliguori * Copyright (c) 2003-2005 Silicon Graphics, Inc. 6e3aff4f6Saliguori * 7e3aff4f6Saliguori * This work is licensed under the terms of the GNU GPL, version 2 or later. 8e3aff4f6Saliguori * See the COPYING file in the top-level directory. 9e3aff4f6Saliguori */ 10c32d766aSStefan Weil #include <sys/time.h> 11e3aff4f6Saliguori #include <sys/types.h> 12e3aff4f6Saliguori #include <stdarg.h> 13e3aff4f6Saliguori #include <stdio.h> 14e3aff4f6Saliguori #include <getopt.h> 15c32d766aSStefan Weil #include <libgen.h> 16e3aff4f6Saliguori 17e3aff4f6Saliguori #include "qemu-common.h" 18e3aff4f6Saliguori #include "block_int.h" 19e3aff4f6Saliguori #include "cmd.h" 20e3aff4f6Saliguori 21e3aff4f6Saliguori #define VERSION "0.0.1" 22e3aff4f6Saliguori 23e3aff4f6Saliguori #define CMD_NOFILE_OK 0x01 24e3aff4f6Saliguori 25e3aff4f6Saliguori char *progname; 26e3aff4f6Saliguori static BlockDriverState *bs; 27e3aff4f6Saliguori 28e3aff4f6Saliguori static int misalign; 29e3aff4f6Saliguori 30e3aff4f6Saliguori /* 31cf070d7eSChristoph Hellwig * Parse the pattern argument to various sub-commands. 32cf070d7eSChristoph Hellwig * 33cf070d7eSChristoph Hellwig * Because the pattern is used as an argument to memset it must evaluate 34cf070d7eSChristoph Hellwig * to an unsigned integer that fits into a single byte. 35cf070d7eSChristoph Hellwig */ 36cf070d7eSChristoph Hellwig static int parse_pattern(const char *arg) 37cf070d7eSChristoph Hellwig { 38cf070d7eSChristoph Hellwig char *endptr = NULL; 39cf070d7eSChristoph Hellwig long pattern; 40cf070d7eSChristoph Hellwig 41cf070d7eSChristoph Hellwig pattern = strtol(arg, &endptr, 0); 42cf070d7eSChristoph Hellwig if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') { 43cf070d7eSChristoph Hellwig printf("%s is not a valid pattern byte\n", arg); 44cf070d7eSChristoph Hellwig return -1; 45cf070d7eSChristoph Hellwig } 46cf070d7eSChristoph Hellwig 47cf070d7eSChristoph Hellwig return pattern; 48cf070d7eSChristoph Hellwig } 49cf070d7eSChristoph Hellwig 50cf070d7eSChristoph Hellwig /* 51e3aff4f6Saliguori * Memory allocation helpers. 52e3aff4f6Saliguori * 53e3aff4f6Saliguori * Make sure memory is aligned by default, or purposefully misaligned if 54e3aff4f6Saliguori * that is specified on the command line. 55e3aff4f6Saliguori */ 56e3aff4f6Saliguori 57e3aff4f6Saliguori #define MISALIGN_OFFSET 16 58e3aff4f6Saliguori static void *qemu_io_alloc(size_t len, int pattern) 59e3aff4f6Saliguori { 60e3aff4f6Saliguori void *buf; 61e3aff4f6Saliguori 6243642b38SDevin Nakamura if (misalign) { 63e3aff4f6Saliguori len += MISALIGN_OFFSET; 6443642b38SDevin Nakamura } 6572aef731SChristoph Hellwig buf = qemu_blockalign(bs, len); 66e3aff4f6Saliguori memset(buf, pattern, len); 6743642b38SDevin Nakamura if (misalign) { 68e3aff4f6Saliguori buf += MISALIGN_OFFSET; 6943642b38SDevin Nakamura } 70e3aff4f6Saliguori return buf; 71e3aff4f6Saliguori } 72e3aff4f6Saliguori 73e3aff4f6Saliguori static void qemu_io_free(void *p) 74e3aff4f6Saliguori { 7543642b38SDevin Nakamura if (misalign) { 76e3aff4f6Saliguori p -= MISALIGN_OFFSET; 7743642b38SDevin Nakamura } 78e3aff4f6Saliguori qemu_vfree(p); 79e3aff4f6Saliguori } 80e3aff4f6Saliguori 8143642b38SDevin Nakamura static void dump_buffer(const void *buffer, int64_t offset, int len) 82e3aff4f6Saliguori { 83e3aff4f6Saliguori int i, j; 843abcdf49SStefan Weil const uint8_t *p; 85e3aff4f6Saliguori 86e3aff4f6Saliguori for (i = 0, p = buffer; i < len; i += 16) { 873abcdf49SStefan Weil const uint8_t *s = p; 88e3aff4f6Saliguori 890bfcd599SBlue Swirl printf("%08" PRIx64 ": ", offset + i); 9043642b38SDevin Nakamura for (j = 0; j < 16 && i + j < len; j++, p++) { 91e3aff4f6Saliguori printf("%02x ", *p); 9243642b38SDevin Nakamura } 93e3aff4f6Saliguori printf(" "); 94e3aff4f6Saliguori for (j = 0; j < 16 && i + j < len; j++, s++) { 9543642b38SDevin Nakamura if (isalnum(*s)) { 96e3aff4f6Saliguori printf("%c", *s); 9743642b38SDevin Nakamura } else { 98e3aff4f6Saliguori printf("."); 99e3aff4f6Saliguori } 10043642b38SDevin Nakamura } 101e3aff4f6Saliguori printf("\n"); 102e3aff4f6Saliguori } 103e3aff4f6Saliguori } 104e3aff4f6Saliguori 10543642b38SDevin Nakamura static void print_report(const char *op, struct timeval *t, int64_t offset, 106e3aff4f6Saliguori int count, int total, int cnt, int Cflag) 107e3aff4f6Saliguori { 108e3aff4f6Saliguori char s1[64], s2[64], ts[64]; 109e3aff4f6Saliguori 110e3aff4f6Saliguori timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); 111e3aff4f6Saliguori if (!Cflag) { 112e3aff4f6Saliguori cvtstr((double)total, s1, sizeof(s1)); 113e3aff4f6Saliguori cvtstr(tdiv((double)total, *t), s2, sizeof(s2)); 1140bfcd599SBlue Swirl printf("%s %d/%d bytes at offset %" PRId64 "\n", 1150bfcd599SBlue Swirl op, total, count, offset); 116e3aff4f6Saliguori printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n", 117e3aff4f6Saliguori s1, cnt, ts, s2, tdiv((double)cnt, *t)); 118e3aff4f6Saliguori } else {/* bytes,ops,time,bytes/sec,ops/sec */ 119e3aff4f6Saliguori printf("%d,%d,%s,%.3f,%.3f\n", 120e3aff4f6Saliguori total, cnt, ts, 121e3aff4f6Saliguori tdiv((double)total, *t), 122e3aff4f6Saliguori tdiv((double)cnt, *t)); 123e3aff4f6Saliguori } 124e3aff4f6Saliguori } 125e3aff4f6Saliguori 126cf57298aSChristoph Hellwig /* 127cf57298aSChristoph Hellwig * Parse multiple length statements for vectored I/O, and construct an I/O 128cf57298aSChristoph Hellwig * vector matching it. 129cf57298aSChristoph Hellwig */ 130cf57298aSChristoph Hellwig static void * 131cf57298aSChristoph Hellwig create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern) 132cf57298aSChristoph Hellwig { 133cf57298aSChristoph Hellwig size_t *sizes = calloc(nr_iov, sizeof(size_t)); 134cf57298aSChristoph Hellwig size_t count = 0; 13540a0d7c3SKevin Wolf void *buf = NULL; 13640a0d7c3SKevin Wolf void *p; 137cf57298aSChristoph Hellwig int i; 138cf57298aSChristoph Hellwig 139cf57298aSChristoph Hellwig for (i = 0; i < nr_iov; i++) { 140cf57298aSChristoph Hellwig char *arg = argv[i]; 141ca1d6ac6SJoel Schopp int64_t len; 142cf57298aSChristoph Hellwig 143cf57298aSChristoph Hellwig len = cvtnum(arg); 144cf57298aSChristoph Hellwig if (len < 0) { 145cf57298aSChristoph Hellwig printf("non-numeric length argument -- %s\n", arg); 14640a0d7c3SKevin Wolf goto fail; 147cf57298aSChristoph Hellwig } 148cf57298aSChristoph Hellwig 149cf57298aSChristoph Hellwig /* should be SIZE_T_MAX, but that doesn't exist */ 150ca1d6ac6SJoel Schopp if (len > INT_MAX) { 151cf57298aSChristoph Hellwig printf("too large length argument -- %s\n", arg); 15240a0d7c3SKevin Wolf goto fail; 153cf57298aSChristoph Hellwig } 154cf57298aSChristoph Hellwig 155cf57298aSChristoph Hellwig if (len & 0x1ff) { 1560bfcd599SBlue Swirl printf("length argument %" PRId64 1570bfcd599SBlue Swirl " is not sector aligned\n", len); 15840a0d7c3SKevin Wolf goto fail; 159cf57298aSChristoph Hellwig } 160cf57298aSChristoph Hellwig 161cf57298aSChristoph Hellwig sizes[i] = len; 162cf57298aSChristoph Hellwig count += len; 163cf57298aSChristoph Hellwig } 164cf57298aSChristoph Hellwig 165cf57298aSChristoph Hellwig qemu_iovec_init(qiov, nr_iov); 166cf57298aSChristoph Hellwig 167cf57298aSChristoph Hellwig buf = p = qemu_io_alloc(count, pattern); 168cf57298aSChristoph Hellwig 169cf57298aSChristoph Hellwig for (i = 0; i < nr_iov; i++) { 170cf57298aSChristoph Hellwig qemu_iovec_add(qiov, p, sizes[i]); 171cf57298aSChristoph Hellwig p += sizes[i]; 172cf57298aSChristoph Hellwig } 173cf57298aSChristoph Hellwig 17440a0d7c3SKevin Wolf fail: 175cf57298aSChristoph Hellwig free(sizes); 176cf57298aSChristoph Hellwig return buf; 177cf57298aSChristoph Hellwig } 178cf57298aSChristoph Hellwig 179e3aff4f6Saliguori static int do_read(char *buf, int64_t offset, int count, int *total) 180e3aff4f6Saliguori { 181e3aff4f6Saliguori int ret; 182e3aff4f6Saliguori 183e3aff4f6Saliguori ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9); 18443642b38SDevin Nakamura if (ret < 0) { 185e3aff4f6Saliguori return ret; 18643642b38SDevin Nakamura } 187e3aff4f6Saliguori *total = count; 188e3aff4f6Saliguori return 1; 189e3aff4f6Saliguori } 190e3aff4f6Saliguori 191e3aff4f6Saliguori static int do_write(char *buf, int64_t offset, int count, int *total) 192e3aff4f6Saliguori { 193e3aff4f6Saliguori int ret; 194e3aff4f6Saliguori 195e3aff4f6Saliguori ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9); 19643642b38SDevin Nakamura if (ret < 0) { 197e3aff4f6Saliguori return ret; 19843642b38SDevin Nakamura } 199e3aff4f6Saliguori *total = count; 200e3aff4f6Saliguori return 1; 201e3aff4f6Saliguori } 202e3aff4f6Saliguori 203e3aff4f6Saliguori static int do_pread(char *buf, int64_t offset, int count, int *total) 204e3aff4f6Saliguori { 205e3aff4f6Saliguori *total = bdrv_pread(bs, offset, (uint8_t *)buf, count); 20643642b38SDevin Nakamura if (*total < 0) { 207e3aff4f6Saliguori return *total; 20843642b38SDevin Nakamura } 209e3aff4f6Saliguori return 1; 210e3aff4f6Saliguori } 211e3aff4f6Saliguori 212e3aff4f6Saliguori static int do_pwrite(char *buf, int64_t offset, int count, int *total) 213e3aff4f6Saliguori { 214e3aff4f6Saliguori *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count); 21543642b38SDevin Nakamura if (*total < 0) { 216e3aff4f6Saliguori return *total; 21743642b38SDevin Nakamura } 218e3aff4f6Saliguori return 1; 219e3aff4f6Saliguori } 220e3aff4f6Saliguori 221ca94dbc7SKevin Wolf static int do_load_vmstate(char *buf, int64_t offset, int count, int *total) 222ca94dbc7SKevin Wolf { 223ca94dbc7SKevin Wolf *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count); 22443642b38SDevin Nakamura if (*total < 0) { 225ca94dbc7SKevin Wolf return *total; 22643642b38SDevin Nakamura } 227ca94dbc7SKevin Wolf return 1; 228ca94dbc7SKevin Wolf } 229ca94dbc7SKevin Wolf 230ca94dbc7SKevin Wolf static int do_save_vmstate(char *buf, int64_t offset, int count, int *total) 231ca94dbc7SKevin Wolf { 232ca94dbc7SKevin Wolf *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count); 23343642b38SDevin Nakamura if (*total < 0) { 234ca94dbc7SKevin Wolf return *total; 23543642b38SDevin Nakamura } 236ca94dbc7SKevin Wolf return 1; 237ca94dbc7SKevin Wolf } 238ca94dbc7SKevin Wolf 239e3aff4f6Saliguori #define NOT_DONE 0x7fffffff 240e3aff4f6Saliguori static void aio_rw_done(void *opaque, int ret) 241e3aff4f6Saliguori { 242e3aff4f6Saliguori *(int *)opaque = ret; 243e3aff4f6Saliguori } 244e3aff4f6Saliguori 245e3aff4f6Saliguori static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total) 246e3aff4f6Saliguori { 247e3aff4f6Saliguori BlockDriverAIOCB *acb; 248e3aff4f6Saliguori int async_ret = NOT_DONE; 249e3aff4f6Saliguori 250e3aff4f6Saliguori acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, 251e3aff4f6Saliguori aio_rw_done, &async_ret); 25243642b38SDevin Nakamura if (!acb) { 253e3aff4f6Saliguori return -EIO; 25443642b38SDevin Nakamura } 25543642b38SDevin Nakamura while (async_ret == NOT_DONE) { 256e3aff4f6Saliguori qemu_aio_wait(); 25743642b38SDevin Nakamura } 258e3aff4f6Saliguori 259e3aff4f6Saliguori *total = qiov->size; 260e3aff4f6Saliguori return async_ret < 0 ? async_ret : 1; 261e3aff4f6Saliguori } 262e3aff4f6Saliguori 263e3aff4f6Saliguori static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) 264e3aff4f6Saliguori { 265e3aff4f6Saliguori BlockDriverAIOCB *acb; 266e3aff4f6Saliguori int async_ret = NOT_DONE; 267e3aff4f6Saliguori 268e3aff4f6Saliguori acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, 269e3aff4f6Saliguori aio_rw_done, &async_ret); 27043642b38SDevin Nakamura if (!acb) { 271e3aff4f6Saliguori return -EIO; 27243642b38SDevin Nakamura } 273e3aff4f6Saliguori 27443642b38SDevin Nakamura while (async_ret == NOT_DONE) { 275e3aff4f6Saliguori qemu_aio_wait(); 27643642b38SDevin Nakamura } 277e3aff4f6Saliguori 2787e9bbc9fSaliguori *total = qiov->size; 279e3aff4f6Saliguori return async_ret < 0 ? async_ret : 1; 280e3aff4f6Saliguori } 281e3aff4f6Saliguori 282776cbbbdSKevin Wolf struct multiwrite_async_ret { 283776cbbbdSKevin Wolf int num_done; 284776cbbbdSKevin Wolf int error; 285776cbbbdSKevin Wolf }; 286776cbbbdSKevin Wolf 287776cbbbdSKevin Wolf static void multiwrite_cb(void *opaque, int ret) 288776cbbbdSKevin Wolf { 289776cbbbdSKevin Wolf struct multiwrite_async_ret *async_ret = opaque; 290776cbbbdSKevin Wolf 291776cbbbdSKevin Wolf async_ret->num_done++; 292776cbbbdSKevin Wolf if (ret < 0) { 293776cbbbdSKevin Wolf async_ret->error = ret; 294776cbbbdSKevin Wolf } 295776cbbbdSKevin Wolf } 296776cbbbdSKevin Wolf 297776cbbbdSKevin Wolf static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total) 298776cbbbdSKevin Wolf { 299776cbbbdSKevin Wolf int i, ret; 300776cbbbdSKevin Wolf struct multiwrite_async_ret async_ret = { 301776cbbbdSKevin Wolf .num_done = 0, 302776cbbbdSKevin Wolf .error = 0, 303776cbbbdSKevin Wolf }; 304776cbbbdSKevin Wolf 305776cbbbdSKevin Wolf *total = 0; 306776cbbbdSKevin Wolf for (i = 0; i < num_reqs; i++) { 307776cbbbdSKevin Wolf reqs[i].cb = multiwrite_cb; 308776cbbbdSKevin Wolf reqs[i].opaque = &async_ret; 309776cbbbdSKevin Wolf *total += reqs[i].qiov->size; 310776cbbbdSKevin Wolf } 311776cbbbdSKevin Wolf 312776cbbbdSKevin Wolf ret = bdrv_aio_multiwrite(bs, reqs, num_reqs); 313776cbbbdSKevin Wolf if (ret < 0) { 314776cbbbdSKevin Wolf return ret; 315776cbbbdSKevin Wolf } 316776cbbbdSKevin Wolf 317776cbbbdSKevin Wolf while (async_ret.num_done < num_reqs) { 318776cbbbdSKevin Wolf qemu_aio_wait(); 319776cbbbdSKevin Wolf } 320776cbbbdSKevin Wolf 321776cbbbdSKevin Wolf return async_ret.error < 0 ? async_ret.error : 1; 322776cbbbdSKevin Wolf } 323e3aff4f6Saliguori 32443642b38SDevin Nakamura static void read_help(void) 325e3aff4f6Saliguori { 326e3aff4f6Saliguori printf( 327e3aff4f6Saliguori "\n" 328e3aff4f6Saliguori " reads a range of bytes from the given offset\n" 329e3aff4f6Saliguori "\n" 330e3aff4f6Saliguori " Example:\n" 331e3aff4f6Saliguori " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 332e3aff4f6Saliguori "\n" 333e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 334e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 335ca94dbc7SKevin Wolf " -b, -- read from the VM state rather than the virtual disk\n" 336d9654a58SKevin Wolf " -C, -- report statistics in a machine parsable format\n" 337d9654a58SKevin Wolf " -l, -- length for pattern verification (only with -P)\n" 338e3aff4f6Saliguori " -p, -- use bdrv_pread to read the file\n" 339c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 340095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 341d9654a58SKevin Wolf " -s, -- start offset for pattern verification (only with -P)\n" 342d9654a58SKevin Wolf " -v, -- dump buffer to standard output\n" 343e3aff4f6Saliguori "\n"); 344e3aff4f6Saliguori } 345e3aff4f6Saliguori 34622a2bdcbSBlue Swirl static int read_f(int argc, char **argv); 34722a2bdcbSBlue Swirl 34822a2bdcbSBlue Swirl static const cmdinfo_t read_cmd = { 34922a2bdcbSBlue Swirl .name = "read", 35022a2bdcbSBlue Swirl .altname = "r", 35122a2bdcbSBlue Swirl .cfunc = read_f, 35222a2bdcbSBlue Swirl .argmin = 2, 35322a2bdcbSBlue Swirl .argmax = -1, 35422a2bdcbSBlue Swirl .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", 35522a2bdcbSBlue Swirl .oneline = "reads a number of bytes at a specified offset", 35622a2bdcbSBlue Swirl .help = read_help, 35722a2bdcbSBlue Swirl }; 35822a2bdcbSBlue Swirl 35943642b38SDevin Nakamura static int read_f(int argc, char **argv) 360e3aff4f6Saliguori { 361e3aff4f6Saliguori struct timeval t1, t2; 362e3aff4f6Saliguori int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 363ca94dbc7SKevin Wolf int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; 364e3aff4f6Saliguori int c, cnt; 365e3aff4f6Saliguori char *buf; 366e3aff4f6Saliguori int64_t offset; 367d4ec5228SPaul Brook int count; 368d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 369d4ec5228SPaul Brook int total = 0; 370d9654a58SKevin Wolf int pattern = 0, pattern_offset = 0, pattern_count = 0; 371e3aff4f6Saliguori 372ca94dbc7SKevin Wolf while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { 373e3aff4f6Saliguori switch (c) { 374ca94dbc7SKevin Wolf case 'b': 375ca94dbc7SKevin Wolf bflag = 1; 376ca94dbc7SKevin Wolf break; 377e3aff4f6Saliguori case 'C': 378e3aff4f6Saliguori Cflag = 1; 379e3aff4f6Saliguori break; 380d9654a58SKevin Wolf case 'l': 381d9654a58SKevin Wolf lflag = 1; 382d9654a58SKevin Wolf pattern_count = cvtnum(optarg); 383d9654a58SKevin Wolf if (pattern_count < 0) { 384d9654a58SKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 385d9654a58SKevin Wolf return 0; 386d9654a58SKevin Wolf } 387d9654a58SKevin Wolf break; 388e3aff4f6Saliguori case 'p': 389e3aff4f6Saliguori pflag = 1; 390e3aff4f6Saliguori break; 391c48101aeSaliguori case 'P': 392c48101aeSaliguori Pflag = 1; 393cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 39443642b38SDevin Nakamura if (pattern < 0) { 395cf070d7eSChristoph Hellwig return 0; 39643642b38SDevin Nakamura } 397c48101aeSaliguori break; 398e3aff4f6Saliguori case 'q': 399e3aff4f6Saliguori qflag = 1; 400e3aff4f6Saliguori break; 401d9654a58SKevin Wolf case 's': 402d9654a58SKevin Wolf sflag = 1; 403d9654a58SKevin Wolf pattern_offset = cvtnum(optarg); 404d9654a58SKevin Wolf if (pattern_offset < 0) { 405d9654a58SKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 406d9654a58SKevin Wolf return 0; 407d9654a58SKevin Wolf } 408d9654a58SKevin Wolf break; 409e3aff4f6Saliguori case 'v': 410e3aff4f6Saliguori vflag = 1; 411e3aff4f6Saliguori break; 412e3aff4f6Saliguori default: 413e3aff4f6Saliguori return command_usage(&read_cmd); 414e3aff4f6Saliguori } 415e3aff4f6Saliguori } 416e3aff4f6Saliguori 41743642b38SDevin Nakamura if (optind != argc - 2) { 418e3aff4f6Saliguori return command_usage(&read_cmd); 41943642b38SDevin Nakamura } 420e3aff4f6Saliguori 421ca94dbc7SKevin Wolf if (bflag && pflag) { 422ca94dbc7SKevin Wolf printf("-b and -p cannot be specified at the same time\n"); 423ca94dbc7SKevin Wolf return 0; 424ca94dbc7SKevin Wolf } 425ca94dbc7SKevin Wolf 426e3aff4f6Saliguori offset = cvtnum(argv[optind]); 427e3aff4f6Saliguori if (offset < 0) { 428e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 429e3aff4f6Saliguori return 0; 430e3aff4f6Saliguori } 431e3aff4f6Saliguori 432e3aff4f6Saliguori optind++; 433e3aff4f6Saliguori count = cvtnum(argv[optind]); 434e3aff4f6Saliguori if (count < 0) { 435e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 436e3aff4f6Saliguori return 0; 437e3aff4f6Saliguori } 438e3aff4f6Saliguori 439d9654a58SKevin Wolf if (!Pflag && (lflag || sflag)) { 440d9654a58SKevin Wolf return command_usage(&read_cmd); 441d9654a58SKevin Wolf } 442d9654a58SKevin Wolf 443d9654a58SKevin Wolf if (!lflag) { 444d9654a58SKevin Wolf pattern_count = count - pattern_offset; 445d9654a58SKevin Wolf } 446d9654a58SKevin Wolf 447d9654a58SKevin Wolf if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 448d9654a58SKevin Wolf printf("pattern verfication range exceeds end of read data\n"); 449d9654a58SKevin Wolf return 0; 450d9654a58SKevin Wolf } 451d9654a58SKevin Wolf 4525afc8b3dSDevin Nakamura if (!pflag) { 453e3aff4f6Saliguori if (offset & 0x1ff) { 4540bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 4550bfcd599SBlue Swirl offset); 456e3aff4f6Saliguori return 0; 45743642b38SDevin Nakamura } 458e3aff4f6Saliguori if (count & 0x1ff) { 459e3aff4f6Saliguori printf("count %d is not sector aligned\n", 460e3aff4f6Saliguori count); 461e3aff4f6Saliguori return 0; 462e3aff4f6Saliguori } 4635afc8b3dSDevin Nakamura } 464e3aff4f6Saliguori 465e3aff4f6Saliguori buf = qemu_io_alloc(count, 0xab); 466e3aff4f6Saliguori 467e3aff4f6Saliguori gettimeofday(&t1, NULL); 46843642b38SDevin Nakamura if (pflag) { 469e3aff4f6Saliguori cnt = do_pread(buf, offset, count, &total); 47043642b38SDevin Nakamura } else if (bflag) { 471ca94dbc7SKevin Wolf cnt = do_load_vmstate(buf, offset, count, &total); 47243642b38SDevin Nakamura } else { 473e3aff4f6Saliguori cnt = do_read(buf, offset, count, &total); 47443642b38SDevin Nakamura } 475e3aff4f6Saliguori gettimeofday(&t2, NULL); 476e3aff4f6Saliguori 477e3aff4f6Saliguori if (cnt < 0) { 478e3aff4f6Saliguori printf("read failed: %s\n", strerror(-cnt)); 4797d8abfcbSKevin Wolf goto out; 480e3aff4f6Saliguori } 481e3aff4f6Saliguori 482c48101aeSaliguori if (Pflag) { 483d9654a58SKevin Wolf void *cmp_buf = malloc(pattern_count); 484d9654a58SKevin Wolf memset(cmp_buf, pattern, pattern_count); 485d9654a58SKevin Wolf if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 4860bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 4870bfcd599SBlue Swirl PRId64 ", %d bytes\n", 4880bfcd599SBlue Swirl offset + pattern_offset, pattern_count); 489c48101aeSaliguori } 490c48101aeSaliguori free(cmp_buf); 491c48101aeSaliguori } 492c48101aeSaliguori 49343642b38SDevin Nakamura if (qflag) { 4947d8abfcbSKevin Wolf goto out; 49543642b38SDevin Nakamura } 496e3aff4f6Saliguori 49743642b38SDevin Nakamura if (vflag) { 498e3aff4f6Saliguori dump_buffer(buf, offset, count); 49943642b38SDevin Nakamura } 500e3aff4f6Saliguori 501e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 502e3aff4f6Saliguori t2 = tsub(t2, t1); 503e3aff4f6Saliguori print_report("read", &t2, offset, count, total, cnt, Cflag); 504e3aff4f6Saliguori 5057d8abfcbSKevin Wolf out: 506e3aff4f6Saliguori qemu_io_free(buf); 507e3aff4f6Saliguori 508e3aff4f6Saliguori return 0; 509e3aff4f6Saliguori } 510e3aff4f6Saliguori 51143642b38SDevin Nakamura static void readv_help(void) 512e3aff4f6Saliguori { 513e3aff4f6Saliguori printf( 514e3aff4f6Saliguori "\n" 515e3aff4f6Saliguori " reads a range of bytes from the given offset into multiple buffers\n" 516e3aff4f6Saliguori "\n" 517e3aff4f6Saliguori " Example:\n" 518e3aff4f6Saliguori " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 519e3aff4f6Saliguori "\n" 520e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 521e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 522e3aff4f6Saliguori " Uses multiple iovec buffers if more than one byte range is specified.\n" 523e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 524c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 525e3aff4f6Saliguori " -v, -- dump buffer to standard output\n" 526095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 527e3aff4f6Saliguori "\n"); 528e3aff4f6Saliguori } 529e3aff4f6Saliguori 53022a2bdcbSBlue Swirl static int readv_f(int argc, char **argv); 53122a2bdcbSBlue Swirl 53222a2bdcbSBlue Swirl static const cmdinfo_t readv_cmd = { 53322a2bdcbSBlue Swirl .name = "readv", 53422a2bdcbSBlue Swirl .cfunc = readv_f, 53522a2bdcbSBlue Swirl .argmin = 2, 53622a2bdcbSBlue Swirl .argmax = -1, 53722a2bdcbSBlue Swirl .args = "[-Cqv] [-P pattern ] off len [len..]", 53822a2bdcbSBlue Swirl .oneline = "reads a number of bytes at a specified offset", 53922a2bdcbSBlue Swirl .help = readv_help, 54022a2bdcbSBlue Swirl }; 54122a2bdcbSBlue Swirl 54243642b38SDevin Nakamura static int readv_f(int argc, char **argv) 543e3aff4f6Saliguori { 544e3aff4f6Saliguori struct timeval t1, t2; 545e3aff4f6Saliguori int Cflag = 0, qflag = 0, vflag = 0; 546e3aff4f6Saliguori int c, cnt; 547cf57298aSChristoph Hellwig char *buf; 548e3aff4f6Saliguori int64_t offset; 5496474bd69SBlue Swirl /* Some compilers get confused and warn if this is not initialized. */ 5506474bd69SBlue Swirl int total = 0; 551cf57298aSChristoph Hellwig int nr_iov; 552e3aff4f6Saliguori QEMUIOVector qiov; 553c48101aeSaliguori int pattern = 0; 554c48101aeSaliguori int Pflag = 0; 555e3aff4f6Saliguori 556c48101aeSaliguori while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 557e3aff4f6Saliguori switch (c) { 558e3aff4f6Saliguori case 'C': 559e3aff4f6Saliguori Cflag = 1; 560e3aff4f6Saliguori break; 561c48101aeSaliguori case 'P': 562c48101aeSaliguori Pflag = 1; 563cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 56443642b38SDevin Nakamura if (pattern < 0) { 565cf070d7eSChristoph Hellwig return 0; 56643642b38SDevin Nakamura } 567c48101aeSaliguori break; 568e3aff4f6Saliguori case 'q': 569e3aff4f6Saliguori qflag = 1; 570e3aff4f6Saliguori break; 571e3aff4f6Saliguori case 'v': 572e3aff4f6Saliguori vflag = 1; 573e3aff4f6Saliguori break; 574e3aff4f6Saliguori default: 575e3aff4f6Saliguori return command_usage(&readv_cmd); 576e3aff4f6Saliguori } 577e3aff4f6Saliguori } 578e3aff4f6Saliguori 57943642b38SDevin Nakamura if (optind > argc - 2) { 580e3aff4f6Saliguori return command_usage(&readv_cmd); 58143642b38SDevin Nakamura } 582e3aff4f6Saliguori 583e3aff4f6Saliguori 584e3aff4f6Saliguori offset = cvtnum(argv[optind]); 585e3aff4f6Saliguori if (offset < 0) { 586e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 587e3aff4f6Saliguori return 0; 588e3aff4f6Saliguori } 589e3aff4f6Saliguori optind++; 590e3aff4f6Saliguori 591e3aff4f6Saliguori if (offset & 0x1ff) { 5920bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 5930bfcd599SBlue Swirl offset); 594e3aff4f6Saliguori return 0; 595e3aff4f6Saliguori } 596e3aff4f6Saliguori 597e3aff4f6Saliguori nr_iov = argc - optind; 598cf57298aSChristoph Hellwig buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); 599e3aff4f6Saliguori 600e3aff4f6Saliguori gettimeofday(&t1, NULL); 601e3aff4f6Saliguori cnt = do_aio_readv(&qiov, offset, &total); 602e3aff4f6Saliguori gettimeofday(&t2, NULL); 603e3aff4f6Saliguori 604e3aff4f6Saliguori if (cnt < 0) { 605e3aff4f6Saliguori printf("readv failed: %s\n", strerror(-cnt)); 6067d8abfcbSKevin Wolf goto out; 607e3aff4f6Saliguori } 608e3aff4f6Saliguori 609c48101aeSaliguori if (Pflag) { 610cf57298aSChristoph Hellwig void *cmp_buf = malloc(qiov.size); 611cf57298aSChristoph Hellwig memset(cmp_buf, pattern, qiov.size); 612cf57298aSChristoph Hellwig if (memcmp(buf, cmp_buf, qiov.size)) { 6130bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 61443642b38SDevin Nakamura PRId64 ", %zd bytes\n", offset, qiov.size); 615c48101aeSaliguori } 616c48101aeSaliguori free(cmp_buf); 617c48101aeSaliguori } 618c48101aeSaliguori 61943642b38SDevin Nakamura if (qflag) { 6207d8abfcbSKevin Wolf goto out; 62143642b38SDevin Nakamura } 622e3aff4f6Saliguori 62343642b38SDevin Nakamura if (vflag) { 624e3aff4f6Saliguori dump_buffer(buf, offset, qiov.size); 62543642b38SDevin Nakamura } 626e3aff4f6Saliguori 627e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 628e3aff4f6Saliguori t2 = tsub(t2, t1); 629e3aff4f6Saliguori print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 630e3aff4f6Saliguori 6317d8abfcbSKevin Wolf out: 632e3aff4f6Saliguori qemu_io_free(buf); 633e3aff4f6Saliguori return 0; 634e3aff4f6Saliguori } 635e3aff4f6Saliguori 63643642b38SDevin Nakamura static void write_help(void) 637e3aff4f6Saliguori { 638e3aff4f6Saliguori printf( 639e3aff4f6Saliguori "\n" 640e3aff4f6Saliguori " writes a range of bytes from the given offset\n" 641e3aff4f6Saliguori "\n" 642e3aff4f6Saliguori " Example:\n" 643e3aff4f6Saliguori " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 644e3aff4f6Saliguori "\n" 645e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 646e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 647ca94dbc7SKevin Wolf " -b, -- write to the VM state rather than the virtual disk\n" 648e3aff4f6Saliguori " -p, -- use bdrv_pwrite to write the file\n" 649e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 650e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 651095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 652e3aff4f6Saliguori "\n"); 653e3aff4f6Saliguori } 654e3aff4f6Saliguori 65522a2bdcbSBlue Swirl static int write_f(int argc, char **argv); 65622a2bdcbSBlue Swirl 65722a2bdcbSBlue Swirl static const cmdinfo_t write_cmd = { 65822a2bdcbSBlue Swirl .name = "write", 65922a2bdcbSBlue Swirl .altname = "w", 66022a2bdcbSBlue Swirl .cfunc = write_f, 66122a2bdcbSBlue Swirl .argmin = 2, 66222a2bdcbSBlue Swirl .argmax = -1, 66322a2bdcbSBlue Swirl .args = "[-abCpq] [-P pattern ] off len", 66422a2bdcbSBlue Swirl .oneline = "writes a number of bytes at a specified offset", 66522a2bdcbSBlue Swirl .help = write_help, 66622a2bdcbSBlue Swirl }; 66722a2bdcbSBlue Swirl 66843642b38SDevin Nakamura static int write_f(int argc, char **argv) 669e3aff4f6Saliguori { 670e3aff4f6Saliguori struct timeval t1, t2; 671ca94dbc7SKevin Wolf int Cflag = 0, pflag = 0, qflag = 0, bflag = 0; 672e3aff4f6Saliguori int c, cnt; 673e3aff4f6Saliguori char *buf; 674e3aff4f6Saliguori int64_t offset; 675d4ec5228SPaul Brook int count; 676d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 677d4ec5228SPaul Brook int total = 0; 678e3aff4f6Saliguori int pattern = 0xcd; 679e3aff4f6Saliguori 680ca94dbc7SKevin Wolf while ((c = getopt(argc, argv, "bCpP:q")) != EOF) { 681e3aff4f6Saliguori switch (c) { 682ca94dbc7SKevin Wolf case 'b': 683ca94dbc7SKevin Wolf bflag = 1; 684ca94dbc7SKevin Wolf break; 685e3aff4f6Saliguori case 'C': 686e3aff4f6Saliguori Cflag = 1; 687e3aff4f6Saliguori break; 688e3aff4f6Saliguori case 'p': 689e3aff4f6Saliguori pflag = 1; 690e3aff4f6Saliguori break; 691e3aff4f6Saliguori case 'P': 692cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 69343642b38SDevin Nakamura if (pattern < 0) { 694cf070d7eSChristoph Hellwig return 0; 69543642b38SDevin Nakamura } 696e3aff4f6Saliguori break; 697e3aff4f6Saliguori case 'q': 698e3aff4f6Saliguori qflag = 1; 699e3aff4f6Saliguori break; 700e3aff4f6Saliguori default: 701e3aff4f6Saliguori return command_usage(&write_cmd); 702e3aff4f6Saliguori } 703e3aff4f6Saliguori } 704e3aff4f6Saliguori 70543642b38SDevin Nakamura if (optind != argc - 2) { 706e3aff4f6Saliguori return command_usage(&write_cmd); 70743642b38SDevin Nakamura } 708e3aff4f6Saliguori 709ca94dbc7SKevin Wolf if (bflag && pflag) { 710ca94dbc7SKevin Wolf printf("-b and -p cannot be specified at the same time\n"); 711ca94dbc7SKevin Wolf return 0; 712ca94dbc7SKevin Wolf } 713ca94dbc7SKevin Wolf 714e3aff4f6Saliguori offset = cvtnum(argv[optind]); 715e3aff4f6Saliguori if (offset < 0) { 716e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 717e3aff4f6Saliguori return 0; 718e3aff4f6Saliguori } 719e3aff4f6Saliguori 720e3aff4f6Saliguori optind++; 721e3aff4f6Saliguori count = cvtnum(argv[optind]); 722e3aff4f6Saliguori if (count < 0) { 723e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 724e3aff4f6Saliguori return 0; 725e3aff4f6Saliguori } 726e3aff4f6Saliguori 727e3aff4f6Saliguori if (!pflag) { 728e3aff4f6Saliguori if (offset & 0x1ff) { 7290bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 7300bfcd599SBlue Swirl offset); 731e3aff4f6Saliguori return 0; 732e3aff4f6Saliguori } 733e3aff4f6Saliguori 734e3aff4f6Saliguori if (count & 0x1ff) { 735e3aff4f6Saliguori printf("count %d is not sector aligned\n", 736e3aff4f6Saliguori count); 737e3aff4f6Saliguori return 0; 738e3aff4f6Saliguori } 739e3aff4f6Saliguori } 740e3aff4f6Saliguori 741e3aff4f6Saliguori buf = qemu_io_alloc(count, pattern); 742e3aff4f6Saliguori 743e3aff4f6Saliguori gettimeofday(&t1, NULL); 74443642b38SDevin Nakamura if (pflag) { 745e3aff4f6Saliguori cnt = do_pwrite(buf, offset, count, &total); 74643642b38SDevin Nakamura } else if (bflag) { 747ca94dbc7SKevin Wolf cnt = do_save_vmstate(buf, offset, count, &total); 74843642b38SDevin Nakamura } else { 749e3aff4f6Saliguori cnt = do_write(buf, offset, count, &total); 75043642b38SDevin Nakamura } 751e3aff4f6Saliguori gettimeofday(&t2, NULL); 752e3aff4f6Saliguori 753e3aff4f6Saliguori if (cnt < 0) { 754e3aff4f6Saliguori printf("write failed: %s\n", strerror(-cnt)); 7557d8abfcbSKevin Wolf goto out; 756e3aff4f6Saliguori } 757e3aff4f6Saliguori 75843642b38SDevin Nakamura if (qflag) { 7597d8abfcbSKevin Wolf goto out; 76043642b38SDevin Nakamura } 761e3aff4f6Saliguori 762e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 763e3aff4f6Saliguori t2 = tsub(t2, t1); 764e3aff4f6Saliguori print_report("wrote", &t2, offset, count, total, cnt, Cflag); 765e3aff4f6Saliguori 7667d8abfcbSKevin Wolf out: 767e3aff4f6Saliguori qemu_io_free(buf); 768e3aff4f6Saliguori 769e3aff4f6Saliguori return 0; 770e3aff4f6Saliguori } 771e3aff4f6Saliguori 772e3aff4f6Saliguori static void 773e3aff4f6Saliguori writev_help(void) 774e3aff4f6Saliguori { 775e3aff4f6Saliguori printf( 776e3aff4f6Saliguori "\n" 777e3aff4f6Saliguori " writes a range of bytes from the given offset source from multiple buffers\n" 778e3aff4f6Saliguori "\n" 779e3aff4f6Saliguori " Example:\n" 780e3aff4f6Saliguori " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 781e3aff4f6Saliguori "\n" 782e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 783e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 784e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 785e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 786095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 787e3aff4f6Saliguori "\n"); 788e3aff4f6Saliguori } 789e3aff4f6Saliguori 79022a2bdcbSBlue Swirl static int writev_f(int argc, char **argv); 79122a2bdcbSBlue Swirl 79222a2bdcbSBlue Swirl static const cmdinfo_t writev_cmd = { 79322a2bdcbSBlue Swirl .name = "writev", 79422a2bdcbSBlue Swirl .cfunc = writev_f, 79522a2bdcbSBlue Swirl .argmin = 2, 79622a2bdcbSBlue Swirl .argmax = -1, 79722a2bdcbSBlue Swirl .args = "[-Cq] [-P pattern ] off len [len..]", 79822a2bdcbSBlue Swirl .oneline = "writes a number of bytes at a specified offset", 79922a2bdcbSBlue Swirl .help = writev_help, 80022a2bdcbSBlue Swirl }; 80122a2bdcbSBlue Swirl 80243642b38SDevin Nakamura static int writev_f(int argc, char **argv) 803e3aff4f6Saliguori { 804e3aff4f6Saliguori struct timeval t1, t2; 805e3aff4f6Saliguori int Cflag = 0, qflag = 0; 806e3aff4f6Saliguori int c, cnt; 807cf57298aSChristoph Hellwig char *buf; 808e3aff4f6Saliguori int64_t offset; 8096474bd69SBlue Swirl /* Some compilers get confused and warn if this is not initialized. */ 8106474bd69SBlue Swirl int total = 0; 811cf57298aSChristoph Hellwig int nr_iov; 812e3aff4f6Saliguori int pattern = 0xcd; 813e3aff4f6Saliguori QEMUIOVector qiov; 814e3aff4f6Saliguori 815e3aff4f6Saliguori while ((c = getopt(argc, argv, "CqP:")) != EOF) { 816e3aff4f6Saliguori switch (c) { 817e3aff4f6Saliguori case 'C': 818e3aff4f6Saliguori Cflag = 1; 819e3aff4f6Saliguori break; 820e3aff4f6Saliguori case 'q': 821e3aff4f6Saliguori qflag = 1; 822e3aff4f6Saliguori break; 823e3aff4f6Saliguori case 'P': 824cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 82543642b38SDevin Nakamura if (pattern < 0) { 826cf070d7eSChristoph Hellwig return 0; 82743642b38SDevin Nakamura } 828e3aff4f6Saliguori break; 829e3aff4f6Saliguori default: 830e3aff4f6Saliguori return command_usage(&writev_cmd); 831e3aff4f6Saliguori } 832e3aff4f6Saliguori } 833e3aff4f6Saliguori 83443642b38SDevin Nakamura if (optind > argc - 2) { 835e3aff4f6Saliguori return command_usage(&writev_cmd); 83643642b38SDevin Nakamura } 837e3aff4f6Saliguori 838e3aff4f6Saliguori offset = cvtnum(argv[optind]); 839e3aff4f6Saliguori if (offset < 0) { 840e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 841e3aff4f6Saliguori return 0; 842e3aff4f6Saliguori } 843e3aff4f6Saliguori optind++; 844e3aff4f6Saliguori 845e3aff4f6Saliguori if (offset & 0x1ff) { 8460bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 8470bfcd599SBlue Swirl offset); 848e3aff4f6Saliguori return 0; 849e3aff4f6Saliguori } 850e3aff4f6Saliguori 851e3aff4f6Saliguori nr_iov = argc - optind; 852cf57298aSChristoph Hellwig buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); 853e3aff4f6Saliguori 854e3aff4f6Saliguori gettimeofday(&t1, NULL); 855e3aff4f6Saliguori cnt = do_aio_writev(&qiov, offset, &total); 856e3aff4f6Saliguori gettimeofday(&t2, NULL); 857e3aff4f6Saliguori 858e3aff4f6Saliguori if (cnt < 0) { 859e3aff4f6Saliguori printf("writev failed: %s\n", strerror(-cnt)); 8607d8abfcbSKevin Wolf goto out; 861e3aff4f6Saliguori } 862e3aff4f6Saliguori 86343642b38SDevin Nakamura if (qflag) { 8647d8abfcbSKevin Wolf goto out; 86543642b38SDevin Nakamura } 866e3aff4f6Saliguori 867e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 868e3aff4f6Saliguori t2 = tsub(t2, t1); 869e3aff4f6Saliguori print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 8707d8abfcbSKevin Wolf out: 871e3aff4f6Saliguori qemu_io_free(buf); 872e3aff4f6Saliguori return 0; 873e3aff4f6Saliguori } 874e3aff4f6Saliguori 87543642b38SDevin Nakamura static void multiwrite_help(void) 876776cbbbdSKevin Wolf { 877776cbbbdSKevin Wolf printf( 878776cbbbdSKevin Wolf "\n" 879776cbbbdSKevin Wolf " writes a range of bytes from the given offset source from multiple buffers,\n" 880776cbbbdSKevin Wolf " in a batch of requests that may be merged by qemu\n" 881776cbbbdSKevin Wolf "\n" 882776cbbbdSKevin Wolf " Example:\n" 883776cbbbdSKevin Wolf " 'multiwrite 512 1k 1k ; 4k 1k'\n" 884776cbbbdSKevin Wolf " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n" 885776cbbbdSKevin Wolf "\n" 886776cbbbdSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n" 887776cbbbdSKevin Wolf " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n" 888776cbbbdSKevin Wolf " by one for each request contained in the multiwrite command.\n" 889776cbbbdSKevin Wolf " -P, -- use different pattern to fill file\n" 890776cbbbdSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 891776cbbbdSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 892776cbbbdSKevin Wolf "\n"); 893776cbbbdSKevin Wolf } 894776cbbbdSKevin Wolf 895776cbbbdSKevin Wolf static int multiwrite_f(int argc, char **argv); 896776cbbbdSKevin Wolf 897776cbbbdSKevin Wolf static const cmdinfo_t multiwrite_cmd = { 898776cbbbdSKevin Wolf .name = "multiwrite", 899776cbbbdSKevin Wolf .cfunc = multiwrite_f, 900776cbbbdSKevin Wolf .argmin = 2, 901776cbbbdSKevin Wolf .argmax = -1, 902776cbbbdSKevin Wolf .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]", 903776cbbbdSKevin Wolf .oneline = "issues multiple write requests at once", 904776cbbbdSKevin Wolf .help = multiwrite_help, 905776cbbbdSKevin Wolf }; 906776cbbbdSKevin Wolf 90743642b38SDevin Nakamura static int multiwrite_f(int argc, char **argv) 908776cbbbdSKevin Wolf { 909776cbbbdSKevin Wolf struct timeval t1, t2; 910776cbbbdSKevin Wolf int Cflag = 0, qflag = 0; 911776cbbbdSKevin Wolf int c, cnt; 912776cbbbdSKevin Wolf char **buf; 913776cbbbdSKevin Wolf int64_t offset, first_offset = 0; 914776cbbbdSKevin Wolf /* Some compilers get confused and warn if this is not initialized. */ 915776cbbbdSKevin Wolf int total = 0; 916776cbbbdSKevin Wolf int nr_iov; 917776cbbbdSKevin Wolf int nr_reqs; 918776cbbbdSKevin Wolf int pattern = 0xcd; 919776cbbbdSKevin Wolf QEMUIOVector *qiovs; 920776cbbbdSKevin Wolf int i; 921776cbbbdSKevin Wolf BlockRequest *reqs; 922776cbbbdSKevin Wolf 923776cbbbdSKevin Wolf while ((c = getopt(argc, argv, "CqP:")) != EOF) { 924776cbbbdSKevin Wolf switch (c) { 925776cbbbdSKevin Wolf case 'C': 926776cbbbdSKevin Wolf Cflag = 1; 927776cbbbdSKevin Wolf break; 928776cbbbdSKevin Wolf case 'q': 929776cbbbdSKevin Wolf qflag = 1; 930776cbbbdSKevin Wolf break; 931776cbbbdSKevin Wolf case 'P': 932776cbbbdSKevin Wolf pattern = parse_pattern(optarg); 93343642b38SDevin Nakamura if (pattern < 0) { 934776cbbbdSKevin Wolf return 0; 93543642b38SDevin Nakamura } 936776cbbbdSKevin Wolf break; 937776cbbbdSKevin Wolf default: 938776cbbbdSKevin Wolf return command_usage(&writev_cmd); 939776cbbbdSKevin Wolf } 940776cbbbdSKevin Wolf } 941776cbbbdSKevin Wolf 94243642b38SDevin Nakamura if (optind > argc - 2) { 943776cbbbdSKevin Wolf return command_usage(&writev_cmd); 94443642b38SDevin Nakamura } 945776cbbbdSKevin Wolf 946776cbbbdSKevin Wolf nr_reqs = 1; 947776cbbbdSKevin Wolf for (i = optind; i < argc; i++) { 948776cbbbdSKevin Wolf if (!strcmp(argv[i], ";")) { 949776cbbbdSKevin Wolf nr_reqs++; 950776cbbbdSKevin Wolf } 951776cbbbdSKevin Wolf } 952776cbbbdSKevin Wolf 9537267c094SAnthony Liguori reqs = g_malloc(nr_reqs * sizeof(*reqs)); 9547267c094SAnthony Liguori buf = g_malloc(nr_reqs * sizeof(*buf)); 9557267c094SAnthony Liguori qiovs = g_malloc(nr_reqs * sizeof(*qiovs)); 956776cbbbdSKevin Wolf 957776cbbbdSKevin Wolf for (i = 0; i < nr_reqs; i++) { 958776cbbbdSKevin Wolf int j; 959776cbbbdSKevin Wolf 960776cbbbdSKevin Wolf /* Read the offset of the request */ 961776cbbbdSKevin Wolf offset = cvtnum(argv[optind]); 962776cbbbdSKevin Wolf if (offset < 0) { 963776cbbbdSKevin Wolf printf("non-numeric offset argument -- %s\n", argv[optind]); 964776cbbbdSKevin Wolf return 0; 965776cbbbdSKevin Wolf } 966776cbbbdSKevin Wolf optind++; 967776cbbbdSKevin Wolf 968776cbbbdSKevin Wolf if (offset & 0x1ff) { 969776cbbbdSKevin Wolf printf("offset %lld is not sector aligned\n", 970776cbbbdSKevin Wolf (long long)offset); 971776cbbbdSKevin Wolf return 0; 972776cbbbdSKevin Wolf } 973776cbbbdSKevin Wolf 974776cbbbdSKevin Wolf if (i == 0) { 975776cbbbdSKevin Wolf first_offset = offset; 976776cbbbdSKevin Wolf } 977776cbbbdSKevin Wolf 978776cbbbdSKevin Wolf /* Read lengths for qiov entries */ 979776cbbbdSKevin Wolf for (j = optind; j < argc; j++) { 980776cbbbdSKevin Wolf if (!strcmp(argv[j], ";")) { 981776cbbbdSKevin Wolf break; 982776cbbbdSKevin Wolf } 983776cbbbdSKevin Wolf } 984776cbbbdSKevin Wolf 985776cbbbdSKevin Wolf nr_iov = j - optind; 986776cbbbdSKevin Wolf 987776cbbbdSKevin Wolf /* Build request */ 988776cbbbdSKevin Wolf reqs[i].qiov = &qiovs[i]; 989776cbbbdSKevin Wolf buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern); 990776cbbbdSKevin Wolf reqs[i].sector = offset >> 9; 991776cbbbdSKevin Wolf reqs[i].nb_sectors = reqs[i].qiov->size >> 9; 992776cbbbdSKevin Wolf 993776cbbbdSKevin Wolf optind = j + 1; 994776cbbbdSKevin Wolf 995776cbbbdSKevin Wolf pattern++; 996776cbbbdSKevin Wolf } 997776cbbbdSKevin Wolf 998776cbbbdSKevin Wolf gettimeofday(&t1, NULL); 999776cbbbdSKevin Wolf cnt = do_aio_multiwrite(reqs, nr_reqs, &total); 1000776cbbbdSKevin Wolf gettimeofday(&t2, NULL); 1001776cbbbdSKevin Wolf 1002776cbbbdSKevin Wolf if (cnt < 0) { 1003776cbbbdSKevin Wolf printf("aio_multiwrite failed: %s\n", strerror(-cnt)); 1004776cbbbdSKevin Wolf goto out; 1005776cbbbdSKevin Wolf } 1006776cbbbdSKevin Wolf 100743642b38SDevin Nakamura if (qflag) { 1008776cbbbdSKevin Wolf goto out; 100943642b38SDevin Nakamura } 1010776cbbbdSKevin Wolf 1011776cbbbdSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 1012776cbbbdSKevin Wolf t2 = tsub(t2, t1); 1013776cbbbdSKevin Wolf print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); 1014776cbbbdSKevin Wolf out: 1015776cbbbdSKevin Wolf for (i = 0; i < nr_reqs; i++) { 1016776cbbbdSKevin Wolf qemu_io_free(buf[i]); 1017776cbbbdSKevin Wolf qemu_iovec_destroy(&qiovs[i]); 1018776cbbbdSKevin Wolf } 10197267c094SAnthony Liguori g_free(buf); 10207267c094SAnthony Liguori g_free(reqs); 10217267c094SAnthony Liguori g_free(qiovs); 1022776cbbbdSKevin Wolf return 0; 1023776cbbbdSKevin Wolf } 1024776cbbbdSKevin Wolf 102595533d5fSChristoph Hellwig struct aio_ctx { 102695533d5fSChristoph Hellwig QEMUIOVector qiov; 102795533d5fSChristoph Hellwig int64_t offset; 102895533d5fSChristoph Hellwig char *buf; 102995533d5fSChristoph Hellwig int qflag; 103095533d5fSChristoph Hellwig int vflag; 103195533d5fSChristoph Hellwig int Cflag; 103295533d5fSChristoph Hellwig int Pflag; 103395533d5fSChristoph Hellwig int pattern; 103495533d5fSChristoph Hellwig struct timeval t1; 103595533d5fSChristoph Hellwig }; 103695533d5fSChristoph Hellwig 103743642b38SDevin Nakamura static void aio_write_done(void *opaque, int ret) 103895533d5fSChristoph Hellwig { 103995533d5fSChristoph Hellwig struct aio_ctx *ctx = opaque; 104095533d5fSChristoph Hellwig struct timeval t2; 104195533d5fSChristoph Hellwig 104295533d5fSChristoph Hellwig gettimeofday(&t2, NULL); 104395533d5fSChristoph Hellwig 104495533d5fSChristoph Hellwig 104595533d5fSChristoph Hellwig if (ret < 0) { 104695533d5fSChristoph Hellwig printf("aio_write failed: %s\n", strerror(-ret)); 10477d8abfcbSKevin Wolf goto out; 104895533d5fSChristoph Hellwig } 104995533d5fSChristoph Hellwig 1050230d4fa4SChristoph Hellwig if (ctx->qflag) { 10517d8abfcbSKevin Wolf goto out; 1052230d4fa4SChristoph Hellwig } 105395533d5fSChristoph Hellwig 105495533d5fSChristoph Hellwig /* Finally, report back -- -C gives a parsable format */ 105595533d5fSChristoph Hellwig t2 = tsub(t2, ctx->t1); 1056230d4fa4SChristoph Hellwig print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1057230d4fa4SChristoph Hellwig ctx->qiov.size, 1, ctx->Cflag); 10587d8abfcbSKevin Wolf out: 105995533d5fSChristoph Hellwig qemu_io_free(ctx->buf); 106095533d5fSChristoph Hellwig free(ctx); 106195533d5fSChristoph Hellwig } 106295533d5fSChristoph Hellwig 106343642b38SDevin Nakamura static void aio_read_done(void *opaque, int ret) 106495533d5fSChristoph Hellwig { 106595533d5fSChristoph Hellwig struct aio_ctx *ctx = opaque; 106695533d5fSChristoph Hellwig struct timeval t2; 106795533d5fSChristoph Hellwig 106895533d5fSChristoph Hellwig gettimeofday(&t2, NULL); 106995533d5fSChristoph Hellwig 107095533d5fSChristoph Hellwig if (ret < 0) { 107195533d5fSChristoph Hellwig printf("readv failed: %s\n", strerror(-ret)); 10727d8abfcbSKevin Wolf goto out; 107395533d5fSChristoph Hellwig } 107495533d5fSChristoph Hellwig 107595533d5fSChristoph Hellwig if (ctx->Pflag) { 1076230d4fa4SChristoph Hellwig void *cmp_buf = malloc(ctx->qiov.size); 107795533d5fSChristoph Hellwig 1078230d4fa4SChristoph Hellwig memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1079230d4fa4SChristoph Hellwig if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 10800bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 108143642b38SDevin Nakamura PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size); 108295533d5fSChristoph Hellwig } 108395533d5fSChristoph Hellwig free(cmp_buf); 108495533d5fSChristoph Hellwig } 108595533d5fSChristoph Hellwig 1086230d4fa4SChristoph Hellwig if (ctx->qflag) { 10877d8abfcbSKevin Wolf goto out; 1088230d4fa4SChristoph Hellwig } 108995533d5fSChristoph Hellwig 1090230d4fa4SChristoph Hellwig if (ctx->vflag) { 1091230d4fa4SChristoph Hellwig dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1092230d4fa4SChristoph Hellwig } 109395533d5fSChristoph Hellwig 109495533d5fSChristoph Hellwig /* Finally, report back -- -C gives a parsable format */ 109595533d5fSChristoph Hellwig t2 = tsub(t2, ctx->t1); 1096230d4fa4SChristoph Hellwig print_report("read", &t2, ctx->offset, ctx->qiov.size, 1097230d4fa4SChristoph Hellwig ctx->qiov.size, 1, ctx->Cflag); 10987d8abfcbSKevin Wolf out: 109995533d5fSChristoph Hellwig qemu_io_free(ctx->buf); 110095533d5fSChristoph Hellwig free(ctx); 110195533d5fSChristoph Hellwig } 110295533d5fSChristoph Hellwig 110343642b38SDevin Nakamura static void aio_read_help(void) 110495533d5fSChristoph Hellwig { 110595533d5fSChristoph Hellwig printf( 110695533d5fSChristoph Hellwig "\n" 110795533d5fSChristoph Hellwig " asynchronously reads a range of bytes from the given offset\n" 110895533d5fSChristoph Hellwig "\n" 110995533d5fSChristoph Hellwig " Example:\n" 111095533d5fSChristoph Hellwig " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 111195533d5fSChristoph Hellwig "\n" 111295533d5fSChristoph Hellwig " Reads a segment of the currently open file, optionally dumping it to the\n" 111395533d5fSChristoph Hellwig " standard output stream (with -v option) for subsequent inspection.\n" 1114e432cef9SChristoph Hellwig " The read is performed asynchronously and the aio_flush command must be\n" 1115e432cef9SChristoph Hellwig " used to ensure all outstanding aio requests have been completed\n" 111695533d5fSChristoph Hellwig " -C, -- report statistics in a machine parsable format\n" 111795533d5fSChristoph Hellwig " -P, -- use a pattern to verify read data\n" 111895533d5fSChristoph Hellwig " -v, -- dump buffer to standard output\n" 1119095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 112095533d5fSChristoph Hellwig "\n"); 112195533d5fSChristoph Hellwig } 112295533d5fSChristoph Hellwig 112322a2bdcbSBlue Swirl static int aio_read_f(int argc, char **argv); 112422a2bdcbSBlue Swirl 112522a2bdcbSBlue Swirl static const cmdinfo_t aio_read_cmd = { 112622a2bdcbSBlue Swirl .name = "aio_read", 112722a2bdcbSBlue Swirl .cfunc = aio_read_f, 112822a2bdcbSBlue Swirl .argmin = 2, 112922a2bdcbSBlue Swirl .argmax = -1, 113022a2bdcbSBlue Swirl .args = "[-Cqv] [-P pattern ] off len [len..]", 113122a2bdcbSBlue Swirl .oneline = "asynchronously reads a number of bytes", 113222a2bdcbSBlue Swirl .help = aio_read_help, 113322a2bdcbSBlue Swirl }; 113422a2bdcbSBlue Swirl 113543642b38SDevin Nakamura static int aio_read_f(int argc, char **argv) 113695533d5fSChristoph Hellwig { 1137cf57298aSChristoph Hellwig int nr_iov, c; 113895533d5fSChristoph Hellwig struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 113995533d5fSChristoph Hellwig BlockDriverAIOCB *acb; 114095533d5fSChristoph Hellwig 114195533d5fSChristoph Hellwig while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 114295533d5fSChristoph Hellwig switch (c) { 114395533d5fSChristoph Hellwig case 'C': 114495533d5fSChristoph Hellwig ctx->Cflag = 1; 114595533d5fSChristoph Hellwig break; 114695533d5fSChristoph Hellwig case 'P': 114795533d5fSChristoph Hellwig ctx->Pflag = 1; 1148cf070d7eSChristoph Hellwig ctx->pattern = parse_pattern(optarg); 11491afec913SBlue Swirl if (ctx->pattern < 0) { 11501afec913SBlue Swirl free(ctx); 1151cf070d7eSChristoph Hellwig return 0; 11521afec913SBlue Swirl } 115395533d5fSChristoph Hellwig break; 115495533d5fSChristoph Hellwig case 'q': 115595533d5fSChristoph Hellwig ctx->qflag = 1; 115695533d5fSChristoph Hellwig break; 115795533d5fSChristoph Hellwig case 'v': 115895533d5fSChristoph Hellwig ctx->vflag = 1; 115995533d5fSChristoph Hellwig break; 116095533d5fSChristoph Hellwig default: 11617d8abfcbSKevin Wolf free(ctx); 116295533d5fSChristoph Hellwig return command_usage(&aio_read_cmd); 116395533d5fSChristoph Hellwig } 116495533d5fSChristoph Hellwig } 116595533d5fSChristoph Hellwig 11667d8abfcbSKevin Wolf if (optind > argc - 2) { 11677d8abfcbSKevin Wolf free(ctx); 116895533d5fSChristoph Hellwig return command_usage(&aio_read_cmd); 11697d8abfcbSKevin Wolf } 117095533d5fSChristoph Hellwig 117195533d5fSChristoph Hellwig ctx->offset = cvtnum(argv[optind]); 117295533d5fSChristoph Hellwig if (ctx->offset < 0) { 117395533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[optind]); 11747d8abfcbSKevin Wolf free(ctx); 117595533d5fSChristoph Hellwig return 0; 117695533d5fSChristoph Hellwig } 117795533d5fSChristoph Hellwig optind++; 117895533d5fSChristoph Hellwig 117995533d5fSChristoph Hellwig if (ctx->offset & 0x1ff) { 11800bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 11810bfcd599SBlue Swirl ctx->offset); 11827d8abfcbSKevin Wolf free(ctx); 118395533d5fSChristoph Hellwig return 0; 118495533d5fSChristoph Hellwig } 118595533d5fSChristoph Hellwig 118695533d5fSChristoph Hellwig nr_iov = argc - optind; 1187cf57298aSChristoph Hellwig ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); 118895533d5fSChristoph Hellwig 118995533d5fSChristoph Hellwig gettimeofday(&ctx->t1, NULL); 119095533d5fSChristoph Hellwig acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 119195533d5fSChristoph Hellwig ctx->qiov.size >> 9, aio_read_done, ctx); 11927d8abfcbSKevin Wolf if (!acb) { 11937d8abfcbSKevin Wolf free(ctx->buf); 11947d8abfcbSKevin Wolf free(ctx); 119595533d5fSChristoph Hellwig return -EIO; 11967d8abfcbSKevin Wolf } 119795533d5fSChristoph Hellwig 119895533d5fSChristoph Hellwig return 0; 119995533d5fSChristoph Hellwig } 120095533d5fSChristoph Hellwig 120143642b38SDevin Nakamura static void aio_write_help(void) 120295533d5fSChristoph Hellwig { 120395533d5fSChristoph Hellwig printf( 120495533d5fSChristoph Hellwig "\n" 120595533d5fSChristoph Hellwig " asynchronously writes a range of bytes from the given offset source\n" 120695533d5fSChristoph Hellwig " from multiple buffers\n" 120795533d5fSChristoph Hellwig "\n" 120895533d5fSChristoph Hellwig " Example:\n" 120995533d5fSChristoph Hellwig " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 121095533d5fSChristoph Hellwig "\n" 121195533d5fSChristoph Hellwig " Writes into a segment of the currently open file, using a buffer\n" 121295533d5fSChristoph Hellwig " filled with a set pattern (0xcdcdcdcd).\n" 1213e432cef9SChristoph Hellwig " The write is performed asynchronously and the aio_flush command must be\n" 1214e432cef9SChristoph Hellwig " used to ensure all outstanding aio requests have been completed\n" 121595533d5fSChristoph Hellwig " -P, -- use different pattern to fill file\n" 121695533d5fSChristoph Hellwig " -C, -- report statistics in a machine parsable format\n" 1217095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 121895533d5fSChristoph Hellwig "\n"); 121995533d5fSChristoph Hellwig } 122095533d5fSChristoph Hellwig 122122a2bdcbSBlue Swirl static int aio_write_f(int argc, char **argv); 122222a2bdcbSBlue Swirl 122322a2bdcbSBlue Swirl static const cmdinfo_t aio_write_cmd = { 122422a2bdcbSBlue Swirl .name = "aio_write", 122522a2bdcbSBlue Swirl .cfunc = aio_write_f, 122622a2bdcbSBlue Swirl .argmin = 2, 122722a2bdcbSBlue Swirl .argmax = -1, 122822a2bdcbSBlue Swirl .args = "[-Cq] [-P pattern ] off len [len..]", 122922a2bdcbSBlue Swirl .oneline = "asynchronously writes a number of bytes", 123022a2bdcbSBlue Swirl .help = aio_write_help, 123122a2bdcbSBlue Swirl }; 123295533d5fSChristoph Hellwig 123343642b38SDevin Nakamura static int aio_write_f(int argc, char **argv) 123495533d5fSChristoph Hellwig { 1235cf57298aSChristoph Hellwig int nr_iov, c; 123695533d5fSChristoph Hellwig int pattern = 0xcd; 123795533d5fSChristoph Hellwig struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 123895533d5fSChristoph Hellwig BlockDriverAIOCB *acb; 123995533d5fSChristoph Hellwig 124095533d5fSChristoph Hellwig while ((c = getopt(argc, argv, "CqP:")) != EOF) { 124195533d5fSChristoph Hellwig switch (c) { 124295533d5fSChristoph Hellwig case 'C': 124395533d5fSChristoph Hellwig ctx->Cflag = 1; 124495533d5fSChristoph Hellwig break; 124595533d5fSChristoph Hellwig case 'q': 124695533d5fSChristoph Hellwig ctx->qflag = 1; 124795533d5fSChristoph Hellwig break; 124895533d5fSChristoph Hellwig case 'P': 1249cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 125043642b38SDevin Nakamura if (pattern < 0) { 1251b1b1dad3SAlex Jia free(ctx); 1252cf070d7eSChristoph Hellwig return 0; 125343642b38SDevin Nakamura } 125495533d5fSChristoph Hellwig break; 125595533d5fSChristoph Hellwig default: 12567d8abfcbSKevin Wolf free(ctx); 125795533d5fSChristoph Hellwig return command_usage(&aio_write_cmd); 125895533d5fSChristoph Hellwig } 125995533d5fSChristoph Hellwig } 126095533d5fSChristoph Hellwig 12617d8abfcbSKevin Wolf if (optind > argc - 2) { 12627d8abfcbSKevin Wolf free(ctx); 126395533d5fSChristoph Hellwig return command_usage(&aio_write_cmd); 12647d8abfcbSKevin Wolf } 126595533d5fSChristoph Hellwig 126695533d5fSChristoph Hellwig ctx->offset = cvtnum(argv[optind]); 126795533d5fSChristoph Hellwig if (ctx->offset < 0) { 126895533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[optind]); 12697d8abfcbSKevin Wolf free(ctx); 127095533d5fSChristoph Hellwig return 0; 127195533d5fSChristoph Hellwig } 127295533d5fSChristoph Hellwig optind++; 127395533d5fSChristoph Hellwig 127495533d5fSChristoph Hellwig if (ctx->offset & 0x1ff) { 12750bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 12760bfcd599SBlue Swirl ctx->offset); 12777d8abfcbSKevin Wolf free(ctx); 127895533d5fSChristoph Hellwig return 0; 127995533d5fSChristoph Hellwig } 128095533d5fSChristoph Hellwig 128195533d5fSChristoph Hellwig nr_iov = argc - optind; 1282cf57298aSChristoph Hellwig ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); 128395533d5fSChristoph Hellwig 128495533d5fSChristoph Hellwig gettimeofday(&ctx->t1, NULL); 128595533d5fSChristoph Hellwig acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 128695533d5fSChristoph Hellwig ctx->qiov.size >> 9, aio_write_done, ctx); 12877d8abfcbSKevin Wolf if (!acb) { 12887d8abfcbSKevin Wolf free(ctx->buf); 12897d8abfcbSKevin Wolf free(ctx); 129095533d5fSChristoph Hellwig return -EIO; 12917d8abfcbSKevin Wolf } 129295533d5fSChristoph Hellwig 129395533d5fSChristoph Hellwig return 0; 129495533d5fSChristoph Hellwig } 129595533d5fSChristoph Hellwig 129643642b38SDevin Nakamura static int aio_flush_f(int argc, char **argv) 129795533d5fSChristoph Hellwig { 129895533d5fSChristoph Hellwig qemu_aio_flush(); 129995533d5fSChristoph Hellwig return 0; 130095533d5fSChristoph Hellwig } 130195533d5fSChristoph Hellwig 130295533d5fSChristoph Hellwig static const cmdinfo_t aio_flush_cmd = { 130395533d5fSChristoph Hellwig .name = "aio_flush", 130495533d5fSChristoph Hellwig .cfunc = aio_flush_f, 1305e432cef9SChristoph Hellwig .oneline = "completes all outstanding aio requests" 130695533d5fSChristoph Hellwig }; 130795533d5fSChristoph Hellwig 130843642b38SDevin Nakamura static int flush_f(int argc, char **argv) 1309e3aff4f6Saliguori { 1310e3aff4f6Saliguori bdrv_flush(bs); 1311e3aff4f6Saliguori return 0; 1312e3aff4f6Saliguori } 1313e3aff4f6Saliguori 1314e3aff4f6Saliguori static const cmdinfo_t flush_cmd = { 1315e3aff4f6Saliguori .name = "flush", 1316e3aff4f6Saliguori .altname = "f", 1317e3aff4f6Saliguori .cfunc = flush_f, 1318e3aff4f6Saliguori .oneline = "flush all in-core file state to disk", 1319e3aff4f6Saliguori }; 1320e3aff4f6Saliguori 132143642b38SDevin Nakamura static int truncate_f(int argc, char **argv) 1322e3aff4f6Saliguori { 1323e3aff4f6Saliguori int64_t offset; 1324e3aff4f6Saliguori int ret; 1325e3aff4f6Saliguori 1326e3aff4f6Saliguori offset = cvtnum(argv[1]); 1327e3aff4f6Saliguori if (offset < 0) { 1328e3aff4f6Saliguori printf("non-numeric truncate argument -- %s\n", argv[1]); 1329e3aff4f6Saliguori return 0; 1330e3aff4f6Saliguori } 1331e3aff4f6Saliguori 1332e3aff4f6Saliguori ret = bdrv_truncate(bs, offset); 1333e3aff4f6Saliguori if (ret < 0) { 13340923c577SKevin Wolf printf("truncate: %s\n", strerror(-ret)); 1335e3aff4f6Saliguori return 0; 1336e3aff4f6Saliguori } 1337e3aff4f6Saliguori 1338e3aff4f6Saliguori return 0; 1339e3aff4f6Saliguori } 1340e3aff4f6Saliguori 1341e3aff4f6Saliguori static const cmdinfo_t truncate_cmd = { 1342e3aff4f6Saliguori .name = "truncate", 1343e3aff4f6Saliguori .altname = "t", 1344e3aff4f6Saliguori .cfunc = truncate_f, 1345e3aff4f6Saliguori .argmin = 1, 1346e3aff4f6Saliguori .argmax = 1, 1347e3aff4f6Saliguori .args = "off", 1348e3aff4f6Saliguori .oneline = "truncates the current file at the given offset", 1349e3aff4f6Saliguori }; 1350e3aff4f6Saliguori 135143642b38SDevin Nakamura static int length_f(int argc, char **argv) 1352e3aff4f6Saliguori { 1353e3aff4f6Saliguori int64_t size; 1354e3aff4f6Saliguori char s1[64]; 1355e3aff4f6Saliguori 1356e3aff4f6Saliguori size = bdrv_getlength(bs); 1357e3aff4f6Saliguori if (size < 0) { 13580923c577SKevin Wolf printf("getlength: %s\n", strerror(-size)); 1359e3aff4f6Saliguori return 0; 1360e3aff4f6Saliguori } 1361e3aff4f6Saliguori 1362e3aff4f6Saliguori cvtstr(size, s1, sizeof(s1)); 1363e3aff4f6Saliguori printf("%s\n", s1); 1364e3aff4f6Saliguori return 0; 1365e3aff4f6Saliguori } 1366e3aff4f6Saliguori 1367e3aff4f6Saliguori 1368e3aff4f6Saliguori static const cmdinfo_t length_cmd = { 1369e3aff4f6Saliguori .name = "length", 1370e3aff4f6Saliguori .altname = "l", 1371e3aff4f6Saliguori .cfunc = length_f, 1372e3aff4f6Saliguori .oneline = "gets the length of the current file", 1373e3aff4f6Saliguori }; 1374e3aff4f6Saliguori 1375e3aff4f6Saliguori 137643642b38SDevin Nakamura static int info_f(int argc, char **argv) 1377e3aff4f6Saliguori { 1378e3aff4f6Saliguori BlockDriverInfo bdi; 1379e3aff4f6Saliguori char s1[64], s2[64]; 1380e3aff4f6Saliguori int ret; 1381e3aff4f6Saliguori 138243642b38SDevin Nakamura if (bs->drv && bs->drv->format_name) { 1383e3aff4f6Saliguori printf("format name: %s\n", bs->drv->format_name); 138443642b38SDevin Nakamura } 138543642b38SDevin Nakamura if (bs->drv && bs->drv->protocol_name) { 1386e3aff4f6Saliguori printf("format name: %s\n", bs->drv->protocol_name); 138743642b38SDevin Nakamura } 1388e3aff4f6Saliguori 1389e3aff4f6Saliguori ret = bdrv_get_info(bs, &bdi); 139043642b38SDevin Nakamura if (ret) { 1391e3aff4f6Saliguori return 0; 139243642b38SDevin Nakamura } 1393e3aff4f6Saliguori 1394e3aff4f6Saliguori cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1395e3aff4f6Saliguori cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1396e3aff4f6Saliguori 1397e3aff4f6Saliguori printf("cluster size: %s\n", s1); 1398e3aff4f6Saliguori printf("vm state offset: %s\n", s2); 1399e3aff4f6Saliguori 1400e3aff4f6Saliguori return 0; 1401e3aff4f6Saliguori } 1402e3aff4f6Saliguori 1403e3aff4f6Saliguori 1404e3aff4f6Saliguori 1405e3aff4f6Saliguori static const cmdinfo_t info_cmd = { 1406e3aff4f6Saliguori .name = "info", 1407e3aff4f6Saliguori .altname = "i", 1408e3aff4f6Saliguori .cfunc = info_f, 1409e3aff4f6Saliguori .oneline = "prints information about the current file", 1410e3aff4f6Saliguori }; 1411e3aff4f6Saliguori 141243642b38SDevin Nakamura static void discard_help(void) 1413edff5db1SStefan Hajnoczi { 1414edff5db1SStefan Hajnoczi printf( 1415edff5db1SStefan Hajnoczi "\n" 1416edff5db1SStefan Hajnoczi " discards a range of bytes from the given offset\n" 1417edff5db1SStefan Hajnoczi "\n" 1418edff5db1SStefan Hajnoczi " Example:\n" 1419edff5db1SStefan Hajnoczi " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n" 1420edff5db1SStefan Hajnoczi "\n" 1421edff5db1SStefan Hajnoczi " Discards a segment of the currently open file.\n" 1422edff5db1SStefan Hajnoczi " -C, -- report statistics in a machine parsable format\n" 1423095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 1424edff5db1SStefan Hajnoczi "\n"); 1425edff5db1SStefan Hajnoczi } 1426edff5db1SStefan Hajnoczi 1427edff5db1SStefan Hajnoczi static int discard_f(int argc, char **argv); 1428edff5db1SStefan Hajnoczi 1429edff5db1SStefan Hajnoczi static const cmdinfo_t discard_cmd = { 1430edff5db1SStefan Hajnoczi .name = "discard", 1431edff5db1SStefan Hajnoczi .altname = "d", 1432edff5db1SStefan Hajnoczi .cfunc = discard_f, 1433edff5db1SStefan Hajnoczi .argmin = 2, 1434edff5db1SStefan Hajnoczi .argmax = -1, 1435edff5db1SStefan Hajnoczi .args = "[-Cq] off len", 1436edff5db1SStefan Hajnoczi .oneline = "discards a number of bytes at a specified offset", 1437edff5db1SStefan Hajnoczi .help = discard_help, 1438edff5db1SStefan Hajnoczi }; 1439edff5db1SStefan Hajnoczi 144043642b38SDevin Nakamura static int discard_f(int argc, char **argv) 1441edff5db1SStefan Hajnoczi { 1442edff5db1SStefan Hajnoczi struct timeval t1, t2; 1443edff5db1SStefan Hajnoczi int Cflag = 0, qflag = 0; 1444edff5db1SStefan Hajnoczi int c, ret; 1445edff5db1SStefan Hajnoczi int64_t offset; 1446edff5db1SStefan Hajnoczi int count; 1447edff5db1SStefan Hajnoczi 1448edff5db1SStefan Hajnoczi while ((c = getopt(argc, argv, "Cq")) != EOF) { 1449edff5db1SStefan Hajnoczi switch (c) { 1450edff5db1SStefan Hajnoczi case 'C': 1451edff5db1SStefan Hajnoczi Cflag = 1; 1452edff5db1SStefan Hajnoczi break; 1453edff5db1SStefan Hajnoczi case 'q': 1454edff5db1SStefan Hajnoczi qflag = 1; 1455edff5db1SStefan Hajnoczi break; 1456edff5db1SStefan Hajnoczi default: 1457edff5db1SStefan Hajnoczi return command_usage(&discard_cmd); 1458edff5db1SStefan Hajnoczi } 1459edff5db1SStefan Hajnoczi } 1460edff5db1SStefan Hajnoczi 1461edff5db1SStefan Hajnoczi if (optind != argc - 2) { 1462edff5db1SStefan Hajnoczi return command_usage(&discard_cmd); 1463edff5db1SStefan Hajnoczi } 1464edff5db1SStefan Hajnoczi 1465edff5db1SStefan Hajnoczi offset = cvtnum(argv[optind]); 1466edff5db1SStefan Hajnoczi if (offset < 0) { 1467edff5db1SStefan Hajnoczi printf("non-numeric length argument -- %s\n", argv[optind]); 1468edff5db1SStefan Hajnoczi return 0; 1469edff5db1SStefan Hajnoczi } 1470edff5db1SStefan Hajnoczi 1471edff5db1SStefan Hajnoczi optind++; 1472edff5db1SStefan Hajnoczi count = cvtnum(argv[optind]); 1473edff5db1SStefan Hajnoczi if (count < 0) { 1474edff5db1SStefan Hajnoczi printf("non-numeric length argument -- %s\n", argv[optind]); 1475edff5db1SStefan Hajnoczi return 0; 1476edff5db1SStefan Hajnoczi } 1477edff5db1SStefan Hajnoczi 1478edff5db1SStefan Hajnoczi gettimeofday(&t1, NULL); 147943642b38SDevin Nakamura ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, 148043642b38SDevin Nakamura count >> BDRV_SECTOR_BITS); 1481edff5db1SStefan Hajnoczi gettimeofday(&t2, NULL); 1482edff5db1SStefan Hajnoczi 1483edff5db1SStefan Hajnoczi if (ret < 0) { 1484edff5db1SStefan Hajnoczi printf("discard failed: %s\n", strerror(-ret)); 1485edff5db1SStefan Hajnoczi goto out; 1486edff5db1SStefan Hajnoczi } 1487edff5db1SStefan Hajnoczi 1488edff5db1SStefan Hajnoczi /* Finally, report back -- -C gives a parsable format */ 1489edff5db1SStefan Hajnoczi if (!qflag) { 1490edff5db1SStefan Hajnoczi t2 = tsub(t2, t1); 1491edff5db1SStefan Hajnoczi print_report("discard", &t2, offset, count, count, 1, Cflag); 1492edff5db1SStefan Hajnoczi } 1493edff5db1SStefan Hajnoczi 1494edff5db1SStefan Hajnoczi out: 1495edff5db1SStefan Hajnoczi return 0; 1496edff5db1SStefan Hajnoczi } 1497edff5db1SStefan Hajnoczi 149843642b38SDevin Nakamura static int alloc_f(int argc, char **argv) 1499e3aff4f6Saliguori { 1500e3aff4f6Saliguori int64_t offset; 1501a7824a88SKevin Wolf int nb_sectors, remaining; 1502e3aff4f6Saliguori char s1[64]; 1503a7824a88SKevin Wolf int num, sum_alloc; 1504e3aff4f6Saliguori int ret; 1505e3aff4f6Saliguori 1506e3aff4f6Saliguori offset = cvtnum(argv[1]); 1507e3aff4f6Saliguori if (offset & 0x1ff) { 15080bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 15090bfcd599SBlue Swirl offset); 1510e3aff4f6Saliguori return 0; 1511e3aff4f6Saliguori } 1512e3aff4f6Saliguori 151343642b38SDevin Nakamura if (argc == 3) { 1514e3aff4f6Saliguori nb_sectors = cvtnum(argv[2]); 151543642b38SDevin Nakamura } else { 1516e3aff4f6Saliguori nb_sectors = 1; 151743642b38SDevin Nakamura } 1518e3aff4f6Saliguori 1519a7824a88SKevin Wolf remaining = nb_sectors; 1520a7824a88SKevin Wolf sum_alloc = 0; 1521a7824a88SKevin Wolf while (remaining) { 1522e3aff4f6Saliguori ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); 1523a7824a88SKevin Wolf remaining -= num; 1524a7824a88SKevin Wolf if (ret) { 1525a7824a88SKevin Wolf sum_alloc += num; 1526a7824a88SKevin Wolf } 1527a7824a88SKevin Wolf } 1528e3aff4f6Saliguori 1529e3aff4f6Saliguori cvtstr(offset, s1, sizeof(s1)); 1530e3aff4f6Saliguori 1531a7824a88SKevin Wolf printf("%d/%d sectors allocated at offset %s\n", 1532a7824a88SKevin Wolf sum_alloc, nb_sectors, s1); 1533e3aff4f6Saliguori return 0; 1534e3aff4f6Saliguori } 1535e3aff4f6Saliguori 1536e3aff4f6Saliguori static const cmdinfo_t alloc_cmd = { 1537e3aff4f6Saliguori .name = "alloc", 1538e3aff4f6Saliguori .altname = "a", 1539e3aff4f6Saliguori .argmin = 1, 1540e3aff4f6Saliguori .argmax = 2, 1541e3aff4f6Saliguori .cfunc = alloc_f, 1542e3aff4f6Saliguori .args = "off [sectors]", 1543e3aff4f6Saliguori .oneline = "checks if a sector is present in the file", 1544e3aff4f6Saliguori }; 1545e3aff4f6Saliguori 154643642b38SDevin Nakamura static int map_f(int argc, char **argv) 1547191c2890SKevin Wolf { 1548191c2890SKevin Wolf int64_t offset; 1549191c2890SKevin Wolf int64_t nb_sectors; 1550191c2890SKevin Wolf char s1[64]; 1551191c2890SKevin Wolf int num, num_checked; 1552191c2890SKevin Wolf int ret; 1553191c2890SKevin Wolf const char *retstr; 1554191c2890SKevin Wolf 1555191c2890SKevin Wolf offset = 0; 1556191c2890SKevin Wolf nb_sectors = bs->total_sectors; 1557191c2890SKevin Wolf 1558191c2890SKevin Wolf do { 1559191c2890SKevin Wolf num_checked = MIN(nb_sectors, INT_MAX); 1560191c2890SKevin Wolf ret = bdrv_is_allocated(bs, offset, num_checked, &num); 1561191c2890SKevin Wolf retstr = ret ? " allocated" : "not allocated"; 1562191c2890SKevin Wolf cvtstr(offset << 9ULL, s1, sizeof(s1)); 1563191c2890SKevin Wolf printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n", 1564191c2890SKevin Wolf offset << 9ULL, num, num_checked, retstr, s1, ret); 1565191c2890SKevin Wolf 1566191c2890SKevin Wolf offset += num; 1567191c2890SKevin Wolf nb_sectors -= num; 1568191c2890SKevin Wolf } while (offset < bs->total_sectors); 1569191c2890SKevin Wolf 1570191c2890SKevin Wolf return 0; 1571191c2890SKevin Wolf } 1572191c2890SKevin Wolf 1573191c2890SKevin Wolf static const cmdinfo_t map_cmd = { 1574191c2890SKevin Wolf .name = "map", 1575191c2890SKevin Wolf .argmin = 0, 1576191c2890SKevin Wolf .argmax = 0, 1577191c2890SKevin Wolf .cfunc = map_f, 1578191c2890SKevin Wolf .args = "", 1579191c2890SKevin Wolf .oneline = "prints the allocated areas of a file", 1580191c2890SKevin Wolf }; 1581191c2890SKevin Wolf 1582191c2890SKevin Wolf 158343642b38SDevin Nakamura static int close_f(int argc, char **argv) 1584e3aff4f6Saliguori { 1585*b4657855SStefan Hajnoczi bdrv_delete(bs); 1586e3aff4f6Saliguori bs = NULL; 1587e3aff4f6Saliguori return 0; 1588e3aff4f6Saliguori } 1589e3aff4f6Saliguori 1590e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 1591e3aff4f6Saliguori .name = "close", 1592e3aff4f6Saliguori .altname = "c", 1593e3aff4f6Saliguori .cfunc = close_f, 1594e3aff4f6Saliguori .oneline = "close the current open file", 1595e3aff4f6Saliguori }; 1596e3aff4f6Saliguori 15979c4bab26SChristoph Hellwig static int openfile(char *name, int flags, int growable) 1598e3aff4f6Saliguori { 1599e3aff4f6Saliguori if (bs) { 1600e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 1601e3aff4f6Saliguori return 1; 1602e3aff4f6Saliguori } 1603e3aff4f6Saliguori 16046db95603SChristoph Hellwig if (growable) { 16056db95603SChristoph Hellwig if (bdrv_file_open(&bs, name, flags)) { 16066db95603SChristoph Hellwig fprintf(stderr, "%s: can't open device %s\n", progname, name); 16076db95603SChristoph Hellwig return 1; 16086db95603SChristoph Hellwig } 16096db95603SChristoph Hellwig } else { 1610e3aff4f6Saliguori bs = bdrv_new("hda"); 1611e3aff4f6Saliguori 1612d6e9098eSKevin Wolf if (bdrv_open(bs, name, flags, NULL) < 0) { 1613e3aff4f6Saliguori fprintf(stderr, "%s: can't open device %s\n", progname, name); 1614*b4657855SStefan Hajnoczi bdrv_delete(bs); 1615e3aff4f6Saliguori bs = NULL; 1616e3aff4f6Saliguori return 1; 1617e3aff4f6Saliguori } 16189c4bab26SChristoph Hellwig } 16196db95603SChristoph Hellwig 1620e3aff4f6Saliguori return 0; 1621e3aff4f6Saliguori } 1622e3aff4f6Saliguori 162343642b38SDevin Nakamura static void open_help(void) 1624e3aff4f6Saliguori { 1625e3aff4f6Saliguori printf( 1626e3aff4f6Saliguori "\n" 1627e3aff4f6Saliguori " opens a new file in the requested mode\n" 1628e3aff4f6Saliguori "\n" 1629e3aff4f6Saliguori " Example:\n" 1630e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 1631e3aff4f6Saliguori "\n" 1632e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 1633e3aff4f6Saliguori " -r, -- open file read-only\n" 1634e3aff4f6Saliguori " -s, -- use snapshot file\n" 1635e3aff4f6Saliguori " -n, -- disable host cache\n" 16369c4bab26SChristoph Hellwig " -g, -- allow file to grow (only applies to protocols)" 1637e3aff4f6Saliguori "\n"); 1638e3aff4f6Saliguori } 1639e3aff4f6Saliguori 164022a2bdcbSBlue Swirl static int open_f(int argc, char **argv); 164122a2bdcbSBlue Swirl 164222a2bdcbSBlue Swirl static const cmdinfo_t open_cmd = { 164322a2bdcbSBlue Swirl .name = "open", 164422a2bdcbSBlue Swirl .altname = "o", 164522a2bdcbSBlue Swirl .cfunc = open_f, 164622a2bdcbSBlue Swirl .argmin = 1, 164722a2bdcbSBlue Swirl .argmax = -1, 164822a2bdcbSBlue Swirl .flags = CMD_NOFILE_OK, 164922a2bdcbSBlue Swirl .args = "[-Crsn] [path]", 165022a2bdcbSBlue Swirl .oneline = "open the file specified by path", 165122a2bdcbSBlue Swirl .help = open_help, 165222a2bdcbSBlue Swirl }; 1653e3aff4f6Saliguori 165443642b38SDevin Nakamura static int open_f(int argc, char **argv) 1655e3aff4f6Saliguori { 1656e3aff4f6Saliguori int flags = 0; 1657e3aff4f6Saliguori int readonly = 0; 16589c4bab26SChristoph Hellwig int growable = 0; 1659e3aff4f6Saliguori int c; 1660e3aff4f6Saliguori 16619a2d77adSChristoph Hellwig while ((c = getopt(argc, argv, "snrg")) != EOF) { 1662e3aff4f6Saliguori switch (c) { 1663e3aff4f6Saliguori case 's': 1664e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1665e3aff4f6Saliguori break; 1666e3aff4f6Saliguori case 'n': 1667a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 1668e3aff4f6Saliguori break; 1669e3aff4f6Saliguori case 'r': 1670e3aff4f6Saliguori readonly = 1; 1671e3aff4f6Saliguori break; 16729c4bab26SChristoph Hellwig case 'g': 16739c4bab26SChristoph Hellwig growable = 1; 16749c4bab26SChristoph Hellwig break; 1675e3aff4f6Saliguori default: 1676e3aff4f6Saliguori return command_usage(&open_cmd); 1677e3aff4f6Saliguori } 1678e3aff4f6Saliguori } 1679e3aff4f6Saliguori 1680f5edb014SNaphtali Sprei if (!readonly) { 1681e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1682f5edb014SNaphtali Sprei } 1683e3aff4f6Saliguori 168443642b38SDevin Nakamura if (optind != argc - 1) { 1685e3aff4f6Saliguori return command_usage(&open_cmd); 168643642b38SDevin Nakamura } 1687e3aff4f6Saliguori 16889c4bab26SChristoph Hellwig return openfile(argv[optind], flags, growable); 1689e3aff4f6Saliguori } 1690e3aff4f6Saliguori 169143642b38SDevin Nakamura static int init_args_command(int index) 1692e3aff4f6Saliguori { 1693e3aff4f6Saliguori /* only one device allowed so far */ 169443642b38SDevin Nakamura if (index >= 1) { 1695e3aff4f6Saliguori return 0; 169643642b38SDevin Nakamura } 1697e3aff4f6Saliguori return ++index; 1698e3aff4f6Saliguori } 1699e3aff4f6Saliguori 170043642b38SDevin Nakamura static int init_check_command(const cmdinfo_t *ct) 1701e3aff4f6Saliguori { 170243642b38SDevin Nakamura if (ct->flags & CMD_FLAG_GLOBAL) { 1703e3aff4f6Saliguori return 1; 170443642b38SDevin Nakamura } 1705e3aff4f6Saliguori if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1706e3aff4f6Saliguori fprintf(stderr, "no file open, try 'help open'\n"); 1707e3aff4f6Saliguori return 0; 1708e3aff4f6Saliguori } 1709e3aff4f6Saliguori return 1; 1710e3aff4f6Saliguori } 1711e3aff4f6Saliguori 1712e3aff4f6Saliguori static void usage(const char *name) 1713e3aff4f6Saliguori { 1714e3aff4f6Saliguori printf( 17159a2d77adSChristoph Hellwig "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" 171684844a20SStefan Weil "QEMU Disk exerciser\n" 1717e3aff4f6Saliguori "\n" 1718e3aff4f6Saliguori " -c, --cmd command to execute\n" 1719e3aff4f6Saliguori " -r, --read-only export read-only\n" 1720e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 1721e3aff4f6Saliguori " -n, --nocache disable host cache\n" 17221db6947dSChristoph Hellwig " -g, --growable allow file to grow (only applies to protocols)\n" 1723e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 17245c6c3a6cSChristoph Hellwig " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 1725e3aff4f6Saliguori " -h, --help display this help and exit\n" 1726e3aff4f6Saliguori " -V, --version output version information and exit\n" 1727e3aff4f6Saliguori "\n", 1728e3aff4f6Saliguori name); 1729e3aff4f6Saliguori } 1730e3aff4f6Saliguori 1731e3aff4f6Saliguori 1732e3aff4f6Saliguori int main(int argc, char **argv) 1733e3aff4f6Saliguori { 1734e3aff4f6Saliguori int readonly = 0; 17359c4bab26SChristoph Hellwig int growable = 0; 17369a2d77adSChristoph Hellwig const char *sopt = "hVc:rsnmgk"; 1737b32bb952SBlue Swirl const struct option lopt[] = { 1738660f11beSBlue Swirl { "help", 0, NULL, 'h' }, 1739660f11beSBlue Swirl { "version", 0, NULL, 'V' }, 1740660f11beSBlue Swirl { "offset", 1, NULL, 'o' }, 1741660f11beSBlue Swirl { "cmd", 1, NULL, 'c' }, 1742660f11beSBlue Swirl { "read-only", 0, NULL, 'r' }, 1743660f11beSBlue Swirl { "snapshot", 0, NULL, 's' }, 1744660f11beSBlue Swirl { "nocache", 0, NULL, 'n' }, 1745660f11beSBlue Swirl { "misalign", 0, NULL, 'm' }, 1746660f11beSBlue Swirl { "growable", 0, NULL, 'g' }, 17475c6c3a6cSChristoph Hellwig { "native-aio", 0, NULL, 'k' }, 1748660f11beSBlue Swirl { NULL, 0, NULL, 0 } 1749e3aff4f6Saliguori }; 1750e3aff4f6Saliguori int c; 1751e3aff4f6Saliguori int opt_index = 0; 1752e3aff4f6Saliguori int flags = 0; 1753e3aff4f6Saliguori 1754e3aff4f6Saliguori progname = basename(argv[0]); 1755e3aff4f6Saliguori 1756e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1757e3aff4f6Saliguori switch (c) { 1758e3aff4f6Saliguori case 's': 1759e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1760e3aff4f6Saliguori break; 1761e3aff4f6Saliguori case 'n': 1762a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 1763e3aff4f6Saliguori break; 1764e3aff4f6Saliguori case 'c': 1765e3aff4f6Saliguori add_user_command(optarg); 1766e3aff4f6Saliguori break; 1767e3aff4f6Saliguori case 'r': 1768e3aff4f6Saliguori readonly = 1; 1769e3aff4f6Saliguori break; 1770e3aff4f6Saliguori case 'm': 1771e3aff4f6Saliguori misalign = 1; 1772e3aff4f6Saliguori break; 17739c4bab26SChristoph Hellwig case 'g': 17749c4bab26SChristoph Hellwig growable = 1; 17759c4bab26SChristoph Hellwig break; 17765c6c3a6cSChristoph Hellwig case 'k': 17775c6c3a6cSChristoph Hellwig flags |= BDRV_O_NATIVE_AIO; 17785c6c3a6cSChristoph Hellwig break; 1779e3aff4f6Saliguori case 'V': 1780e3aff4f6Saliguori printf("%s version %s\n", progname, VERSION); 1781e3aff4f6Saliguori exit(0); 1782e3aff4f6Saliguori case 'h': 1783e3aff4f6Saliguori usage(progname); 1784e3aff4f6Saliguori exit(0); 1785e3aff4f6Saliguori default: 1786e3aff4f6Saliguori usage(progname); 1787e3aff4f6Saliguori exit(1); 1788e3aff4f6Saliguori } 1789e3aff4f6Saliguori } 1790e3aff4f6Saliguori 1791e3aff4f6Saliguori if ((argc - optind) > 1) { 1792e3aff4f6Saliguori usage(progname); 1793e3aff4f6Saliguori exit(1); 1794e3aff4f6Saliguori } 1795e3aff4f6Saliguori 1796e3aff4f6Saliguori bdrv_init(); 1797e3aff4f6Saliguori 1798e3aff4f6Saliguori /* initialize commands */ 1799e3aff4f6Saliguori quit_init(); 1800e3aff4f6Saliguori help_init(); 1801e3aff4f6Saliguori add_command(&open_cmd); 1802e3aff4f6Saliguori add_command(&close_cmd); 1803e3aff4f6Saliguori add_command(&read_cmd); 1804e3aff4f6Saliguori add_command(&readv_cmd); 1805e3aff4f6Saliguori add_command(&write_cmd); 1806e3aff4f6Saliguori add_command(&writev_cmd); 1807776cbbbdSKevin Wolf add_command(&multiwrite_cmd); 180895533d5fSChristoph Hellwig add_command(&aio_read_cmd); 180995533d5fSChristoph Hellwig add_command(&aio_write_cmd); 181095533d5fSChristoph Hellwig add_command(&aio_flush_cmd); 1811e3aff4f6Saliguori add_command(&flush_cmd); 1812e3aff4f6Saliguori add_command(&truncate_cmd); 1813e3aff4f6Saliguori add_command(&length_cmd); 1814e3aff4f6Saliguori add_command(&info_cmd); 1815edff5db1SStefan Hajnoczi add_command(&discard_cmd); 1816e3aff4f6Saliguori add_command(&alloc_cmd); 1817191c2890SKevin Wolf add_command(&map_cmd); 1818e3aff4f6Saliguori 1819e3aff4f6Saliguori add_args_command(init_args_command); 1820e3aff4f6Saliguori add_check_command(init_check_command); 1821e3aff4f6Saliguori 1822e3aff4f6Saliguori /* open the device */ 1823f5edb014SNaphtali Sprei if (!readonly) { 1824e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1825f5edb014SNaphtali Sprei } 1826e3aff4f6Saliguori 182743642b38SDevin Nakamura if ((argc - optind) == 1) { 18289c4bab26SChristoph Hellwig openfile(argv[optind], flags, growable); 182943642b38SDevin Nakamura } 1830e3aff4f6Saliguori command_loop(); 1831e3aff4f6Saliguori 183295533d5fSChristoph Hellwig /* 183395533d5fSChristoph Hellwig * Make sure all outstanding requests get flushed the program exits. 183495533d5fSChristoph Hellwig */ 183595533d5fSChristoph Hellwig qemu_aio_flush(); 183695533d5fSChristoph Hellwig 183743642b38SDevin Nakamura if (bs) { 1838*b4657855SStefan Hajnoczi bdrv_delete(bs); 183943642b38SDevin Nakamura } 1840e3aff4f6Saliguori return 0; 1841e3aff4f6Saliguori } 1842