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 62e3aff4f6Saliguori if (misalign) 63e3aff4f6Saliguori len += MISALIGN_OFFSET; 6472aef731SChristoph Hellwig buf = qemu_blockalign(bs, len); 65e3aff4f6Saliguori memset(buf, pattern, len); 66e3aff4f6Saliguori if (misalign) 67e3aff4f6Saliguori buf += MISALIGN_OFFSET; 68e3aff4f6Saliguori return buf; 69e3aff4f6Saliguori } 70e3aff4f6Saliguori 71e3aff4f6Saliguori static void qemu_io_free(void *p) 72e3aff4f6Saliguori { 73e3aff4f6Saliguori if (misalign) 74e3aff4f6Saliguori p -= MISALIGN_OFFSET; 75e3aff4f6Saliguori qemu_vfree(p); 76e3aff4f6Saliguori } 77e3aff4f6Saliguori 78e3aff4f6Saliguori static void 793abcdf49SStefan Weil dump_buffer(const void *buffer, int64_t offset, int len) 80e3aff4f6Saliguori { 81e3aff4f6Saliguori int i, j; 823abcdf49SStefan Weil const uint8_t *p; 83e3aff4f6Saliguori 84e3aff4f6Saliguori for (i = 0, p = buffer; i < len; i += 16) { 853abcdf49SStefan Weil const uint8_t *s = p; 86e3aff4f6Saliguori 870bfcd599SBlue Swirl printf("%08" PRIx64 ": ", offset + i); 88e3aff4f6Saliguori for (j = 0; j < 16 && i + j < len; j++, p++) 89e3aff4f6Saliguori printf("%02x ", *p); 90e3aff4f6Saliguori printf(" "); 91e3aff4f6Saliguori for (j = 0; j < 16 && i + j < len; j++, s++) { 923abcdf49SStefan Weil if (isalnum(*s)) 93e3aff4f6Saliguori printf("%c", *s); 94e3aff4f6Saliguori else 95e3aff4f6Saliguori printf("."); 96e3aff4f6Saliguori } 97e3aff4f6Saliguori printf("\n"); 98e3aff4f6Saliguori } 99e3aff4f6Saliguori } 100e3aff4f6Saliguori 101e3aff4f6Saliguori static void 102e3aff4f6Saliguori print_report(const char *op, struct timeval *t, int64_t offset, 103e3aff4f6Saliguori int count, int total, int cnt, int Cflag) 104e3aff4f6Saliguori { 105e3aff4f6Saliguori char s1[64], s2[64], ts[64]; 106e3aff4f6Saliguori 107e3aff4f6Saliguori timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); 108e3aff4f6Saliguori if (!Cflag) { 109e3aff4f6Saliguori cvtstr((double)total, s1, sizeof(s1)); 110e3aff4f6Saliguori cvtstr(tdiv((double)total, *t), s2, sizeof(s2)); 1110bfcd599SBlue Swirl printf("%s %d/%d bytes at offset %" PRId64 "\n", 1120bfcd599SBlue Swirl op, total, count, offset); 113e3aff4f6Saliguori printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n", 114e3aff4f6Saliguori s1, cnt, ts, s2, tdiv((double)cnt, *t)); 115e3aff4f6Saliguori } else {/* bytes,ops,time,bytes/sec,ops/sec */ 116e3aff4f6Saliguori printf("%d,%d,%s,%.3f,%.3f\n", 117e3aff4f6Saliguori total, cnt, ts, 118e3aff4f6Saliguori tdiv((double)total, *t), 119e3aff4f6Saliguori tdiv((double)cnt, *t)); 120e3aff4f6Saliguori } 121e3aff4f6Saliguori } 122e3aff4f6Saliguori 123cf57298aSChristoph Hellwig /* 124cf57298aSChristoph Hellwig * Parse multiple length statements for vectored I/O, and construct an I/O 125cf57298aSChristoph Hellwig * vector matching it. 126cf57298aSChristoph Hellwig */ 127cf57298aSChristoph Hellwig static void * 128cf57298aSChristoph Hellwig create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern) 129cf57298aSChristoph Hellwig { 130cf57298aSChristoph Hellwig size_t *sizes = calloc(nr_iov, sizeof(size_t)); 131cf57298aSChristoph Hellwig size_t count = 0; 13240a0d7c3SKevin Wolf void *buf = NULL; 13340a0d7c3SKevin Wolf void *p; 134cf57298aSChristoph Hellwig int i; 135cf57298aSChristoph Hellwig 136cf57298aSChristoph Hellwig for (i = 0; i < nr_iov; i++) { 137cf57298aSChristoph Hellwig char *arg = argv[i]; 138ca1d6ac6SJoel Schopp int64_t len; 139cf57298aSChristoph Hellwig 140cf57298aSChristoph Hellwig len = cvtnum(arg); 141cf57298aSChristoph Hellwig if (len < 0) { 142cf57298aSChristoph Hellwig printf("non-numeric length argument -- %s\n", arg); 14340a0d7c3SKevin Wolf goto fail; 144cf57298aSChristoph Hellwig } 145cf57298aSChristoph Hellwig 146cf57298aSChristoph Hellwig /* should be SIZE_T_MAX, but that doesn't exist */ 147ca1d6ac6SJoel Schopp if (len > INT_MAX) { 148cf57298aSChristoph Hellwig printf("too large length argument -- %s\n", arg); 14940a0d7c3SKevin Wolf goto fail; 150cf57298aSChristoph Hellwig } 151cf57298aSChristoph Hellwig 152cf57298aSChristoph Hellwig if (len & 0x1ff) { 1530bfcd599SBlue Swirl printf("length argument %" PRId64 1540bfcd599SBlue Swirl " is not sector aligned\n", len); 15540a0d7c3SKevin Wolf goto fail; 156cf57298aSChristoph Hellwig } 157cf57298aSChristoph Hellwig 158cf57298aSChristoph Hellwig sizes[i] = len; 159cf57298aSChristoph Hellwig count += len; 160cf57298aSChristoph Hellwig } 161cf57298aSChristoph Hellwig 162cf57298aSChristoph Hellwig qemu_iovec_init(qiov, nr_iov); 163cf57298aSChristoph Hellwig 164cf57298aSChristoph Hellwig buf = p = qemu_io_alloc(count, pattern); 165cf57298aSChristoph Hellwig 166cf57298aSChristoph Hellwig for (i = 0; i < nr_iov; i++) { 167cf57298aSChristoph Hellwig qemu_iovec_add(qiov, p, sizes[i]); 168cf57298aSChristoph Hellwig p += sizes[i]; 169cf57298aSChristoph Hellwig } 170cf57298aSChristoph Hellwig 17140a0d7c3SKevin Wolf fail: 172cf57298aSChristoph Hellwig free(sizes); 173cf57298aSChristoph Hellwig return buf; 174cf57298aSChristoph Hellwig } 175cf57298aSChristoph Hellwig 176e3aff4f6Saliguori static int do_read(char *buf, int64_t offset, int count, int *total) 177e3aff4f6Saliguori { 178e3aff4f6Saliguori int ret; 179e3aff4f6Saliguori 180e3aff4f6Saliguori ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9); 181e3aff4f6Saliguori if (ret < 0) 182e3aff4f6Saliguori return ret; 183e3aff4f6Saliguori *total = count; 184e3aff4f6Saliguori return 1; 185e3aff4f6Saliguori } 186e3aff4f6Saliguori 187e3aff4f6Saliguori static int do_write(char *buf, int64_t offset, int count, int *total) 188e3aff4f6Saliguori { 189e3aff4f6Saliguori int ret; 190e3aff4f6Saliguori 191e3aff4f6Saliguori ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9); 192e3aff4f6Saliguori if (ret < 0) 193e3aff4f6Saliguori return ret; 194e3aff4f6Saliguori *total = count; 195e3aff4f6Saliguori return 1; 196e3aff4f6Saliguori } 197e3aff4f6Saliguori 198e3aff4f6Saliguori static int do_pread(char *buf, int64_t offset, int count, int *total) 199e3aff4f6Saliguori { 200e3aff4f6Saliguori *total = bdrv_pread(bs, offset, (uint8_t *)buf, count); 201e3aff4f6Saliguori if (*total < 0) 202e3aff4f6Saliguori return *total; 203e3aff4f6Saliguori return 1; 204e3aff4f6Saliguori } 205e3aff4f6Saliguori 206e3aff4f6Saliguori static int do_pwrite(char *buf, int64_t offset, int count, int *total) 207e3aff4f6Saliguori { 208e3aff4f6Saliguori *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count); 209e3aff4f6Saliguori if (*total < 0) 210e3aff4f6Saliguori return *total; 211e3aff4f6Saliguori return 1; 212e3aff4f6Saliguori } 213e3aff4f6Saliguori 214ca94dbc7SKevin Wolf static int do_load_vmstate(char *buf, int64_t offset, int count, int *total) 215ca94dbc7SKevin Wolf { 216ca94dbc7SKevin Wolf *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count); 217ca94dbc7SKevin Wolf if (*total < 0) 218ca94dbc7SKevin Wolf return *total; 219ca94dbc7SKevin Wolf return 1; 220ca94dbc7SKevin Wolf } 221ca94dbc7SKevin Wolf 222ca94dbc7SKevin Wolf static int do_save_vmstate(char *buf, int64_t offset, int count, int *total) 223ca94dbc7SKevin Wolf { 224ca94dbc7SKevin Wolf *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count); 225ca94dbc7SKevin Wolf if (*total < 0) 226ca94dbc7SKevin Wolf return *total; 227ca94dbc7SKevin Wolf return 1; 228ca94dbc7SKevin Wolf } 229ca94dbc7SKevin Wolf 230e3aff4f6Saliguori #define NOT_DONE 0x7fffffff 231e3aff4f6Saliguori static void aio_rw_done(void *opaque, int ret) 232e3aff4f6Saliguori { 233e3aff4f6Saliguori *(int *)opaque = ret; 234e3aff4f6Saliguori } 235e3aff4f6Saliguori 236e3aff4f6Saliguori static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total) 237e3aff4f6Saliguori { 238e3aff4f6Saliguori BlockDriverAIOCB *acb; 239e3aff4f6Saliguori int async_ret = NOT_DONE; 240e3aff4f6Saliguori 241e3aff4f6Saliguori acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, 242e3aff4f6Saliguori aio_rw_done, &async_ret); 243e3aff4f6Saliguori if (!acb) 244e3aff4f6Saliguori return -EIO; 245e3aff4f6Saliguori 246e3aff4f6Saliguori while (async_ret == NOT_DONE) 247e3aff4f6Saliguori qemu_aio_wait(); 248e3aff4f6Saliguori 249e3aff4f6Saliguori *total = qiov->size; 250e3aff4f6Saliguori return async_ret < 0 ? async_ret : 1; 251e3aff4f6Saliguori } 252e3aff4f6Saliguori 253e3aff4f6Saliguori static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) 254e3aff4f6Saliguori { 255e3aff4f6Saliguori BlockDriverAIOCB *acb; 256e3aff4f6Saliguori int async_ret = NOT_DONE; 257e3aff4f6Saliguori 258e3aff4f6Saliguori acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, 259e3aff4f6Saliguori aio_rw_done, &async_ret); 260e3aff4f6Saliguori if (!acb) 261e3aff4f6Saliguori return -EIO; 262e3aff4f6Saliguori 263e3aff4f6Saliguori while (async_ret == NOT_DONE) 264e3aff4f6Saliguori qemu_aio_wait(); 265e3aff4f6Saliguori 2667e9bbc9fSaliguori *total = qiov->size; 267e3aff4f6Saliguori return async_ret < 0 ? async_ret : 1; 268e3aff4f6Saliguori } 269e3aff4f6Saliguori 270776cbbbdSKevin Wolf struct multiwrite_async_ret { 271776cbbbdSKevin Wolf int num_done; 272776cbbbdSKevin Wolf int error; 273776cbbbdSKevin Wolf }; 274776cbbbdSKevin Wolf 275776cbbbdSKevin Wolf static void multiwrite_cb(void *opaque, int ret) 276776cbbbdSKevin Wolf { 277776cbbbdSKevin Wolf struct multiwrite_async_ret *async_ret = opaque; 278776cbbbdSKevin Wolf 279776cbbbdSKevin Wolf async_ret->num_done++; 280776cbbbdSKevin Wolf if (ret < 0) { 281776cbbbdSKevin Wolf async_ret->error = ret; 282776cbbbdSKevin Wolf } 283776cbbbdSKevin Wolf } 284776cbbbdSKevin Wolf 285776cbbbdSKevin Wolf static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total) 286776cbbbdSKevin Wolf { 287776cbbbdSKevin Wolf int i, ret; 288776cbbbdSKevin Wolf struct multiwrite_async_ret async_ret = { 289776cbbbdSKevin Wolf .num_done = 0, 290776cbbbdSKevin Wolf .error = 0, 291776cbbbdSKevin Wolf }; 292776cbbbdSKevin Wolf 293776cbbbdSKevin Wolf *total = 0; 294776cbbbdSKevin Wolf for (i = 0; i < num_reqs; i++) { 295776cbbbdSKevin Wolf reqs[i].cb = multiwrite_cb; 296776cbbbdSKevin Wolf reqs[i].opaque = &async_ret; 297776cbbbdSKevin Wolf *total += reqs[i].qiov->size; 298776cbbbdSKevin Wolf } 299776cbbbdSKevin Wolf 300776cbbbdSKevin Wolf ret = bdrv_aio_multiwrite(bs, reqs, num_reqs); 301776cbbbdSKevin Wolf if (ret < 0) { 302776cbbbdSKevin Wolf return ret; 303776cbbbdSKevin Wolf } 304776cbbbdSKevin Wolf 305776cbbbdSKevin Wolf while (async_ret.num_done < num_reqs) { 306776cbbbdSKevin Wolf qemu_aio_wait(); 307776cbbbdSKevin Wolf } 308776cbbbdSKevin Wolf 309776cbbbdSKevin Wolf return async_ret.error < 0 ? async_ret.error : 1; 310776cbbbdSKevin Wolf } 311e3aff4f6Saliguori 312e3aff4f6Saliguori static void 313e3aff4f6Saliguori read_help(void) 314e3aff4f6Saliguori { 315e3aff4f6Saliguori printf( 316e3aff4f6Saliguori "\n" 317e3aff4f6Saliguori " reads a range of bytes from the given offset\n" 318e3aff4f6Saliguori "\n" 319e3aff4f6Saliguori " Example:\n" 320e3aff4f6Saliguori " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 321e3aff4f6Saliguori "\n" 322e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 323e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 324ca94dbc7SKevin Wolf " -b, -- read from the VM state rather than the virtual disk\n" 325d9654a58SKevin Wolf " -C, -- report statistics in a machine parsable format\n" 326d9654a58SKevin Wolf " -l, -- length for pattern verification (only with -P)\n" 327e3aff4f6Saliguori " -p, -- use bdrv_pread to read the file\n" 328c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 329095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 330d9654a58SKevin Wolf " -s, -- start offset for pattern verification (only with -P)\n" 331d9654a58SKevin Wolf " -v, -- dump buffer to standard output\n" 332e3aff4f6Saliguori "\n"); 333e3aff4f6Saliguori } 334e3aff4f6Saliguori 33522a2bdcbSBlue Swirl static int read_f(int argc, char **argv); 33622a2bdcbSBlue Swirl 33722a2bdcbSBlue Swirl static const cmdinfo_t read_cmd = { 33822a2bdcbSBlue Swirl .name = "read", 33922a2bdcbSBlue Swirl .altname = "r", 34022a2bdcbSBlue Swirl .cfunc = read_f, 34122a2bdcbSBlue Swirl .argmin = 2, 34222a2bdcbSBlue Swirl .argmax = -1, 34322a2bdcbSBlue Swirl .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", 34422a2bdcbSBlue Swirl .oneline = "reads a number of bytes at a specified offset", 34522a2bdcbSBlue Swirl .help = read_help, 34622a2bdcbSBlue Swirl }; 34722a2bdcbSBlue Swirl 348e3aff4f6Saliguori static int 349e3aff4f6Saliguori read_f(int argc, char **argv) 350e3aff4f6Saliguori { 351e3aff4f6Saliguori struct timeval t1, t2; 352e3aff4f6Saliguori int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 353ca94dbc7SKevin Wolf int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; 354e3aff4f6Saliguori int c, cnt; 355e3aff4f6Saliguori char *buf; 356e3aff4f6Saliguori int64_t offset; 357d4ec5228SPaul Brook int count; 358d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 359d4ec5228SPaul Brook int total = 0; 360d9654a58SKevin Wolf int pattern = 0, pattern_offset = 0, pattern_count = 0; 361e3aff4f6Saliguori 362ca94dbc7SKevin Wolf while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { 363e3aff4f6Saliguori switch (c) { 364ca94dbc7SKevin Wolf case 'b': 365ca94dbc7SKevin Wolf bflag = 1; 366ca94dbc7SKevin Wolf break; 367e3aff4f6Saliguori case 'C': 368e3aff4f6Saliguori Cflag = 1; 369e3aff4f6Saliguori break; 370d9654a58SKevin Wolf case 'l': 371d9654a58SKevin Wolf lflag = 1; 372d9654a58SKevin Wolf pattern_count = cvtnum(optarg); 373d9654a58SKevin Wolf if (pattern_count < 0) { 374d9654a58SKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 375d9654a58SKevin Wolf return 0; 376d9654a58SKevin Wolf } 377d9654a58SKevin Wolf break; 378e3aff4f6Saliguori case 'p': 379e3aff4f6Saliguori pflag = 1; 380e3aff4f6Saliguori break; 381c48101aeSaliguori case 'P': 382c48101aeSaliguori Pflag = 1; 383cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 384cf070d7eSChristoph Hellwig if (pattern < 0) 385cf070d7eSChristoph Hellwig return 0; 386c48101aeSaliguori break; 387e3aff4f6Saliguori case 'q': 388e3aff4f6Saliguori qflag = 1; 389e3aff4f6Saliguori break; 390d9654a58SKevin Wolf case 's': 391d9654a58SKevin Wolf sflag = 1; 392d9654a58SKevin Wolf pattern_offset = cvtnum(optarg); 393d9654a58SKevin Wolf if (pattern_offset < 0) { 394d9654a58SKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 395d9654a58SKevin Wolf return 0; 396d9654a58SKevin Wolf } 397d9654a58SKevin Wolf break; 398e3aff4f6Saliguori case 'v': 399e3aff4f6Saliguori vflag = 1; 400e3aff4f6Saliguori break; 401e3aff4f6Saliguori default: 402e3aff4f6Saliguori return command_usage(&read_cmd); 403e3aff4f6Saliguori } 404e3aff4f6Saliguori } 405e3aff4f6Saliguori 406e3aff4f6Saliguori if (optind != argc - 2) 407e3aff4f6Saliguori return command_usage(&read_cmd); 408e3aff4f6Saliguori 409ca94dbc7SKevin Wolf if (bflag && pflag) { 410ca94dbc7SKevin Wolf printf("-b and -p cannot be specified at the same time\n"); 411ca94dbc7SKevin Wolf return 0; 412ca94dbc7SKevin Wolf } 413ca94dbc7SKevin Wolf 414e3aff4f6Saliguori offset = cvtnum(argv[optind]); 415e3aff4f6Saliguori if (offset < 0) { 416e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 417e3aff4f6Saliguori return 0; 418e3aff4f6Saliguori } 419e3aff4f6Saliguori 420e3aff4f6Saliguori optind++; 421e3aff4f6Saliguori count = cvtnum(argv[optind]); 422e3aff4f6Saliguori if (count < 0) { 423e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 424e3aff4f6Saliguori return 0; 425e3aff4f6Saliguori } 426e3aff4f6Saliguori 427d9654a58SKevin Wolf if (!Pflag && (lflag || sflag)) { 428d9654a58SKevin Wolf return command_usage(&read_cmd); 429d9654a58SKevin Wolf } 430d9654a58SKevin Wolf 431d9654a58SKevin Wolf if (!lflag) { 432d9654a58SKevin Wolf pattern_count = count - pattern_offset; 433d9654a58SKevin Wolf } 434d9654a58SKevin Wolf 435d9654a58SKevin Wolf if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 436d9654a58SKevin Wolf printf("pattern verfication range exceeds end of read data\n"); 437d9654a58SKevin Wolf return 0; 438d9654a58SKevin Wolf } 439d9654a58SKevin Wolf 440e3aff4f6Saliguori if (!pflag) 441e3aff4f6Saliguori if (offset & 0x1ff) { 4420bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 4430bfcd599SBlue Swirl offset); 444e3aff4f6Saliguori return 0; 445e3aff4f6Saliguori 446e3aff4f6Saliguori if (count & 0x1ff) { 447e3aff4f6Saliguori printf("count %d is not sector aligned\n", 448e3aff4f6Saliguori count); 449e3aff4f6Saliguori return 0; 450e3aff4f6Saliguori } 451e3aff4f6Saliguori } 452e3aff4f6Saliguori 453e3aff4f6Saliguori buf = qemu_io_alloc(count, 0xab); 454e3aff4f6Saliguori 455e3aff4f6Saliguori gettimeofday(&t1, NULL); 456e3aff4f6Saliguori if (pflag) 457e3aff4f6Saliguori cnt = do_pread(buf, offset, count, &total); 458ca94dbc7SKevin Wolf else if (bflag) 459ca94dbc7SKevin Wolf cnt = do_load_vmstate(buf, offset, count, &total); 460e3aff4f6Saliguori else 461e3aff4f6Saliguori cnt = do_read(buf, offset, count, &total); 462e3aff4f6Saliguori gettimeofday(&t2, NULL); 463e3aff4f6Saliguori 464e3aff4f6Saliguori if (cnt < 0) { 465e3aff4f6Saliguori printf("read failed: %s\n", strerror(-cnt)); 4667d8abfcbSKevin Wolf goto out; 467e3aff4f6Saliguori } 468e3aff4f6Saliguori 469c48101aeSaliguori if (Pflag) { 470d9654a58SKevin Wolf void* cmp_buf = malloc(pattern_count); 471d9654a58SKevin Wolf memset(cmp_buf, pattern, pattern_count); 472d9654a58SKevin Wolf if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 4730bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 4740bfcd599SBlue Swirl PRId64 ", %d bytes\n", 4750bfcd599SBlue Swirl offset + pattern_offset, pattern_count); 476c48101aeSaliguori } 477c48101aeSaliguori free(cmp_buf); 478c48101aeSaliguori } 479c48101aeSaliguori 480e3aff4f6Saliguori if (qflag) 4817d8abfcbSKevin Wolf goto out; 482e3aff4f6Saliguori 483e3aff4f6Saliguori if (vflag) 484e3aff4f6Saliguori dump_buffer(buf, offset, count); 485e3aff4f6Saliguori 486e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 487e3aff4f6Saliguori t2 = tsub(t2, t1); 488e3aff4f6Saliguori print_report("read", &t2, offset, count, total, cnt, Cflag); 489e3aff4f6Saliguori 4907d8abfcbSKevin Wolf out: 491e3aff4f6Saliguori qemu_io_free(buf); 492e3aff4f6Saliguori 493e3aff4f6Saliguori return 0; 494e3aff4f6Saliguori } 495e3aff4f6Saliguori 496e3aff4f6Saliguori static void 497e3aff4f6Saliguori readv_help(void) 498e3aff4f6Saliguori { 499e3aff4f6Saliguori printf( 500e3aff4f6Saliguori "\n" 501e3aff4f6Saliguori " reads a range of bytes from the given offset into multiple buffers\n" 502e3aff4f6Saliguori "\n" 503e3aff4f6Saliguori " Example:\n" 504e3aff4f6Saliguori " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 505e3aff4f6Saliguori "\n" 506e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 507e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 508e3aff4f6Saliguori " Uses multiple iovec buffers if more than one byte range is specified.\n" 509e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 510c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 511e3aff4f6Saliguori " -v, -- dump buffer to standard output\n" 512095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 513e3aff4f6Saliguori "\n"); 514e3aff4f6Saliguori } 515e3aff4f6Saliguori 51622a2bdcbSBlue Swirl static int readv_f(int argc, char **argv); 51722a2bdcbSBlue Swirl 51822a2bdcbSBlue Swirl static const cmdinfo_t readv_cmd = { 51922a2bdcbSBlue Swirl .name = "readv", 52022a2bdcbSBlue Swirl .cfunc = readv_f, 52122a2bdcbSBlue Swirl .argmin = 2, 52222a2bdcbSBlue Swirl .argmax = -1, 52322a2bdcbSBlue Swirl .args = "[-Cqv] [-P pattern ] off len [len..]", 52422a2bdcbSBlue Swirl .oneline = "reads a number of bytes at a specified offset", 52522a2bdcbSBlue Swirl .help = readv_help, 52622a2bdcbSBlue Swirl }; 52722a2bdcbSBlue Swirl 528e3aff4f6Saliguori static int 529e3aff4f6Saliguori readv_f(int argc, char **argv) 530e3aff4f6Saliguori { 531e3aff4f6Saliguori struct timeval t1, t2; 532e3aff4f6Saliguori int Cflag = 0, qflag = 0, vflag = 0; 533e3aff4f6Saliguori int c, cnt; 534cf57298aSChristoph Hellwig char *buf; 535e3aff4f6Saliguori int64_t offset; 5366474bd69SBlue Swirl /* Some compilers get confused and warn if this is not initialized. */ 5376474bd69SBlue Swirl int total = 0; 538cf57298aSChristoph Hellwig int nr_iov; 539e3aff4f6Saliguori QEMUIOVector qiov; 540c48101aeSaliguori int pattern = 0; 541c48101aeSaliguori int Pflag = 0; 542e3aff4f6Saliguori 543c48101aeSaliguori while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 544e3aff4f6Saliguori switch (c) { 545e3aff4f6Saliguori case 'C': 546e3aff4f6Saliguori Cflag = 1; 547e3aff4f6Saliguori break; 548c48101aeSaliguori case 'P': 549c48101aeSaliguori Pflag = 1; 550cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 551cf070d7eSChristoph Hellwig if (pattern < 0) 552cf070d7eSChristoph Hellwig return 0; 553c48101aeSaliguori break; 554e3aff4f6Saliguori case 'q': 555e3aff4f6Saliguori qflag = 1; 556e3aff4f6Saliguori break; 557e3aff4f6Saliguori case 'v': 558e3aff4f6Saliguori vflag = 1; 559e3aff4f6Saliguori break; 560e3aff4f6Saliguori default: 561e3aff4f6Saliguori return command_usage(&readv_cmd); 562e3aff4f6Saliguori } 563e3aff4f6Saliguori } 564e3aff4f6Saliguori 565e3aff4f6Saliguori if (optind > argc - 2) 566e3aff4f6Saliguori return command_usage(&readv_cmd); 567e3aff4f6Saliguori 568e3aff4f6Saliguori 569e3aff4f6Saliguori offset = cvtnum(argv[optind]); 570e3aff4f6Saliguori if (offset < 0) { 571e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 572e3aff4f6Saliguori return 0; 573e3aff4f6Saliguori } 574e3aff4f6Saliguori optind++; 575e3aff4f6Saliguori 576e3aff4f6Saliguori if (offset & 0x1ff) { 5770bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 5780bfcd599SBlue Swirl offset); 579e3aff4f6Saliguori return 0; 580e3aff4f6Saliguori } 581e3aff4f6Saliguori 582e3aff4f6Saliguori nr_iov = argc - optind; 583cf57298aSChristoph Hellwig buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); 584e3aff4f6Saliguori 585e3aff4f6Saliguori gettimeofday(&t1, NULL); 586e3aff4f6Saliguori cnt = do_aio_readv(&qiov, offset, &total); 587e3aff4f6Saliguori gettimeofday(&t2, NULL); 588e3aff4f6Saliguori 589e3aff4f6Saliguori if (cnt < 0) { 590e3aff4f6Saliguori printf("readv failed: %s\n", strerror(-cnt)); 5917d8abfcbSKevin Wolf goto out; 592e3aff4f6Saliguori } 593e3aff4f6Saliguori 594c48101aeSaliguori if (Pflag) { 595cf57298aSChristoph Hellwig void* cmp_buf = malloc(qiov.size); 596cf57298aSChristoph Hellwig memset(cmp_buf, pattern, qiov.size); 597cf57298aSChristoph Hellwig if (memcmp(buf, cmp_buf, qiov.size)) { 5980bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 5990bfcd599SBlue Swirl PRId64 ", %zd bytes\n", 6000bfcd599SBlue Swirl offset, qiov.size); 601c48101aeSaliguori } 602c48101aeSaliguori free(cmp_buf); 603c48101aeSaliguori } 604c48101aeSaliguori 605e3aff4f6Saliguori if (qflag) 6067d8abfcbSKevin Wolf goto out; 607e3aff4f6Saliguori 608e3aff4f6Saliguori if (vflag) 609e3aff4f6Saliguori dump_buffer(buf, offset, qiov.size); 610e3aff4f6Saliguori 611e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 612e3aff4f6Saliguori t2 = tsub(t2, t1); 613e3aff4f6Saliguori print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 614e3aff4f6Saliguori 6157d8abfcbSKevin Wolf out: 616e3aff4f6Saliguori qemu_io_free(buf); 617e3aff4f6Saliguori return 0; 618e3aff4f6Saliguori } 619e3aff4f6Saliguori 620e3aff4f6Saliguori static void 621e3aff4f6Saliguori write_help(void) 622e3aff4f6Saliguori { 623e3aff4f6Saliguori printf( 624e3aff4f6Saliguori "\n" 625e3aff4f6Saliguori " writes a range of bytes from the given offset\n" 626e3aff4f6Saliguori "\n" 627e3aff4f6Saliguori " Example:\n" 628e3aff4f6Saliguori " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 629e3aff4f6Saliguori "\n" 630e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 631e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 632ca94dbc7SKevin Wolf " -b, -- write to the VM state rather than the virtual disk\n" 633e3aff4f6Saliguori " -p, -- use bdrv_pwrite to write the file\n" 634e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 635e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 636095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 637e3aff4f6Saliguori "\n"); 638e3aff4f6Saliguori } 639e3aff4f6Saliguori 64022a2bdcbSBlue Swirl static int write_f(int argc, char **argv); 64122a2bdcbSBlue Swirl 64222a2bdcbSBlue Swirl static const cmdinfo_t write_cmd = { 64322a2bdcbSBlue Swirl .name = "write", 64422a2bdcbSBlue Swirl .altname = "w", 64522a2bdcbSBlue Swirl .cfunc = write_f, 64622a2bdcbSBlue Swirl .argmin = 2, 64722a2bdcbSBlue Swirl .argmax = -1, 64822a2bdcbSBlue Swirl .args = "[-abCpq] [-P pattern ] off len", 64922a2bdcbSBlue Swirl .oneline = "writes a number of bytes at a specified offset", 65022a2bdcbSBlue Swirl .help = write_help, 65122a2bdcbSBlue Swirl }; 65222a2bdcbSBlue Swirl 653e3aff4f6Saliguori static int 654e3aff4f6Saliguori write_f(int argc, char **argv) 655e3aff4f6Saliguori { 656e3aff4f6Saliguori struct timeval t1, t2; 657ca94dbc7SKevin Wolf int Cflag = 0, pflag = 0, qflag = 0, bflag = 0; 658e3aff4f6Saliguori int c, cnt; 659e3aff4f6Saliguori char *buf; 660e3aff4f6Saliguori int64_t offset; 661d4ec5228SPaul Brook int count; 662d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 663d4ec5228SPaul Brook int total = 0; 664e3aff4f6Saliguori int pattern = 0xcd; 665e3aff4f6Saliguori 666ca94dbc7SKevin Wolf while ((c = getopt(argc, argv, "bCpP:q")) != EOF) { 667e3aff4f6Saliguori switch (c) { 668ca94dbc7SKevin Wolf case 'b': 669ca94dbc7SKevin Wolf bflag = 1; 670ca94dbc7SKevin Wolf break; 671e3aff4f6Saliguori case 'C': 672e3aff4f6Saliguori Cflag = 1; 673e3aff4f6Saliguori break; 674e3aff4f6Saliguori case 'p': 675e3aff4f6Saliguori pflag = 1; 676e3aff4f6Saliguori break; 677e3aff4f6Saliguori case 'P': 678cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 679cf070d7eSChristoph Hellwig if (pattern < 0) 680cf070d7eSChristoph Hellwig return 0; 681e3aff4f6Saliguori break; 682e3aff4f6Saliguori case 'q': 683e3aff4f6Saliguori qflag = 1; 684e3aff4f6Saliguori break; 685e3aff4f6Saliguori default: 686e3aff4f6Saliguori return command_usage(&write_cmd); 687e3aff4f6Saliguori } 688e3aff4f6Saliguori } 689e3aff4f6Saliguori 690e3aff4f6Saliguori if (optind != argc - 2) 691e3aff4f6Saliguori return command_usage(&write_cmd); 692e3aff4f6Saliguori 693ca94dbc7SKevin Wolf if (bflag && pflag) { 694ca94dbc7SKevin Wolf printf("-b and -p cannot be specified at the same time\n"); 695ca94dbc7SKevin Wolf return 0; 696ca94dbc7SKevin Wolf } 697ca94dbc7SKevin Wolf 698e3aff4f6Saliguori offset = cvtnum(argv[optind]); 699e3aff4f6Saliguori if (offset < 0) { 700e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 701e3aff4f6Saliguori return 0; 702e3aff4f6Saliguori } 703e3aff4f6Saliguori 704e3aff4f6Saliguori optind++; 705e3aff4f6Saliguori count = cvtnum(argv[optind]); 706e3aff4f6Saliguori if (count < 0) { 707e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 708e3aff4f6Saliguori return 0; 709e3aff4f6Saliguori } 710e3aff4f6Saliguori 711e3aff4f6Saliguori if (!pflag) { 712e3aff4f6Saliguori if (offset & 0x1ff) { 7130bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 7140bfcd599SBlue Swirl offset); 715e3aff4f6Saliguori return 0; 716e3aff4f6Saliguori } 717e3aff4f6Saliguori 718e3aff4f6Saliguori if (count & 0x1ff) { 719e3aff4f6Saliguori printf("count %d is not sector aligned\n", 720e3aff4f6Saliguori count); 721e3aff4f6Saliguori return 0; 722e3aff4f6Saliguori } 723e3aff4f6Saliguori } 724e3aff4f6Saliguori 725e3aff4f6Saliguori buf = qemu_io_alloc(count, pattern); 726e3aff4f6Saliguori 727e3aff4f6Saliguori gettimeofday(&t1, NULL); 728e3aff4f6Saliguori if (pflag) 729e3aff4f6Saliguori cnt = do_pwrite(buf, offset, count, &total); 730ca94dbc7SKevin Wolf else if (bflag) 731ca94dbc7SKevin Wolf cnt = do_save_vmstate(buf, offset, count, &total); 732e3aff4f6Saliguori else 733e3aff4f6Saliguori cnt = do_write(buf, offset, count, &total); 734e3aff4f6Saliguori gettimeofday(&t2, NULL); 735e3aff4f6Saliguori 736e3aff4f6Saliguori if (cnt < 0) { 737e3aff4f6Saliguori printf("write failed: %s\n", strerror(-cnt)); 7387d8abfcbSKevin Wolf goto out; 739e3aff4f6Saliguori } 740e3aff4f6Saliguori 741e3aff4f6Saliguori if (qflag) 7427d8abfcbSKevin Wolf goto out; 743e3aff4f6Saliguori 744e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 745e3aff4f6Saliguori t2 = tsub(t2, t1); 746e3aff4f6Saliguori print_report("wrote", &t2, offset, count, total, cnt, Cflag); 747e3aff4f6Saliguori 7487d8abfcbSKevin Wolf out: 749e3aff4f6Saliguori qemu_io_free(buf); 750e3aff4f6Saliguori 751e3aff4f6Saliguori return 0; 752e3aff4f6Saliguori } 753e3aff4f6Saliguori 754e3aff4f6Saliguori static void 755e3aff4f6Saliguori writev_help(void) 756e3aff4f6Saliguori { 757e3aff4f6Saliguori printf( 758e3aff4f6Saliguori "\n" 759e3aff4f6Saliguori " writes a range of bytes from the given offset source from multiple buffers\n" 760e3aff4f6Saliguori "\n" 761e3aff4f6Saliguori " Example:\n" 762e3aff4f6Saliguori " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 763e3aff4f6Saliguori "\n" 764e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 765e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 766e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 767e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 768095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 769e3aff4f6Saliguori "\n"); 770e3aff4f6Saliguori } 771e3aff4f6Saliguori 77222a2bdcbSBlue Swirl static int writev_f(int argc, char **argv); 77322a2bdcbSBlue Swirl 77422a2bdcbSBlue Swirl static const cmdinfo_t writev_cmd = { 77522a2bdcbSBlue Swirl .name = "writev", 77622a2bdcbSBlue Swirl .cfunc = writev_f, 77722a2bdcbSBlue Swirl .argmin = 2, 77822a2bdcbSBlue Swirl .argmax = -1, 77922a2bdcbSBlue Swirl .args = "[-Cq] [-P pattern ] off len [len..]", 78022a2bdcbSBlue Swirl .oneline = "writes a number of bytes at a specified offset", 78122a2bdcbSBlue Swirl .help = writev_help, 78222a2bdcbSBlue Swirl }; 78322a2bdcbSBlue Swirl 784e3aff4f6Saliguori static int 785e3aff4f6Saliguori writev_f(int argc, char **argv) 786e3aff4f6Saliguori { 787e3aff4f6Saliguori struct timeval t1, t2; 788e3aff4f6Saliguori int Cflag = 0, qflag = 0; 789e3aff4f6Saliguori int c, cnt; 790cf57298aSChristoph Hellwig char *buf; 791e3aff4f6Saliguori int64_t offset; 7926474bd69SBlue Swirl /* Some compilers get confused and warn if this is not initialized. */ 7936474bd69SBlue Swirl int total = 0; 794cf57298aSChristoph Hellwig int nr_iov; 795e3aff4f6Saliguori int pattern = 0xcd; 796e3aff4f6Saliguori QEMUIOVector qiov; 797e3aff4f6Saliguori 798e3aff4f6Saliguori while ((c = getopt(argc, argv, "CqP:")) != EOF) { 799e3aff4f6Saliguori switch (c) { 800e3aff4f6Saliguori case 'C': 801e3aff4f6Saliguori Cflag = 1; 802e3aff4f6Saliguori break; 803e3aff4f6Saliguori case 'q': 804e3aff4f6Saliguori qflag = 1; 805e3aff4f6Saliguori break; 806e3aff4f6Saliguori case 'P': 807cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 808cf070d7eSChristoph Hellwig if (pattern < 0) 809cf070d7eSChristoph Hellwig return 0; 810e3aff4f6Saliguori break; 811e3aff4f6Saliguori default: 812e3aff4f6Saliguori return command_usage(&writev_cmd); 813e3aff4f6Saliguori } 814e3aff4f6Saliguori } 815e3aff4f6Saliguori 816e3aff4f6Saliguori if (optind > argc - 2) 817e3aff4f6Saliguori return command_usage(&writev_cmd); 818e3aff4f6Saliguori 819e3aff4f6Saliguori offset = cvtnum(argv[optind]); 820e3aff4f6Saliguori if (offset < 0) { 821e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 822e3aff4f6Saliguori return 0; 823e3aff4f6Saliguori } 824e3aff4f6Saliguori optind++; 825e3aff4f6Saliguori 826e3aff4f6Saliguori if (offset & 0x1ff) { 8270bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 8280bfcd599SBlue Swirl offset); 829e3aff4f6Saliguori return 0; 830e3aff4f6Saliguori } 831e3aff4f6Saliguori 832e3aff4f6Saliguori nr_iov = argc - optind; 833cf57298aSChristoph Hellwig buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); 834e3aff4f6Saliguori 835e3aff4f6Saliguori gettimeofday(&t1, NULL); 836e3aff4f6Saliguori cnt = do_aio_writev(&qiov, offset, &total); 837e3aff4f6Saliguori gettimeofday(&t2, NULL); 838e3aff4f6Saliguori 839e3aff4f6Saliguori if (cnt < 0) { 840e3aff4f6Saliguori printf("writev failed: %s\n", strerror(-cnt)); 8417d8abfcbSKevin Wolf goto out; 842e3aff4f6Saliguori } 843e3aff4f6Saliguori 844e3aff4f6Saliguori if (qflag) 8457d8abfcbSKevin Wolf goto out; 846e3aff4f6Saliguori 847e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 848e3aff4f6Saliguori t2 = tsub(t2, t1); 849e3aff4f6Saliguori print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 8507d8abfcbSKevin Wolf out: 851e3aff4f6Saliguori qemu_io_free(buf); 852e3aff4f6Saliguori return 0; 853e3aff4f6Saliguori } 854e3aff4f6Saliguori 855776cbbbdSKevin Wolf static void 856776cbbbdSKevin Wolf multiwrite_help(void) 857776cbbbdSKevin Wolf { 858776cbbbdSKevin Wolf printf( 859776cbbbdSKevin Wolf "\n" 860776cbbbdSKevin Wolf " writes a range of bytes from the given offset source from multiple buffers,\n" 861776cbbbdSKevin Wolf " in a batch of requests that may be merged by qemu\n" 862776cbbbdSKevin Wolf "\n" 863776cbbbdSKevin Wolf " Example:\n" 864776cbbbdSKevin Wolf " 'multiwrite 512 1k 1k ; 4k 1k' \n" 865776cbbbdSKevin Wolf " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n" 866776cbbbdSKevin Wolf "\n" 867776cbbbdSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n" 868776cbbbdSKevin Wolf " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n" 869776cbbbdSKevin Wolf " by one for each request contained in the multiwrite command.\n" 870776cbbbdSKevin Wolf " -P, -- use different pattern to fill file\n" 871776cbbbdSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 872776cbbbdSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 873776cbbbdSKevin Wolf "\n"); 874776cbbbdSKevin Wolf } 875776cbbbdSKevin Wolf 876776cbbbdSKevin Wolf static int multiwrite_f(int argc, char **argv); 877776cbbbdSKevin Wolf 878776cbbbdSKevin Wolf static const cmdinfo_t multiwrite_cmd = { 879776cbbbdSKevin Wolf .name = "multiwrite", 880776cbbbdSKevin Wolf .cfunc = multiwrite_f, 881776cbbbdSKevin Wolf .argmin = 2, 882776cbbbdSKevin Wolf .argmax = -1, 883776cbbbdSKevin Wolf .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]", 884776cbbbdSKevin Wolf .oneline = "issues multiple write requests at once", 885776cbbbdSKevin Wolf .help = multiwrite_help, 886776cbbbdSKevin Wolf }; 887776cbbbdSKevin Wolf 888776cbbbdSKevin Wolf static int 889776cbbbdSKevin Wolf multiwrite_f(int argc, char **argv) 890776cbbbdSKevin Wolf { 891776cbbbdSKevin Wolf struct timeval t1, t2; 892776cbbbdSKevin Wolf int Cflag = 0, qflag = 0; 893776cbbbdSKevin Wolf int c, cnt; 894776cbbbdSKevin Wolf char **buf; 895776cbbbdSKevin Wolf int64_t offset, first_offset = 0; 896776cbbbdSKevin Wolf /* Some compilers get confused and warn if this is not initialized. */ 897776cbbbdSKevin Wolf int total = 0; 898776cbbbdSKevin Wolf int nr_iov; 899776cbbbdSKevin Wolf int nr_reqs; 900776cbbbdSKevin Wolf int pattern = 0xcd; 901776cbbbdSKevin Wolf QEMUIOVector *qiovs; 902776cbbbdSKevin Wolf int i; 903776cbbbdSKevin Wolf BlockRequest *reqs; 904776cbbbdSKevin Wolf 905776cbbbdSKevin Wolf while ((c = getopt(argc, argv, "CqP:")) != EOF) { 906776cbbbdSKevin Wolf switch (c) { 907776cbbbdSKevin Wolf case 'C': 908776cbbbdSKevin Wolf Cflag = 1; 909776cbbbdSKevin Wolf break; 910776cbbbdSKevin Wolf case 'q': 911776cbbbdSKevin Wolf qflag = 1; 912776cbbbdSKevin Wolf break; 913776cbbbdSKevin Wolf case 'P': 914776cbbbdSKevin Wolf pattern = parse_pattern(optarg); 915776cbbbdSKevin Wolf if (pattern < 0) 916776cbbbdSKevin Wolf return 0; 917776cbbbdSKevin Wolf break; 918776cbbbdSKevin Wolf default: 919776cbbbdSKevin Wolf return command_usage(&writev_cmd); 920776cbbbdSKevin Wolf } 921776cbbbdSKevin Wolf } 922776cbbbdSKevin Wolf 923776cbbbdSKevin Wolf if (optind > argc - 2) 924776cbbbdSKevin Wolf return command_usage(&writev_cmd); 925776cbbbdSKevin Wolf 926776cbbbdSKevin Wolf nr_reqs = 1; 927776cbbbdSKevin Wolf for (i = optind; i < argc; i++) { 928776cbbbdSKevin Wolf if (!strcmp(argv[i], ";")) { 929776cbbbdSKevin Wolf nr_reqs++; 930776cbbbdSKevin Wolf } 931776cbbbdSKevin Wolf } 932776cbbbdSKevin Wolf 933776cbbbdSKevin Wolf reqs = qemu_malloc(nr_reqs * sizeof(*reqs)); 934776cbbbdSKevin Wolf buf = qemu_malloc(nr_reqs * sizeof(*buf)); 935776cbbbdSKevin Wolf qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs)); 936776cbbbdSKevin Wolf 937776cbbbdSKevin Wolf for (i = 0; i < nr_reqs; i++) { 938776cbbbdSKevin Wolf int j; 939776cbbbdSKevin Wolf 940776cbbbdSKevin Wolf /* Read the offset of the request */ 941776cbbbdSKevin Wolf offset = cvtnum(argv[optind]); 942776cbbbdSKevin Wolf if (offset < 0) { 943776cbbbdSKevin Wolf printf("non-numeric offset argument -- %s\n", argv[optind]); 944776cbbbdSKevin Wolf return 0; 945776cbbbdSKevin Wolf } 946776cbbbdSKevin Wolf optind++; 947776cbbbdSKevin Wolf 948776cbbbdSKevin Wolf if (offset & 0x1ff) { 949776cbbbdSKevin Wolf printf("offset %lld is not sector aligned\n", 950776cbbbdSKevin Wolf (long long)offset); 951776cbbbdSKevin Wolf return 0; 952776cbbbdSKevin Wolf } 953776cbbbdSKevin Wolf 954776cbbbdSKevin Wolf if (i == 0) { 955776cbbbdSKevin Wolf first_offset = offset; 956776cbbbdSKevin Wolf } 957776cbbbdSKevin Wolf 958776cbbbdSKevin Wolf /* Read lengths for qiov entries */ 959776cbbbdSKevin Wolf for (j = optind; j < argc; j++) { 960776cbbbdSKevin Wolf if (!strcmp(argv[j], ";")) { 961776cbbbdSKevin Wolf break; 962776cbbbdSKevin Wolf } 963776cbbbdSKevin Wolf } 964776cbbbdSKevin Wolf 965776cbbbdSKevin Wolf nr_iov = j - optind; 966776cbbbdSKevin Wolf 967776cbbbdSKevin Wolf /* Build request */ 968776cbbbdSKevin Wolf reqs[i].qiov = &qiovs[i]; 969776cbbbdSKevin Wolf buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern); 970776cbbbdSKevin Wolf reqs[i].sector = offset >> 9; 971776cbbbdSKevin Wolf reqs[i].nb_sectors = reqs[i].qiov->size >> 9; 972776cbbbdSKevin Wolf 973776cbbbdSKevin Wolf optind = j + 1; 974776cbbbdSKevin Wolf 975776cbbbdSKevin Wolf offset += reqs[i].qiov->size; 976776cbbbdSKevin Wolf pattern++; 977776cbbbdSKevin Wolf } 978776cbbbdSKevin Wolf 979776cbbbdSKevin Wolf gettimeofday(&t1, NULL); 980776cbbbdSKevin Wolf cnt = do_aio_multiwrite(reqs, nr_reqs, &total); 981776cbbbdSKevin Wolf gettimeofday(&t2, NULL); 982776cbbbdSKevin Wolf 983776cbbbdSKevin Wolf if (cnt < 0) { 984776cbbbdSKevin Wolf printf("aio_multiwrite failed: %s\n", strerror(-cnt)); 985776cbbbdSKevin Wolf goto out; 986776cbbbdSKevin Wolf } 987776cbbbdSKevin Wolf 988776cbbbdSKevin Wolf if (qflag) 989776cbbbdSKevin Wolf goto out; 990776cbbbdSKevin Wolf 991776cbbbdSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 992776cbbbdSKevin Wolf t2 = tsub(t2, t1); 993776cbbbdSKevin Wolf print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); 994776cbbbdSKevin Wolf out: 995776cbbbdSKevin Wolf for (i = 0; i < nr_reqs; i++) { 996776cbbbdSKevin Wolf qemu_io_free(buf[i]); 997776cbbbdSKevin Wolf qemu_iovec_destroy(&qiovs[i]); 998776cbbbdSKevin Wolf } 999776cbbbdSKevin Wolf qemu_free(buf); 1000776cbbbdSKevin Wolf qemu_free(reqs); 1001776cbbbdSKevin Wolf qemu_free(qiovs); 1002776cbbbdSKevin Wolf return 0; 1003776cbbbdSKevin Wolf } 1004776cbbbdSKevin Wolf 100595533d5fSChristoph Hellwig struct aio_ctx { 100695533d5fSChristoph Hellwig QEMUIOVector qiov; 100795533d5fSChristoph Hellwig int64_t offset; 100895533d5fSChristoph Hellwig char *buf; 100995533d5fSChristoph Hellwig int qflag; 101095533d5fSChristoph Hellwig int vflag; 101195533d5fSChristoph Hellwig int Cflag; 101295533d5fSChristoph Hellwig int Pflag; 101395533d5fSChristoph Hellwig int pattern; 101495533d5fSChristoph Hellwig struct timeval t1; 101595533d5fSChristoph Hellwig }; 101695533d5fSChristoph Hellwig 101795533d5fSChristoph Hellwig static void 101895533d5fSChristoph Hellwig aio_write_done(void *opaque, int ret) 101995533d5fSChristoph Hellwig { 102095533d5fSChristoph Hellwig struct aio_ctx *ctx = opaque; 102195533d5fSChristoph Hellwig struct timeval t2; 102295533d5fSChristoph Hellwig 102395533d5fSChristoph Hellwig gettimeofday(&t2, NULL); 102495533d5fSChristoph Hellwig 102595533d5fSChristoph Hellwig 102695533d5fSChristoph Hellwig if (ret < 0) { 102795533d5fSChristoph Hellwig printf("aio_write failed: %s\n", strerror(-ret)); 10287d8abfcbSKevin Wolf goto out; 102995533d5fSChristoph Hellwig } 103095533d5fSChristoph Hellwig 1031230d4fa4SChristoph Hellwig if (ctx->qflag) { 10327d8abfcbSKevin Wolf goto out; 1033230d4fa4SChristoph Hellwig } 103495533d5fSChristoph Hellwig 103595533d5fSChristoph Hellwig /* Finally, report back -- -C gives a parsable format */ 103695533d5fSChristoph Hellwig t2 = tsub(t2, ctx->t1); 1037230d4fa4SChristoph Hellwig print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1038230d4fa4SChristoph Hellwig ctx->qiov.size, 1, ctx->Cflag); 10397d8abfcbSKevin Wolf out: 104095533d5fSChristoph Hellwig qemu_io_free(ctx->buf); 104195533d5fSChristoph Hellwig free(ctx); 104295533d5fSChristoph Hellwig } 104395533d5fSChristoph Hellwig 104495533d5fSChristoph Hellwig static void 104595533d5fSChristoph Hellwig aio_read_done(void *opaque, int ret) 104695533d5fSChristoph Hellwig { 104795533d5fSChristoph Hellwig struct aio_ctx *ctx = opaque; 104895533d5fSChristoph Hellwig struct timeval t2; 104995533d5fSChristoph Hellwig 105095533d5fSChristoph Hellwig gettimeofday(&t2, NULL); 105195533d5fSChristoph Hellwig 105295533d5fSChristoph Hellwig if (ret < 0) { 105395533d5fSChristoph Hellwig printf("readv failed: %s\n", strerror(-ret)); 10547d8abfcbSKevin Wolf goto out; 105595533d5fSChristoph Hellwig } 105695533d5fSChristoph Hellwig 105795533d5fSChristoph Hellwig if (ctx->Pflag) { 1058230d4fa4SChristoph Hellwig void *cmp_buf = malloc(ctx->qiov.size); 105995533d5fSChristoph Hellwig 1060230d4fa4SChristoph Hellwig memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1061230d4fa4SChristoph Hellwig if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 10620bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 10630bfcd599SBlue Swirl PRId64 ", %zd bytes\n", 10640bfcd599SBlue Swirl ctx->offset, ctx->qiov.size); 106595533d5fSChristoph Hellwig } 106695533d5fSChristoph Hellwig free(cmp_buf); 106795533d5fSChristoph Hellwig } 106895533d5fSChristoph Hellwig 1069230d4fa4SChristoph Hellwig if (ctx->qflag) { 10707d8abfcbSKevin Wolf goto out; 1071230d4fa4SChristoph Hellwig } 107295533d5fSChristoph Hellwig 1073230d4fa4SChristoph Hellwig if (ctx->vflag) { 1074230d4fa4SChristoph Hellwig dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1075230d4fa4SChristoph Hellwig } 107695533d5fSChristoph Hellwig 107795533d5fSChristoph Hellwig /* Finally, report back -- -C gives a parsable format */ 107895533d5fSChristoph Hellwig t2 = tsub(t2, ctx->t1); 1079230d4fa4SChristoph Hellwig print_report("read", &t2, ctx->offset, ctx->qiov.size, 1080230d4fa4SChristoph Hellwig ctx->qiov.size, 1, ctx->Cflag); 10817d8abfcbSKevin Wolf out: 108295533d5fSChristoph Hellwig qemu_io_free(ctx->buf); 108395533d5fSChristoph Hellwig free(ctx); 108495533d5fSChristoph Hellwig } 108595533d5fSChristoph Hellwig 108695533d5fSChristoph Hellwig static void 108795533d5fSChristoph Hellwig aio_read_help(void) 108895533d5fSChristoph Hellwig { 108995533d5fSChristoph Hellwig printf( 109095533d5fSChristoph Hellwig "\n" 109195533d5fSChristoph Hellwig " asynchronously reads a range of bytes from the given offset\n" 109295533d5fSChristoph Hellwig "\n" 109395533d5fSChristoph Hellwig " Example:\n" 109495533d5fSChristoph Hellwig " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 109595533d5fSChristoph Hellwig "\n" 109695533d5fSChristoph Hellwig " Reads a segment of the currently open file, optionally dumping it to the\n" 109795533d5fSChristoph Hellwig " standard output stream (with -v option) for subsequent inspection.\n" 1098e432cef9SChristoph Hellwig " The read is performed asynchronously and the aio_flush command must be\n" 1099e432cef9SChristoph Hellwig " used to ensure all outstanding aio requests have been completed\n" 110095533d5fSChristoph Hellwig " -C, -- report statistics in a machine parsable format\n" 110195533d5fSChristoph Hellwig " -P, -- use a pattern to verify read data\n" 110295533d5fSChristoph Hellwig " -v, -- dump buffer to standard output\n" 1103095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 110495533d5fSChristoph Hellwig "\n"); 110595533d5fSChristoph Hellwig } 110695533d5fSChristoph Hellwig 110722a2bdcbSBlue Swirl static int aio_read_f(int argc, char **argv); 110822a2bdcbSBlue Swirl 110922a2bdcbSBlue Swirl static const cmdinfo_t aio_read_cmd = { 111022a2bdcbSBlue Swirl .name = "aio_read", 111122a2bdcbSBlue Swirl .cfunc = aio_read_f, 111222a2bdcbSBlue Swirl .argmin = 2, 111322a2bdcbSBlue Swirl .argmax = -1, 111422a2bdcbSBlue Swirl .args = "[-Cqv] [-P pattern ] off len [len..]", 111522a2bdcbSBlue Swirl .oneline = "asynchronously reads a number of bytes", 111622a2bdcbSBlue Swirl .help = aio_read_help, 111722a2bdcbSBlue Swirl }; 111822a2bdcbSBlue Swirl 111995533d5fSChristoph Hellwig static int 112095533d5fSChristoph Hellwig aio_read_f(int argc, char **argv) 112195533d5fSChristoph Hellwig { 1122cf57298aSChristoph Hellwig int nr_iov, c; 112395533d5fSChristoph Hellwig struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 112495533d5fSChristoph Hellwig BlockDriverAIOCB *acb; 112595533d5fSChristoph Hellwig 112695533d5fSChristoph Hellwig while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 112795533d5fSChristoph Hellwig switch (c) { 112895533d5fSChristoph Hellwig case 'C': 112995533d5fSChristoph Hellwig ctx->Cflag = 1; 113095533d5fSChristoph Hellwig break; 113195533d5fSChristoph Hellwig case 'P': 113295533d5fSChristoph Hellwig ctx->Pflag = 1; 1133cf070d7eSChristoph Hellwig ctx->pattern = parse_pattern(optarg); 1134*1afec913SBlue Swirl if (ctx->pattern < 0) { 1135*1afec913SBlue Swirl free(ctx); 1136cf070d7eSChristoph Hellwig return 0; 1137*1afec913SBlue Swirl } 113895533d5fSChristoph Hellwig break; 113995533d5fSChristoph Hellwig case 'q': 114095533d5fSChristoph Hellwig ctx->qflag = 1; 114195533d5fSChristoph Hellwig break; 114295533d5fSChristoph Hellwig case 'v': 114395533d5fSChristoph Hellwig ctx->vflag = 1; 114495533d5fSChristoph Hellwig break; 114595533d5fSChristoph Hellwig default: 11467d8abfcbSKevin Wolf free(ctx); 114795533d5fSChristoph Hellwig return command_usage(&aio_read_cmd); 114895533d5fSChristoph Hellwig } 114995533d5fSChristoph Hellwig } 115095533d5fSChristoph Hellwig 11517d8abfcbSKevin Wolf if (optind > argc - 2) { 11527d8abfcbSKevin Wolf free(ctx); 115395533d5fSChristoph Hellwig return command_usage(&aio_read_cmd); 11547d8abfcbSKevin Wolf } 115595533d5fSChristoph Hellwig 115695533d5fSChristoph Hellwig ctx->offset = cvtnum(argv[optind]); 115795533d5fSChristoph Hellwig if (ctx->offset < 0) { 115895533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[optind]); 11597d8abfcbSKevin Wolf free(ctx); 116095533d5fSChristoph Hellwig return 0; 116195533d5fSChristoph Hellwig } 116295533d5fSChristoph Hellwig optind++; 116395533d5fSChristoph Hellwig 116495533d5fSChristoph Hellwig if (ctx->offset & 0x1ff) { 11650bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 11660bfcd599SBlue Swirl ctx->offset); 11677d8abfcbSKevin Wolf free(ctx); 116895533d5fSChristoph Hellwig return 0; 116995533d5fSChristoph Hellwig } 117095533d5fSChristoph Hellwig 117195533d5fSChristoph Hellwig nr_iov = argc - optind; 1172cf57298aSChristoph Hellwig ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); 117395533d5fSChristoph Hellwig 117495533d5fSChristoph Hellwig gettimeofday(&ctx->t1, NULL); 117595533d5fSChristoph Hellwig acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 117695533d5fSChristoph Hellwig ctx->qiov.size >> 9, aio_read_done, ctx); 11777d8abfcbSKevin Wolf if (!acb) { 11787d8abfcbSKevin Wolf free(ctx->buf); 11797d8abfcbSKevin Wolf free(ctx); 118095533d5fSChristoph Hellwig return -EIO; 11817d8abfcbSKevin Wolf } 118295533d5fSChristoph Hellwig 118395533d5fSChristoph Hellwig return 0; 118495533d5fSChristoph Hellwig } 118595533d5fSChristoph Hellwig 118695533d5fSChristoph Hellwig static void 118795533d5fSChristoph Hellwig aio_write_help(void) 118895533d5fSChristoph Hellwig { 118995533d5fSChristoph Hellwig printf( 119095533d5fSChristoph Hellwig "\n" 119195533d5fSChristoph Hellwig " asynchronously writes a range of bytes from the given offset source \n" 119295533d5fSChristoph Hellwig " from multiple buffers\n" 119395533d5fSChristoph Hellwig "\n" 119495533d5fSChristoph Hellwig " Example:\n" 119595533d5fSChristoph Hellwig " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 119695533d5fSChristoph Hellwig "\n" 119795533d5fSChristoph Hellwig " Writes into a segment of the currently open file, using a buffer\n" 119895533d5fSChristoph Hellwig " filled with a set pattern (0xcdcdcdcd).\n" 1199e432cef9SChristoph Hellwig " The write is performed asynchronously and the aio_flush command must be\n" 1200e432cef9SChristoph Hellwig " used to ensure all outstanding aio requests have been completed\n" 120195533d5fSChristoph Hellwig " -P, -- use different pattern to fill file\n" 120295533d5fSChristoph Hellwig " -C, -- report statistics in a machine parsable format\n" 1203095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 120495533d5fSChristoph Hellwig "\n"); 120595533d5fSChristoph Hellwig } 120695533d5fSChristoph Hellwig 120722a2bdcbSBlue Swirl static int aio_write_f(int argc, char **argv); 120822a2bdcbSBlue Swirl 120922a2bdcbSBlue Swirl static const cmdinfo_t aio_write_cmd = { 121022a2bdcbSBlue Swirl .name = "aio_write", 121122a2bdcbSBlue Swirl .cfunc = aio_write_f, 121222a2bdcbSBlue Swirl .argmin = 2, 121322a2bdcbSBlue Swirl .argmax = -1, 121422a2bdcbSBlue Swirl .args = "[-Cq] [-P pattern ] off len [len..]", 121522a2bdcbSBlue Swirl .oneline = "asynchronously writes a number of bytes", 121622a2bdcbSBlue Swirl .help = aio_write_help, 121722a2bdcbSBlue Swirl }; 121895533d5fSChristoph Hellwig 121995533d5fSChristoph Hellwig static int 122095533d5fSChristoph Hellwig aio_write_f(int argc, char **argv) 122195533d5fSChristoph Hellwig { 1222cf57298aSChristoph Hellwig int nr_iov, c; 122395533d5fSChristoph Hellwig int pattern = 0xcd; 122495533d5fSChristoph Hellwig struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 122595533d5fSChristoph Hellwig BlockDriverAIOCB *acb; 122695533d5fSChristoph Hellwig 122795533d5fSChristoph Hellwig while ((c = getopt(argc, argv, "CqP:")) != EOF) { 122895533d5fSChristoph Hellwig switch (c) { 122995533d5fSChristoph Hellwig case 'C': 123095533d5fSChristoph Hellwig ctx->Cflag = 1; 123195533d5fSChristoph Hellwig break; 123295533d5fSChristoph Hellwig case 'q': 123395533d5fSChristoph Hellwig ctx->qflag = 1; 123495533d5fSChristoph Hellwig break; 123595533d5fSChristoph Hellwig case 'P': 1236cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 1237cf070d7eSChristoph Hellwig if (pattern < 0) 1238cf070d7eSChristoph Hellwig return 0; 123995533d5fSChristoph Hellwig break; 124095533d5fSChristoph Hellwig default: 12417d8abfcbSKevin Wolf free(ctx); 124295533d5fSChristoph Hellwig return command_usage(&aio_write_cmd); 124395533d5fSChristoph Hellwig } 124495533d5fSChristoph Hellwig } 124595533d5fSChristoph Hellwig 12467d8abfcbSKevin Wolf if (optind > argc - 2) { 12477d8abfcbSKevin Wolf free(ctx); 124895533d5fSChristoph Hellwig return command_usage(&aio_write_cmd); 12497d8abfcbSKevin Wolf } 125095533d5fSChristoph Hellwig 125195533d5fSChristoph Hellwig ctx->offset = cvtnum(argv[optind]); 125295533d5fSChristoph Hellwig if (ctx->offset < 0) { 125395533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[optind]); 12547d8abfcbSKevin Wolf free(ctx); 125595533d5fSChristoph Hellwig return 0; 125695533d5fSChristoph Hellwig } 125795533d5fSChristoph Hellwig optind++; 125895533d5fSChristoph Hellwig 125995533d5fSChristoph Hellwig if (ctx->offset & 0x1ff) { 12600bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 12610bfcd599SBlue Swirl ctx->offset); 12627d8abfcbSKevin Wolf free(ctx); 126395533d5fSChristoph Hellwig return 0; 126495533d5fSChristoph Hellwig } 126595533d5fSChristoph Hellwig 126695533d5fSChristoph Hellwig nr_iov = argc - optind; 1267cf57298aSChristoph Hellwig ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); 126895533d5fSChristoph Hellwig 126995533d5fSChristoph Hellwig gettimeofday(&ctx->t1, NULL); 127095533d5fSChristoph Hellwig acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 127195533d5fSChristoph Hellwig ctx->qiov.size >> 9, aio_write_done, ctx); 12727d8abfcbSKevin Wolf if (!acb) { 12737d8abfcbSKevin Wolf free(ctx->buf); 12747d8abfcbSKevin Wolf free(ctx); 127595533d5fSChristoph Hellwig return -EIO; 12767d8abfcbSKevin Wolf } 127795533d5fSChristoph Hellwig 127895533d5fSChristoph Hellwig return 0; 127995533d5fSChristoph Hellwig } 128095533d5fSChristoph Hellwig 128195533d5fSChristoph Hellwig static int 128295533d5fSChristoph Hellwig aio_flush_f(int argc, char **argv) 128395533d5fSChristoph Hellwig { 128495533d5fSChristoph Hellwig qemu_aio_flush(); 128595533d5fSChristoph Hellwig return 0; 128695533d5fSChristoph Hellwig } 128795533d5fSChristoph Hellwig 128895533d5fSChristoph Hellwig static const cmdinfo_t aio_flush_cmd = { 128995533d5fSChristoph Hellwig .name = "aio_flush", 129095533d5fSChristoph Hellwig .cfunc = aio_flush_f, 1291e432cef9SChristoph Hellwig .oneline = "completes all outstanding aio requests" 129295533d5fSChristoph Hellwig }; 129395533d5fSChristoph Hellwig 1294e3aff4f6Saliguori static int 1295e3aff4f6Saliguori flush_f(int argc, char **argv) 1296e3aff4f6Saliguori { 1297e3aff4f6Saliguori bdrv_flush(bs); 1298e3aff4f6Saliguori return 0; 1299e3aff4f6Saliguori } 1300e3aff4f6Saliguori 1301e3aff4f6Saliguori static const cmdinfo_t flush_cmd = { 1302e3aff4f6Saliguori .name = "flush", 1303e3aff4f6Saliguori .altname = "f", 1304e3aff4f6Saliguori .cfunc = flush_f, 1305e3aff4f6Saliguori .oneline = "flush all in-core file state to disk", 1306e3aff4f6Saliguori }; 1307e3aff4f6Saliguori 1308e3aff4f6Saliguori static int 1309e3aff4f6Saliguori truncate_f(int argc, char **argv) 1310e3aff4f6Saliguori { 1311e3aff4f6Saliguori int64_t offset; 1312e3aff4f6Saliguori int ret; 1313e3aff4f6Saliguori 1314e3aff4f6Saliguori offset = cvtnum(argv[1]); 1315e3aff4f6Saliguori if (offset < 0) { 1316e3aff4f6Saliguori printf("non-numeric truncate argument -- %s\n", argv[1]); 1317e3aff4f6Saliguori return 0; 1318e3aff4f6Saliguori } 1319e3aff4f6Saliguori 1320e3aff4f6Saliguori ret = bdrv_truncate(bs, offset); 1321e3aff4f6Saliguori if (ret < 0) { 13220923c577SKevin Wolf printf("truncate: %s\n", strerror(-ret)); 1323e3aff4f6Saliguori return 0; 1324e3aff4f6Saliguori } 1325e3aff4f6Saliguori 1326e3aff4f6Saliguori return 0; 1327e3aff4f6Saliguori } 1328e3aff4f6Saliguori 1329e3aff4f6Saliguori static const cmdinfo_t truncate_cmd = { 1330e3aff4f6Saliguori .name = "truncate", 1331e3aff4f6Saliguori .altname = "t", 1332e3aff4f6Saliguori .cfunc = truncate_f, 1333e3aff4f6Saliguori .argmin = 1, 1334e3aff4f6Saliguori .argmax = 1, 1335e3aff4f6Saliguori .args = "off", 1336e3aff4f6Saliguori .oneline = "truncates the current file at the given offset", 1337e3aff4f6Saliguori }; 1338e3aff4f6Saliguori 1339e3aff4f6Saliguori static int 1340e3aff4f6Saliguori length_f(int argc, char **argv) 1341e3aff4f6Saliguori { 1342e3aff4f6Saliguori int64_t size; 1343e3aff4f6Saliguori char s1[64]; 1344e3aff4f6Saliguori 1345e3aff4f6Saliguori size = bdrv_getlength(bs); 1346e3aff4f6Saliguori if (size < 0) { 13470923c577SKevin Wolf printf("getlength: %s\n", strerror(-size)); 1348e3aff4f6Saliguori return 0; 1349e3aff4f6Saliguori } 1350e3aff4f6Saliguori 1351e3aff4f6Saliguori cvtstr(size, s1, sizeof(s1)); 1352e3aff4f6Saliguori printf("%s\n", s1); 1353e3aff4f6Saliguori return 0; 1354e3aff4f6Saliguori } 1355e3aff4f6Saliguori 1356e3aff4f6Saliguori 1357e3aff4f6Saliguori static const cmdinfo_t length_cmd = { 1358e3aff4f6Saliguori .name = "length", 1359e3aff4f6Saliguori .altname = "l", 1360e3aff4f6Saliguori .cfunc = length_f, 1361e3aff4f6Saliguori .oneline = "gets the length of the current file", 1362e3aff4f6Saliguori }; 1363e3aff4f6Saliguori 1364e3aff4f6Saliguori 1365e3aff4f6Saliguori static int 1366e3aff4f6Saliguori info_f(int argc, char **argv) 1367e3aff4f6Saliguori { 1368e3aff4f6Saliguori BlockDriverInfo bdi; 1369e3aff4f6Saliguori char s1[64], s2[64]; 1370e3aff4f6Saliguori int ret; 1371e3aff4f6Saliguori 1372e3aff4f6Saliguori if (bs->drv && bs->drv->format_name) 1373e3aff4f6Saliguori printf("format name: %s\n", bs->drv->format_name); 1374e3aff4f6Saliguori if (bs->drv && bs->drv->protocol_name) 1375e3aff4f6Saliguori printf("format name: %s\n", bs->drv->protocol_name); 1376e3aff4f6Saliguori 1377e3aff4f6Saliguori ret = bdrv_get_info(bs, &bdi); 1378e3aff4f6Saliguori if (ret) 1379e3aff4f6Saliguori return 0; 1380e3aff4f6Saliguori 1381e3aff4f6Saliguori cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1382e3aff4f6Saliguori cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1383e3aff4f6Saliguori 1384e3aff4f6Saliguori printf("cluster size: %s\n", s1); 1385e3aff4f6Saliguori printf("vm state offset: %s\n", s2); 1386e3aff4f6Saliguori 1387e3aff4f6Saliguori return 0; 1388e3aff4f6Saliguori } 1389e3aff4f6Saliguori 1390e3aff4f6Saliguori 1391e3aff4f6Saliguori 1392e3aff4f6Saliguori static const cmdinfo_t info_cmd = { 1393e3aff4f6Saliguori .name = "info", 1394e3aff4f6Saliguori .altname = "i", 1395e3aff4f6Saliguori .cfunc = info_f, 1396e3aff4f6Saliguori .oneline = "prints information about the current file", 1397e3aff4f6Saliguori }; 1398e3aff4f6Saliguori 1399edff5db1SStefan Hajnoczi static void 1400edff5db1SStefan Hajnoczi discard_help(void) 1401edff5db1SStefan Hajnoczi { 1402edff5db1SStefan Hajnoczi printf( 1403edff5db1SStefan Hajnoczi "\n" 1404edff5db1SStefan Hajnoczi " discards a range of bytes from the given offset\n" 1405edff5db1SStefan Hajnoczi "\n" 1406edff5db1SStefan Hajnoczi " Example:\n" 1407edff5db1SStefan Hajnoczi " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n" 1408edff5db1SStefan Hajnoczi "\n" 1409edff5db1SStefan Hajnoczi " Discards a segment of the currently open file.\n" 1410edff5db1SStefan Hajnoczi " -C, -- report statistics in a machine parsable format\n" 1411095343adSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 1412edff5db1SStefan Hajnoczi "\n"); 1413edff5db1SStefan Hajnoczi } 1414edff5db1SStefan Hajnoczi 1415edff5db1SStefan Hajnoczi static int discard_f(int argc, char **argv); 1416edff5db1SStefan Hajnoczi 1417edff5db1SStefan Hajnoczi static const cmdinfo_t discard_cmd = { 1418edff5db1SStefan Hajnoczi .name = "discard", 1419edff5db1SStefan Hajnoczi .altname = "d", 1420edff5db1SStefan Hajnoczi .cfunc = discard_f, 1421edff5db1SStefan Hajnoczi .argmin = 2, 1422edff5db1SStefan Hajnoczi .argmax = -1, 1423edff5db1SStefan Hajnoczi .args = "[-Cq] off len", 1424edff5db1SStefan Hajnoczi .oneline = "discards a number of bytes at a specified offset", 1425edff5db1SStefan Hajnoczi .help = discard_help, 1426edff5db1SStefan Hajnoczi }; 1427edff5db1SStefan Hajnoczi 1428edff5db1SStefan Hajnoczi static int 1429edff5db1SStefan Hajnoczi discard_f(int argc, char **argv) 1430edff5db1SStefan Hajnoczi { 1431edff5db1SStefan Hajnoczi struct timeval t1, t2; 1432edff5db1SStefan Hajnoczi int Cflag = 0, qflag = 0; 1433edff5db1SStefan Hajnoczi int c, ret; 1434edff5db1SStefan Hajnoczi int64_t offset; 1435edff5db1SStefan Hajnoczi int count; 1436edff5db1SStefan Hajnoczi 1437edff5db1SStefan Hajnoczi while ((c = getopt(argc, argv, "Cq")) != EOF) { 1438edff5db1SStefan Hajnoczi switch (c) { 1439edff5db1SStefan Hajnoczi case 'C': 1440edff5db1SStefan Hajnoczi Cflag = 1; 1441edff5db1SStefan Hajnoczi break; 1442edff5db1SStefan Hajnoczi case 'q': 1443edff5db1SStefan Hajnoczi qflag = 1; 1444edff5db1SStefan Hajnoczi break; 1445edff5db1SStefan Hajnoczi default: 1446edff5db1SStefan Hajnoczi return command_usage(&discard_cmd); 1447edff5db1SStefan Hajnoczi } 1448edff5db1SStefan Hajnoczi } 1449edff5db1SStefan Hajnoczi 1450edff5db1SStefan Hajnoczi if (optind != argc - 2) { 1451edff5db1SStefan Hajnoczi return command_usage(&discard_cmd); 1452edff5db1SStefan Hajnoczi } 1453edff5db1SStefan Hajnoczi 1454edff5db1SStefan Hajnoczi offset = cvtnum(argv[optind]); 1455edff5db1SStefan Hajnoczi if (offset < 0) { 1456edff5db1SStefan Hajnoczi printf("non-numeric length argument -- %s\n", argv[optind]); 1457edff5db1SStefan Hajnoczi return 0; 1458edff5db1SStefan Hajnoczi } 1459edff5db1SStefan Hajnoczi 1460edff5db1SStefan Hajnoczi optind++; 1461edff5db1SStefan Hajnoczi count = cvtnum(argv[optind]); 1462edff5db1SStefan Hajnoczi if (count < 0) { 1463edff5db1SStefan Hajnoczi printf("non-numeric length argument -- %s\n", argv[optind]); 1464edff5db1SStefan Hajnoczi return 0; 1465edff5db1SStefan Hajnoczi } 1466edff5db1SStefan Hajnoczi 1467edff5db1SStefan Hajnoczi gettimeofday(&t1, NULL); 1468edff5db1SStefan Hajnoczi ret = bdrv_discard(bs, offset, count); 1469edff5db1SStefan Hajnoczi gettimeofday(&t2, NULL); 1470edff5db1SStefan Hajnoczi 1471edff5db1SStefan Hajnoczi if (ret < 0) { 1472edff5db1SStefan Hajnoczi printf("discard failed: %s\n", strerror(-ret)); 1473edff5db1SStefan Hajnoczi goto out; 1474edff5db1SStefan Hajnoczi } 1475edff5db1SStefan Hajnoczi 1476edff5db1SStefan Hajnoczi /* Finally, report back -- -C gives a parsable format */ 1477edff5db1SStefan Hajnoczi if (!qflag) { 1478edff5db1SStefan Hajnoczi t2 = tsub(t2, t1); 1479edff5db1SStefan Hajnoczi print_report("discard", &t2, offset, count, count, 1, Cflag); 1480edff5db1SStefan Hajnoczi } 1481edff5db1SStefan Hajnoczi 1482edff5db1SStefan Hajnoczi out: 1483edff5db1SStefan Hajnoczi return 0; 1484edff5db1SStefan Hajnoczi } 1485edff5db1SStefan Hajnoczi 1486e3aff4f6Saliguori static int 1487e3aff4f6Saliguori alloc_f(int argc, char **argv) 1488e3aff4f6Saliguori { 1489e3aff4f6Saliguori int64_t offset; 1490a7824a88SKevin Wolf int nb_sectors, remaining; 1491e3aff4f6Saliguori char s1[64]; 1492a7824a88SKevin Wolf int num, sum_alloc; 1493e3aff4f6Saliguori int ret; 1494e3aff4f6Saliguori 1495e3aff4f6Saliguori offset = cvtnum(argv[1]); 1496e3aff4f6Saliguori if (offset & 0x1ff) { 14970bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 14980bfcd599SBlue Swirl offset); 1499e3aff4f6Saliguori return 0; 1500e3aff4f6Saliguori } 1501e3aff4f6Saliguori 1502e3aff4f6Saliguori if (argc == 3) 1503e3aff4f6Saliguori nb_sectors = cvtnum(argv[2]); 1504e3aff4f6Saliguori else 1505e3aff4f6Saliguori nb_sectors = 1; 1506e3aff4f6Saliguori 1507a7824a88SKevin Wolf remaining = nb_sectors; 1508a7824a88SKevin Wolf sum_alloc = 0; 1509a7824a88SKevin Wolf while (remaining) { 1510e3aff4f6Saliguori ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); 1511a7824a88SKevin Wolf remaining -= num; 1512a7824a88SKevin Wolf if (ret) { 1513a7824a88SKevin Wolf sum_alloc += num; 1514a7824a88SKevin Wolf } 1515a7824a88SKevin Wolf } 1516e3aff4f6Saliguori 1517e3aff4f6Saliguori cvtstr(offset, s1, sizeof(s1)); 1518e3aff4f6Saliguori 1519a7824a88SKevin Wolf printf("%d/%d sectors allocated at offset %s\n", 1520a7824a88SKevin Wolf sum_alloc, nb_sectors, s1); 1521e3aff4f6Saliguori return 0; 1522e3aff4f6Saliguori } 1523e3aff4f6Saliguori 1524e3aff4f6Saliguori static const cmdinfo_t alloc_cmd = { 1525e3aff4f6Saliguori .name = "alloc", 1526e3aff4f6Saliguori .altname = "a", 1527e3aff4f6Saliguori .argmin = 1, 1528e3aff4f6Saliguori .argmax = 2, 1529e3aff4f6Saliguori .cfunc = alloc_f, 1530e3aff4f6Saliguori .args = "off [sectors]", 1531e3aff4f6Saliguori .oneline = "checks if a sector is present in the file", 1532e3aff4f6Saliguori }; 1533e3aff4f6Saliguori 1534e3aff4f6Saliguori static int 1535191c2890SKevin Wolf map_f(int argc, char **argv) 1536191c2890SKevin Wolf { 1537191c2890SKevin Wolf int64_t offset; 1538191c2890SKevin Wolf int64_t nb_sectors; 1539191c2890SKevin Wolf char s1[64]; 1540191c2890SKevin Wolf int num, num_checked; 1541191c2890SKevin Wolf int ret; 1542191c2890SKevin Wolf const char *retstr; 1543191c2890SKevin Wolf 1544191c2890SKevin Wolf offset = 0; 1545191c2890SKevin Wolf nb_sectors = bs->total_sectors; 1546191c2890SKevin Wolf 1547191c2890SKevin Wolf do { 1548191c2890SKevin Wolf num_checked = MIN(nb_sectors, INT_MAX); 1549191c2890SKevin Wolf ret = bdrv_is_allocated(bs, offset, num_checked, &num); 1550191c2890SKevin Wolf retstr = ret ? " allocated" : "not allocated"; 1551191c2890SKevin Wolf cvtstr(offset << 9ULL, s1, sizeof(s1)); 1552191c2890SKevin Wolf printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n", 1553191c2890SKevin Wolf offset << 9ULL, num, num_checked, retstr, s1, ret); 1554191c2890SKevin Wolf 1555191c2890SKevin Wolf offset += num; 1556191c2890SKevin Wolf nb_sectors -= num; 1557191c2890SKevin Wolf } while(offset < bs->total_sectors); 1558191c2890SKevin Wolf 1559191c2890SKevin Wolf return 0; 1560191c2890SKevin Wolf } 1561191c2890SKevin Wolf 1562191c2890SKevin Wolf static const cmdinfo_t map_cmd = { 1563191c2890SKevin Wolf .name = "map", 1564191c2890SKevin Wolf .argmin = 0, 1565191c2890SKevin Wolf .argmax = 0, 1566191c2890SKevin Wolf .cfunc = map_f, 1567191c2890SKevin Wolf .args = "", 1568191c2890SKevin Wolf .oneline = "prints the allocated areas of a file", 1569191c2890SKevin Wolf }; 1570191c2890SKevin Wolf 1571191c2890SKevin Wolf 1572191c2890SKevin Wolf static int 1573e3aff4f6Saliguori close_f(int argc, char **argv) 1574e3aff4f6Saliguori { 1575e3aff4f6Saliguori bdrv_close(bs); 1576e3aff4f6Saliguori bs = NULL; 1577e3aff4f6Saliguori return 0; 1578e3aff4f6Saliguori } 1579e3aff4f6Saliguori 1580e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 1581e3aff4f6Saliguori .name = "close", 1582e3aff4f6Saliguori .altname = "c", 1583e3aff4f6Saliguori .cfunc = close_f, 1584e3aff4f6Saliguori .oneline = "close the current open file", 1585e3aff4f6Saliguori }; 1586e3aff4f6Saliguori 15879c4bab26SChristoph Hellwig static int openfile(char *name, int flags, int growable) 1588e3aff4f6Saliguori { 1589e3aff4f6Saliguori if (bs) { 1590e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 1591e3aff4f6Saliguori return 1; 1592e3aff4f6Saliguori } 1593e3aff4f6Saliguori 15946db95603SChristoph Hellwig if (growable) { 15956db95603SChristoph Hellwig if (bdrv_file_open(&bs, name, flags)) { 15966db95603SChristoph Hellwig fprintf(stderr, "%s: can't open device %s\n", progname, name); 15976db95603SChristoph Hellwig return 1; 15986db95603SChristoph Hellwig } 15996db95603SChristoph Hellwig } else { 1600e3aff4f6Saliguori bs = bdrv_new("hda"); 1601e3aff4f6Saliguori 1602d6e9098eSKevin Wolf if (bdrv_open(bs, name, flags, NULL) < 0) { 1603e3aff4f6Saliguori fprintf(stderr, "%s: can't open device %s\n", progname, name); 1604e3aff4f6Saliguori bs = NULL; 1605e3aff4f6Saliguori return 1; 1606e3aff4f6Saliguori } 16079c4bab26SChristoph Hellwig } 16086db95603SChristoph Hellwig 1609e3aff4f6Saliguori return 0; 1610e3aff4f6Saliguori } 1611e3aff4f6Saliguori 1612e3aff4f6Saliguori static void 1613e3aff4f6Saliguori open_help(void) 1614e3aff4f6Saliguori { 1615e3aff4f6Saliguori printf( 1616e3aff4f6Saliguori "\n" 1617e3aff4f6Saliguori " opens a new file in the requested mode\n" 1618e3aff4f6Saliguori "\n" 1619e3aff4f6Saliguori " Example:\n" 1620e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 1621e3aff4f6Saliguori "\n" 1622e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 1623e3aff4f6Saliguori " -r, -- open file read-only\n" 1624e3aff4f6Saliguori " -s, -- use snapshot file\n" 1625e3aff4f6Saliguori " -n, -- disable host cache\n" 16269c4bab26SChristoph Hellwig " -g, -- allow file to grow (only applies to protocols)" 1627e3aff4f6Saliguori "\n"); 1628e3aff4f6Saliguori } 1629e3aff4f6Saliguori 163022a2bdcbSBlue Swirl static int open_f(int argc, char **argv); 163122a2bdcbSBlue Swirl 163222a2bdcbSBlue Swirl static const cmdinfo_t open_cmd = { 163322a2bdcbSBlue Swirl .name = "open", 163422a2bdcbSBlue Swirl .altname = "o", 163522a2bdcbSBlue Swirl .cfunc = open_f, 163622a2bdcbSBlue Swirl .argmin = 1, 163722a2bdcbSBlue Swirl .argmax = -1, 163822a2bdcbSBlue Swirl .flags = CMD_NOFILE_OK, 163922a2bdcbSBlue Swirl .args = "[-Crsn] [path]", 164022a2bdcbSBlue Swirl .oneline = "open the file specified by path", 164122a2bdcbSBlue Swirl .help = open_help, 164222a2bdcbSBlue Swirl }; 1643e3aff4f6Saliguori 1644e3aff4f6Saliguori static int 1645e3aff4f6Saliguori open_f(int argc, char **argv) 1646e3aff4f6Saliguori { 1647e3aff4f6Saliguori int flags = 0; 1648e3aff4f6Saliguori int readonly = 0; 16499c4bab26SChristoph Hellwig int growable = 0; 1650e3aff4f6Saliguori int c; 1651e3aff4f6Saliguori 16529a2d77adSChristoph Hellwig while ((c = getopt(argc, argv, "snrg")) != EOF) { 1653e3aff4f6Saliguori switch (c) { 1654e3aff4f6Saliguori case 's': 1655e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1656e3aff4f6Saliguori break; 1657e3aff4f6Saliguori case 'n': 1658e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 1659e3aff4f6Saliguori break; 1660e3aff4f6Saliguori case 'r': 1661e3aff4f6Saliguori readonly = 1; 1662e3aff4f6Saliguori break; 16639c4bab26SChristoph Hellwig case 'g': 16649c4bab26SChristoph Hellwig growable = 1; 16659c4bab26SChristoph Hellwig break; 1666e3aff4f6Saliguori default: 1667e3aff4f6Saliguori return command_usage(&open_cmd); 1668e3aff4f6Saliguori } 1669e3aff4f6Saliguori } 1670e3aff4f6Saliguori 1671f5edb014SNaphtali Sprei if (!readonly) { 1672e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1673f5edb014SNaphtali Sprei } 1674e3aff4f6Saliguori 1675e3aff4f6Saliguori if (optind != argc - 1) 1676e3aff4f6Saliguori return command_usage(&open_cmd); 1677e3aff4f6Saliguori 16789c4bab26SChristoph Hellwig return openfile(argv[optind], flags, growable); 1679e3aff4f6Saliguori } 1680e3aff4f6Saliguori 1681e3aff4f6Saliguori static int 1682e3aff4f6Saliguori init_args_command( 1683e3aff4f6Saliguori int index) 1684e3aff4f6Saliguori { 1685e3aff4f6Saliguori /* only one device allowed so far */ 1686e3aff4f6Saliguori if (index >= 1) 1687e3aff4f6Saliguori return 0; 1688e3aff4f6Saliguori return ++index; 1689e3aff4f6Saliguori } 1690e3aff4f6Saliguori 1691e3aff4f6Saliguori static int 1692e3aff4f6Saliguori init_check_command( 1693e3aff4f6Saliguori const cmdinfo_t *ct) 1694e3aff4f6Saliguori { 1695e3aff4f6Saliguori if (ct->flags & CMD_FLAG_GLOBAL) 1696e3aff4f6Saliguori return 1; 1697e3aff4f6Saliguori if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1698e3aff4f6Saliguori fprintf(stderr, "no file open, try 'help open'\n"); 1699e3aff4f6Saliguori return 0; 1700e3aff4f6Saliguori } 1701e3aff4f6Saliguori return 1; 1702e3aff4f6Saliguori } 1703e3aff4f6Saliguori 1704e3aff4f6Saliguori static void usage(const char *name) 1705e3aff4f6Saliguori { 1706e3aff4f6Saliguori printf( 17079a2d77adSChristoph Hellwig "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" 170884844a20SStefan Weil "QEMU Disk exerciser\n" 1709e3aff4f6Saliguori "\n" 1710e3aff4f6Saliguori " -c, --cmd command to execute\n" 1711e3aff4f6Saliguori " -r, --read-only export read-only\n" 1712e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 1713e3aff4f6Saliguori " -n, --nocache disable host cache\n" 17141db6947dSChristoph Hellwig " -g, --growable allow file to grow (only applies to protocols)\n" 1715e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 17165c6c3a6cSChristoph Hellwig " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 1717e3aff4f6Saliguori " -h, --help display this help and exit\n" 1718e3aff4f6Saliguori " -V, --version output version information and exit\n" 1719e3aff4f6Saliguori "\n", 1720e3aff4f6Saliguori name); 1721e3aff4f6Saliguori } 1722e3aff4f6Saliguori 1723e3aff4f6Saliguori 1724e3aff4f6Saliguori int main(int argc, char **argv) 1725e3aff4f6Saliguori { 1726e3aff4f6Saliguori int readonly = 0; 17279c4bab26SChristoph Hellwig int growable = 0; 17289a2d77adSChristoph Hellwig const char *sopt = "hVc:rsnmgk"; 1729b32bb952SBlue Swirl const struct option lopt[] = { 1730660f11beSBlue Swirl { "help", 0, NULL, 'h' }, 1731660f11beSBlue Swirl { "version", 0, NULL, 'V' }, 1732660f11beSBlue Swirl { "offset", 1, NULL, 'o' }, 1733660f11beSBlue Swirl { "cmd", 1, NULL, 'c' }, 1734660f11beSBlue Swirl { "read-only", 0, NULL, 'r' }, 1735660f11beSBlue Swirl { "snapshot", 0, NULL, 's' }, 1736660f11beSBlue Swirl { "nocache", 0, NULL, 'n' }, 1737660f11beSBlue Swirl { "misalign", 0, NULL, 'm' }, 1738660f11beSBlue Swirl { "growable", 0, NULL, 'g' }, 17395c6c3a6cSChristoph Hellwig { "native-aio", 0, NULL, 'k' }, 1740660f11beSBlue Swirl { NULL, 0, NULL, 0 } 1741e3aff4f6Saliguori }; 1742e3aff4f6Saliguori int c; 1743e3aff4f6Saliguori int opt_index = 0; 1744e3aff4f6Saliguori int flags = 0; 1745e3aff4f6Saliguori 1746e3aff4f6Saliguori progname = basename(argv[0]); 1747e3aff4f6Saliguori 1748e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1749e3aff4f6Saliguori switch (c) { 1750e3aff4f6Saliguori case 's': 1751e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1752e3aff4f6Saliguori break; 1753e3aff4f6Saliguori case 'n': 1754e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 1755e3aff4f6Saliguori break; 1756e3aff4f6Saliguori case 'c': 1757e3aff4f6Saliguori add_user_command(optarg); 1758e3aff4f6Saliguori break; 1759e3aff4f6Saliguori case 'r': 1760e3aff4f6Saliguori readonly = 1; 1761e3aff4f6Saliguori break; 1762e3aff4f6Saliguori case 'm': 1763e3aff4f6Saliguori misalign = 1; 1764e3aff4f6Saliguori break; 17659c4bab26SChristoph Hellwig case 'g': 17669c4bab26SChristoph Hellwig growable = 1; 17679c4bab26SChristoph Hellwig break; 17685c6c3a6cSChristoph Hellwig case 'k': 17695c6c3a6cSChristoph Hellwig flags |= BDRV_O_NATIVE_AIO; 17705c6c3a6cSChristoph Hellwig break; 1771e3aff4f6Saliguori case 'V': 1772e3aff4f6Saliguori printf("%s version %s\n", progname, VERSION); 1773e3aff4f6Saliguori exit(0); 1774e3aff4f6Saliguori case 'h': 1775e3aff4f6Saliguori usage(progname); 1776e3aff4f6Saliguori exit(0); 1777e3aff4f6Saliguori default: 1778e3aff4f6Saliguori usage(progname); 1779e3aff4f6Saliguori exit(1); 1780e3aff4f6Saliguori } 1781e3aff4f6Saliguori } 1782e3aff4f6Saliguori 1783e3aff4f6Saliguori if ((argc - optind) > 1) { 1784e3aff4f6Saliguori usage(progname); 1785e3aff4f6Saliguori exit(1); 1786e3aff4f6Saliguori } 1787e3aff4f6Saliguori 1788e3aff4f6Saliguori bdrv_init(); 1789e3aff4f6Saliguori 1790e3aff4f6Saliguori /* initialize commands */ 1791e3aff4f6Saliguori quit_init(); 1792e3aff4f6Saliguori help_init(); 1793e3aff4f6Saliguori add_command(&open_cmd); 1794e3aff4f6Saliguori add_command(&close_cmd); 1795e3aff4f6Saliguori add_command(&read_cmd); 1796e3aff4f6Saliguori add_command(&readv_cmd); 1797e3aff4f6Saliguori add_command(&write_cmd); 1798e3aff4f6Saliguori add_command(&writev_cmd); 1799776cbbbdSKevin Wolf add_command(&multiwrite_cmd); 180095533d5fSChristoph Hellwig add_command(&aio_read_cmd); 180195533d5fSChristoph Hellwig add_command(&aio_write_cmd); 180295533d5fSChristoph Hellwig add_command(&aio_flush_cmd); 1803e3aff4f6Saliguori add_command(&flush_cmd); 1804e3aff4f6Saliguori add_command(&truncate_cmd); 1805e3aff4f6Saliguori add_command(&length_cmd); 1806e3aff4f6Saliguori add_command(&info_cmd); 1807edff5db1SStefan Hajnoczi add_command(&discard_cmd); 1808e3aff4f6Saliguori add_command(&alloc_cmd); 1809191c2890SKevin Wolf add_command(&map_cmd); 1810e3aff4f6Saliguori 1811e3aff4f6Saliguori add_args_command(init_args_command); 1812e3aff4f6Saliguori add_check_command(init_check_command); 1813e3aff4f6Saliguori 1814e3aff4f6Saliguori /* open the device */ 1815f5edb014SNaphtali Sprei if (!readonly) { 1816e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1817f5edb014SNaphtali Sprei } 1818e3aff4f6Saliguori 1819e3aff4f6Saliguori if ((argc - optind) == 1) 18209c4bab26SChristoph Hellwig openfile(argv[optind], flags, growable); 1821e3aff4f6Saliguori command_loop(); 1822e3aff4f6Saliguori 182395533d5fSChristoph Hellwig /* 182495533d5fSChristoph Hellwig * Make sure all outstanding requests get flushed the program exits. 182595533d5fSChristoph Hellwig */ 182695533d5fSChristoph Hellwig qemu_aio_flush(); 182795533d5fSChristoph Hellwig 1828e3aff4f6Saliguori if (bs) 1829e3aff4f6Saliguori bdrv_close(bs); 1830e3aff4f6Saliguori return 0; 1831e3aff4f6Saliguori } 1832