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; 64e3aff4f6Saliguori buf = qemu_memalign(512, 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 87*0bfcd599SBlue 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)); 111*0bfcd599SBlue Swirl printf("%s %d/%d bytes at offset %" PRId64 "\n", 112*0bfcd599SBlue 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]; 138*0bfcd599SBlue Swirl uint64_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 */ 147cf57298aSChristoph Hellwig if (len > UINT_MAX) { 148cf57298aSChristoph Hellwig printf("too large length argument -- %s\n", arg); 14940a0d7c3SKevin Wolf goto fail; 150cf57298aSChristoph Hellwig } 151cf57298aSChristoph Hellwig 152cf57298aSChristoph Hellwig if (len & 0x1ff) { 153*0bfcd599SBlue Swirl printf("length argument %" PRId64 154*0bfcd599SBlue 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 270e3aff4f6Saliguori 271e3aff4f6Saliguori static void 272e3aff4f6Saliguori read_help(void) 273e3aff4f6Saliguori { 274e3aff4f6Saliguori printf( 275e3aff4f6Saliguori "\n" 276e3aff4f6Saliguori " reads a range of bytes from the given offset\n" 277e3aff4f6Saliguori "\n" 278e3aff4f6Saliguori " Example:\n" 279e3aff4f6Saliguori " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 280e3aff4f6Saliguori "\n" 281e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 282e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 283ca94dbc7SKevin Wolf " -b, -- read from the VM state rather than the virtual disk\n" 284d9654a58SKevin Wolf " -C, -- report statistics in a machine parsable format\n" 285d9654a58SKevin Wolf " -l, -- length for pattern verification (only with -P)\n" 286e3aff4f6Saliguori " -p, -- use bdrv_pread to read the file\n" 287c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 288e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 289d9654a58SKevin Wolf " -s, -- start offset for pattern verification (only with -P)\n" 290d9654a58SKevin Wolf " -v, -- dump buffer to standard output\n" 291e3aff4f6Saliguori "\n"); 292e3aff4f6Saliguori } 293e3aff4f6Saliguori 29422a2bdcbSBlue Swirl static int read_f(int argc, char **argv); 29522a2bdcbSBlue Swirl 29622a2bdcbSBlue Swirl static const cmdinfo_t read_cmd = { 29722a2bdcbSBlue Swirl .name = "read", 29822a2bdcbSBlue Swirl .altname = "r", 29922a2bdcbSBlue Swirl .cfunc = read_f, 30022a2bdcbSBlue Swirl .argmin = 2, 30122a2bdcbSBlue Swirl .argmax = -1, 30222a2bdcbSBlue Swirl .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", 30322a2bdcbSBlue Swirl .oneline = "reads a number of bytes at a specified offset", 30422a2bdcbSBlue Swirl .help = read_help, 30522a2bdcbSBlue Swirl }; 30622a2bdcbSBlue Swirl 307e3aff4f6Saliguori static int 308e3aff4f6Saliguori read_f(int argc, char **argv) 309e3aff4f6Saliguori { 310e3aff4f6Saliguori struct timeval t1, t2; 311e3aff4f6Saliguori int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 312ca94dbc7SKevin Wolf int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; 313e3aff4f6Saliguori int c, cnt; 314e3aff4f6Saliguori char *buf; 315e3aff4f6Saliguori int64_t offset; 316d4ec5228SPaul Brook int count; 317d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 318d4ec5228SPaul Brook int total = 0; 319d9654a58SKevin Wolf int pattern = 0, pattern_offset = 0, pattern_count = 0; 320e3aff4f6Saliguori 321ca94dbc7SKevin Wolf while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { 322e3aff4f6Saliguori switch (c) { 323ca94dbc7SKevin Wolf case 'b': 324ca94dbc7SKevin Wolf bflag = 1; 325ca94dbc7SKevin Wolf break; 326e3aff4f6Saliguori case 'C': 327e3aff4f6Saliguori Cflag = 1; 328e3aff4f6Saliguori break; 329d9654a58SKevin Wolf case 'l': 330d9654a58SKevin Wolf lflag = 1; 331d9654a58SKevin Wolf pattern_count = cvtnum(optarg); 332d9654a58SKevin Wolf if (pattern_count < 0) { 333d9654a58SKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 334d9654a58SKevin Wolf return 0; 335d9654a58SKevin Wolf } 336d9654a58SKevin Wolf break; 337e3aff4f6Saliguori case 'p': 338e3aff4f6Saliguori pflag = 1; 339e3aff4f6Saliguori break; 340c48101aeSaliguori case 'P': 341c48101aeSaliguori Pflag = 1; 342cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 343cf070d7eSChristoph Hellwig if (pattern < 0) 344cf070d7eSChristoph Hellwig return 0; 345c48101aeSaliguori break; 346e3aff4f6Saliguori case 'q': 347e3aff4f6Saliguori qflag = 1; 348e3aff4f6Saliguori break; 349d9654a58SKevin Wolf case 's': 350d9654a58SKevin Wolf sflag = 1; 351d9654a58SKevin Wolf pattern_offset = cvtnum(optarg); 352d9654a58SKevin Wolf if (pattern_offset < 0) { 353d9654a58SKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 354d9654a58SKevin Wolf return 0; 355d9654a58SKevin Wolf } 356d9654a58SKevin Wolf break; 357e3aff4f6Saliguori case 'v': 358e3aff4f6Saliguori vflag = 1; 359e3aff4f6Saliguori break; 360e3aff4f6Saliguori default: 361e3aff4f6Saliguori return command_usage(&read_cmd); 362e3aff4f6Saliguori } 363e3aff4f6Saliguori } 364e3aff4f6Saliguori 365e3aff4f6Saliguori if (optind != argc - 2) 366e3aff4f6Saliguori return command_usage(&read_cmd); 367e3aff4f6Saliguori 368ca94dbc7SKevin Wolf if (bflag && pflag) { 369ca94dbc7SKevin Wolf printf("-b and -p cannot be specified at the same time\n"); 370ca94dbc7SKevin Wolf return 0; 371ca94dbc7SKevin Wolf } 372ca94dbc7SKevin Wolf 373e3aff4f6Saliguori offset = cvtnum(argv[optind]); 374e3aff4f6Saliguori if (offset < 0) { 375e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 376e3aff4f6Saliguori return 0; 377e3aff4f6Saliguori } 378e3aff4f6Saliguori 379e3aff4f6Saliguori optind++; 380e3aff4f6Saliguori count = cvtnum(argv[optind]); 381e3aff4f6Saliguori if (count < 0) { 382e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 383e3aff4f6Saliguori return 0; 384e3aff4f6Saliguori } 385e3aff4f6Saliguori 386d9654a58SKevin Wolf if (!Pflag && (lflag || sflag)) { 387d9654a58SKevin Wolf return command_usage(&read_cmd); 388d9654a58SKevin Wolf } 389d9654a58SKevin Wolf 390d9654a58SKevin Wolf if (!lflag) { 391d9654a58SKevin Wolf pattern_count = count - pattern_offset; 392d9654a58SKevin Wolf } 393d9654a58SKevin Wolf 394d9654a58SKevin Wolf if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 395d9654a58SKevin Wolf printf("pattern verfication range exceeds end of read data\n"); 396d9654a58SKevin Wolf return 0; 397d9654a58SKevin Wolf } 398d9654a58SKevin Wolf 399e3aff4f6Saliguori if (!pflag) 400e3aff4f6Saliguori if (offset & 0x1ff) { 401*0bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 402*0bfcd599SBlue Swirl offset); 403e3aff4f6Saliguori return 0; 404e3aff4f6Saliguori 405e3aff4f6Saliguori if (count & 0x1ff) { 406e3aff4f6Saliguori printf("count %d is not sector aligned\n", 407e3aff4f6Saliguori count); 408e3aff4f6Saliguori return 0; 409e3aff4f6Saliguori } 410e3aff4f6Saliguori } 411e3aff4f6Saliguori 412e3aff4f6Saliguori buf = qemu_io_alloc(count, 0xab); 413e3aff4f6Saliguori 414e3aff4f6Saliguori gettimeofday(&t1, NULL); 415e3aff4f6Saliguori if (pflag) 416e3aff4f6Saliguori cnt = do_pread(buf, offset, count, &total); 417ca94dbc7SKevin Wolf else if (bflag) 418ca94dbc7SKevin Wolf cnt = do_load_vmstate(buf, offset, count, &total); 419e3aff4f6Saliguori else 420e3aff4f6Saliguori cnt = do_read(buf, offset, count, &total); 421e3aff4f6Saliguori gettimeofday(&t2, NULL); 422e3aff4f6Saliguori 423e3aff4f6Saliguori if (cnt < 0) { 424e3aff4f6Saliguori printf("read failed: %s\n", strerror(-cnt)); 4257d8abfcbSKevin Wolf goto out; 426e3aff4f6Saliguori } 427e3aff4f6Saliguori 428c48101aeSaliguori if (Pflag) { 429d9654a58SKevin Wolf void* cmp_buf = malloc(pattern_count); 430d9654a58SKevin Wolf memset(cmp_buf, pattern, pattern_count); 431d9654a58SKevin Wolf if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 432*0bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 433*0bfcd599SBlue Swirl PRId64 ", %d bytes\n", 434*0bfcd599SBlue Swirl offset + pattern_offset, pattern_count); 435c48101aeSaliguori } 436c48101aeSaliguori free(cmp_buf); 437c48101aeSaliguori } 438c48101aeSaliguori 439e3aff4f6Saliguori if (qflag) 4407d8abfcbSKevin Wolf goto out; 441e3aff4f6Saliguori 442e3aff4f6Saliguori if (vflag) 443e3aff4f6Saliguori dump_buffer(buf, offset, count); 444e3aff4f6Saliguori 445e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 446e3aff4f6Saliguori t2 = tsub(t2, t1); 447e3aff4f6Saliguori print_report("read", &t2, offset, count, total, cnt, Cflag); 448e3aff4f6Saliguori 4497d8abfcbSKevin Wolf out: 450e3aff4f6Saliguori qemu_io_free(buf); 451e3aff4f6Saliguori 452e3aff4f6Saliguori return 0; 453e3aff4f6Saliguori } 454e3aff4f6Saliguori 455e3aff4f6Saliguori static void 456e3aff4f6Saliguori readv_help(void) 457e3aff4f6Saliguori { 458e3aff4f6Saliguori printf( 459e3aff4f6Saliguori "\n" 460e3aff4f6Saliguori " reads a range of bytes from the given offset into multiple buffers\n" 461e3aff4f6Saliguori "\n" 462e3aff4f6Saliguori " Example:\n" 463e3aff4f6Saliguori " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 464e3aff4f6Saliguori "\n" 465e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 466e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 467e3aff4f6Saliguori " Uses multiple iovec buffers if more than one byte range is specified.\n" 468e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 469c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 470e3aff4f6Saliguori " -v, -- dump buffer to standard output\n" 471e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 472e3aff4f6Saliguori "\n"); 473e3aff4f6Saliguori } 474e3aff4f6Saliguori 47522a2bdcbSBlue Swirl static int readv_f(int argc, char **argv); 47622a2bdcbSBlue Swirl 47722a2bdcbSBlue Swirl static const cmdinfo_t readv_cmd = { 47822a2bdcbSBlue Swirl .name = "readv", 47922a2bdcbSBlue Swirl .cfunc = readv_f, 48022a2bdcbSBlue Swirl .argmin = 2, 48122a2bdcbSBlue Swirl .argmax = -1, 48222a2bdcbSBlue Swirl .args = "[-Cqv] [-P pattern ] off len [len..]", 48322a2bdcbSBlue Swirl .oneline = "reads a number of bytes at a specified offset", 48422a2bdcbSBlue Swirl .help = readv_help, 48522a2bdcbSBlue Swirl }; 48622a2bdcbSBlue Swirl 487e3aff4f6Saliguori static int 488e3aff4f6Saliguori readv_f(int argc, char **argv) 489e3aff4f6Saliguori { 490e3aff4f6Saliguori struct timeval t1, t2; 491e3aff4f6Saliguori int Cflag = 0, qflag = 0, vflag = 0; 492e3aff4f6Saliguori int c, cnt; 493cf57298aSChristoph Hellwig char *buf; 494e3aff4f6Saliguori int64_t offset; 4956474bd69SBlue Swirl /* Some compilers get confused and warn if this is not initialized. */ 4966474bd69SBlue Swirl int total = 0; 497cf57298aSChristoph Hellwig int nr_iov; 498e3aff4f6Saliguori QEMUIOVector qiov; 499c48101aeSaliguori int pattern = 0; 500c48101aeSaliguori int Pflag = 0; 501e3aff4f6Saliguori 502c48101aeSaliguori while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 503e3aff4f6Saliguori switch (c) { 504e3aff4f6Saliguori case 'C': 505e3aff4f6Saliguori Cflag = 1; 506e3aff4f6Saliguori break; 507c48101aeSaliguori case 'P': 508c48101aeSaliguori Pflag = 1; 509cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 510cf070d7eSChristoph Hellwig if (pattern < 0) 511cf070d7eSChristoph Hellwig return 0; 512c48101aeSaliguori break; 513e3aff4f6Saliguori case 'q': 514e3aff4f6Saliguori qflag = 1; 515e3aff4f6Saliguori break; 516e3aff4f6Saliguori case 'v': 517e3aff4f6Saliguori vflag = 1; 518e3aff4f6Saliguori break; 519e3aff4f6Saliguori default: 520e3aff4f6Saliguori return command_usage(&readv_cmd); 521e3aff4f6Saliguori } 522e3aff4f6Saliguori } 523e3aff4f6Saliguori 524e3aff4f6Saliguori if (optind > argc - 2) 525e3aff4f6Saliguori return command_usage(&readv_cmd); 526e3aff4f6Saliguori 527e3aff4f6Saliguori 528e3aff4f6Saliguori offset = cvtnum(argv[optind]); 529e3aff4f6Saliguori if (offset < 0) { 530e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 531e3aff4f6Saliguori return 0; 532e3aff4f6Saliguori } 533e3aff4f6Saliguori optind++; 534e3aff4f6Saliguori 535e3aff4f6Saliguori if (offset & 0x1ff) { 536*0bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 537*0bfcd599SBlue Swirl offset); 538e3aff4f6Saliguori return 0; 539e3aff4f6Saliguori } 540e3aff4f6Saliguori 541e3aff4f6Saliguori nr_iov = argc - optind; 542cf57298aSChristoph Hellwig buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); 543e3aff4f6Saliguori 544e3aff4f6Saliguori gettimeofday(&t1, NULL); 545e3aff4f6Saliguori cnt = do_aio_readv(&qiov, offset, &total); 546e3aff4f6Saliguori gettimeofday(&t2, NULL); 547e3aff4f6Saliguori 548e3aff4f6Saliguori if (cnt < 0) { 549e3aff4f6Saliguori printf("readv failed: %s\n", strerror(-cnt)); 5507d8abfcbSKevin Wolf goto out; 551e3aff4f6Saliguori } 552e3aff4f6Saliguori 553c48101aeSaliguori if (Pflag) { 554cf57298aSChristoph Hellwig void* cmp_buf = malloc(qiov.size); 555cf57298aSChristoph Hellwig memset(cmp_buf, pattern, qiov.size); 556cf57298aSChristoph Hellwig if (memcmp(buf, cmp_buf, qiov.size)) { 557*0bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 558*0bfcd599SBlue Swirl PRId64 ", %zd bytes\n", 559*0bfcd599SBlue Swirl offset, qiov.size); 560c48101aeSaliguori } 561c48101aeSaliguori free(cmp_buf); 562c48101aeSaliguori } 563c48101aeSaliguori 564e3aff4f6Saliguori if (qflag) 5657d8abfcbSKevin Wolf goto out; 566e3aff4f6Saliguori 567e3aff4f6Saliguori if (vflag) 568e3aff4f6Saliguori dump_buffer(buf, offset, qiov.size); 569e3aff4f6Saliguori 570e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 571e3aff4f6Saliguori t2 = tsub(t2, t1); 572e3aff4f6Saliguori print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 573e3aff4f6Saliguori 5747d8abfcbSKevin Wolf out: 575e3aff4f6Saliguori qemu_io_free(buf); 576e3aff4f6Saliguori return 0; 577e3aff4f6Saliguori } 578e3aff4f6Saliguori 579e3aff4f6Saliguori static void 580e3aff4f6Saliguori write_help(void) 581e3aff4f6Saliguori { 582e3aff4f6Saliguori printf( 583e3aff4f6Saliguori "\n" 584e3aff4f6Saliguori " writes a range of bytes from the given offset\n" 585e3aff4f6Saliguori "\n" 586e3aff4f6Saliguori " Example:\n" 587e3aff4f6Saliguori " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 588e3aff4f6Saliguori "\n" 589e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 590e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 591ca94dbc7SKevin Wolf " -b, -- write to the VM state rather than the virtual disk\n" 592e3aff4f6Saliguori " -p, -- use bdrv_pwrite to write the file\n" 593e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 594e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 595e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 596e3aff4f6Saliguori "\n"); 597e3aff4f6Saliguori } 598e3aff4f6Saliguori 59922a2bdcbSBlue Swirl static int write_f(int argc, char **argv); 60022a2bdcbSBlue Swirl 60122a2bdcbSBlue Swirl static const cmdinfo_t write_cmd = { 60222a2bdcbSBlue Swirl .name = "write", 60322a2bdcbSBlue Swirl .altname = "w", 60422a2bdcbSBlue Swirl .cfunc = write_f, 60522a2bdcbSBlue Swirl .argmin = 2, 60622a2bdcbSBlue Swirl .argmax = -1, 60722a2bdcbSBlue Swirl .args = "[-abCpq] [-P pattern ] off len", 60822a2bdcbSBlue Swirl .oneline = "writes a number of bytes at a specified offset", 60922a2bdcbSBlue Swirl .help = write_help, 61022a2bdcbSBlue Swirl }; 61122a2bdcbSBlue Swirl 612e3aff4f6Saliguori static int 613e3aff4f6Saliguori write_f(int argc, char **argv) 614e3aff4f6Saliguori { 615e3aff4f6Saliguori struct timeval t1, t2; 616ca94dbc7SKevin Wolf int Cflag = 0, pflag = 0, qflag = 0, bflag = 0; 617e3aff4f6Saliguori int c, cnt; 618e3aff4f6Saliguori char *buf; 619e3aff4f6Saliguori int64_t offset; 620d4ec5228SPaul Brook int count; 621d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 622d4ec5228SPaul Brook int total = 0; 623e3aff4f6Saliguori int pattern = 0xcd; 624e3aff4f6Saliguori 625ca94dbc7SKevin Wolf while ((c = getopt(argc, argv, "bCpP:q")) != EOF) { 626e3aff4f6Saliguori switch (c) { 627ca94dbc7SKevin Wolf case 'b': 628ca94dbc7SKevin Wolf bflag = 1; 629ca94dbc7SKevin Wolf break; 630e3aff4f6Saliguori case 'C': 631e3aff4f6Saliguori Cflag = 1; 632e3aff4f6Saliguori break; 633e3aff4f6Saliguori case 'p': 634e3aff4f6Saliguori pflag = 1; 635e3aff4f6Saliguori break; 636e3aff4f6Saliguori case 'P': 637cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 638cf070d7eSChristoph Hellwig if (pattern < 0) 639cf070d7eSChristoph Hellwig return 0; 640e3aff4f6Saliguori break; 641e3aff4f6Saliguori case 'q': 642e3aff4f6Saliguori qflag = 1; 643e3aff4f6Saliguori break; 644e3aff4f6Saliguori default: 645e3aff4f6Saliguori return command_usage(&write_cmd); 646e3aff4f6Saliguori } 647e3aff4f6Saliguori } 648e3aff4f6Saliguori 649e3aff4f6Saliguori if (optind != argc - 2) 650e3aff4f6Saliguori return command_usage(&write_cmd); 651e3aff4f6Saliguori 652ca94dbc7SKevin Wolf if (bflag && pflag) { 653ca94dbc7SKevin Wolf printf("-b and -p cannot be specified at the same time\n"); 654ca94dbc7SKevin Wolf return 0; 655ca94dbc7SKevin Wolf } 656ca94dbc7SKevin Wolf 657e3aff4f6Saliguori offset = cvtnum(argv[optind]); 658e3aff4f6Saliguori if (offset < 0) { 659e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 660e3aff4f6Saliguori return 0; 661e3aff4f6Saliguori } 662e3aff4f6Saliguori 663e3aff4f6Saliguori optind++; 664e3aff4f6Saliguori count = cvtnum(argv[optind]); 665e3aff4f6Saliguori if (count < 0) { 666e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 667e3aff4f6Saliguori return 0; 668e3aff4f6Saliguori } 669e3aff4f6Saliguori 670e3aff4f6Saliguori if (!pflag) { 671e3aff4f6Saliguori if (offset & 0x1ff) { 672*0bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 673*0bfcd599SBlue Swirl offset); 674e3aff4f6Saliguori return 0; 675e3aff4f6Saliguori } 676e3aff4f6Saliguori 677e3aff4f6Saliguori if (count & 0x1ff) { 678e3aff4f6Saliguori printf("count %d is not sector aligned\n", 679e3aff4f6Saliguori count); 680e3aff4f6Saliguori return 0; 681e3aff4f6Saliguori } 682e3aff4f6Saliguori } 683e3aff4f6Saliguori 684e3aff4f6Saliguori buf = qemu_io_alloc(count, pattern); 685e3aff4f6Saliguori 686e3aff4f6Saliguori gettimeofday(&t1, NULL); 687e3aff4f6Saliguori if (pflag) 688e3aff4f6Saliguori cnt = do_pwrite(buf, offset, count, &total); 689ca94dbc7SKevin Wolf else if (bflag) 690ca94dbc7SKevin Wolf cnt = do_save_vmstate(buf, offset, count, &total); 691e3aff4f6Saliguori else 692e3aff4f6Saliguori cnt = do_write(buf, offset, count, &total); 693e3aff4f6Saliguori gettimeofday(&t2, NULL); 694e3aff4f6Saliguori 695e3aff4f6Saliguori if (cnt < 0) { 696e3aff4f6Saliguori printf("write failed: %s\n", strerror(-cnt)); 6977d8abfcbSKevin Wolf goto out; 698e3aff4f6Saliguori } 699e3aff4f6Saliguori 700e3aff4f6Saliguori if (qflag) 7017d8abfcbSKevin Wolf goto out; 702e3aff4f6Saliguori 703e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 704e3aff4f6Saliguori t2 = tsub(t2, t1); 705e3aff4f6Saliguori print_report("wrote", &t2, offset, count, total, cnt, Cflag); 706e3aff4f6Saliguori 7077d8abfcbSKevin Wolf out: 708e3aff4f6Saliguori qemu_io_free(buf); 709e3aff4f6Saliguori 710e3aff4f6Saliguori return 0; 711e3aff4f6Saliguori } 712e3aff4f6Saliguori 713e3aff4f6Saliguori static void 714e3aff4f6Saliguori writev_help(void) 715e3aff4f6Saliguori { 716e3aff4f6Saliguori printf( 717e3aff4f6Saliguori "\n" 718e3aff4f6Saliguori " writes a range of bytes from the given offset source from multiple buffers\n" 719e3aff4f6Saliguori "\n" 720e3aff4f6Saliguori " Example:\n" 721e3aff4f6Saliguori " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 722e3aff4f6Saliguori "\n" 723e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 724e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 725e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 726e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 727e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 728e3aff4f6Saliguori "\n"); 729e3aff4f6Saliguori } 730e3aff4f6Saliguori 73122a2bdcbSBlue Swirl static int writev_f(int argc, char **argv); 73222a2bdcbSBlue Swirl 73322a2bdcbSBlue Swirl static const cmdinfo_t writev_cmd = { 73422a2bdcbSBlue Swirl .name = "writev", 73522a2bdcbSBlue Swirl .cfunc = writev_f, 73622a2bdcbSBlue Swirl .argmin = 2, 73722a2bdcbSBlue Swirl .argmax = -1, 73822a2bdcbSBlue Swirl .args = "[-Cq] [-P pattern ] off len [len..]", 73922a2bdcbSBlue Swirl .oneline = "writes a number of bytes at a specified offset", 74022a2bdcbSBlue Swirl .help = writev_help, 74122a2bdcbSBlue Swirl }; 74222a2bdcbSBlue Swirl 743e3aff4f6Saliguori static int 744e3aff4f6Saliguori writev_f(int argc, char **argv) 745e3aff4f6Saliguori { 746e3aff4f6Saliguori struct timeval t1, t2; 747e3aff4f6Saliguori int Cflag = 0, qflag = 0; 748e3aff4f6Saliguori int c, cnt; 749cf57298aSChristoph Hellwig char *buf; 750e3aff4f6Saliguori int64_t offset; 7516474bd69SBlue Swirl /* Some compilers get confused and warn if this is not initialized. */ 7526474bd69SBlue Swirl int total = 0; 753cf57298aSChristoph Hellwig int nr_iov; 754e3aff4f6Saliguori int pattern = 0xcd; 755e3aff4f6Saliguori QEMUIOVector qiov; 756e3aff4f6Saliguori 757e3aff4f6Saliguori while ((c = getopt(argc, argv, "CqP:")) != EOF) { 758e3aff4f6Saliguori switch (c) { 759e3aff4f6Saliguori case 'C': 760e3aff4f6Saliguori Cflag = 1; 761e3aff4f6Saliguori break; 762e3aff4f6Saliguori case 'q': 763e3aff4f6Saliguori qflag = 1; 764e3aff4f6Saliguori break; 765e3aff4f6Saliguori case 'P': 766cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 767cf070d7eSChristoph Hellwig if (pattern < 0) 768cf070d7eSChristoph Hellwig return 0; 769e3aff4f6Saliguori break; 770e3aff4f6Saliguori default: 771e3aff4f6Saliguori return command_usage(&writev_cmd); 772e3aff4f6Saliguori } 773e3aff4f6Saliguori } 774e3aff4f6Saliguori 775e3aff4f6Saliguori if (optind > argc - 2) 776e3aff4f6Saliguori return command_usage(&writev_cmd); 777e3aff4f6Saliguori 778e3aff4f6Saliguori offset = cvtnum(argv[optind]); 779e3aff4f6Saliguori if (offset < 0) { 780e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 781e3aff4f6Saliguori return 0; 782e3aff4f6Saliguori } 783e3aff4f6Saliguori optind++; 784e3aff4f6Saliguori 785e3aff4f6Saliguori if (offset & 0x1ff) { 786*0bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 787*0bfcd599SBlue Swirl offset); 788e3aff4f6Saliguori return 0; 789e3aff4f6Saliguori } 790e3aff4f6Saliguori 791e3aff4f6Saliguori nr_iov = argc - optind; 792cf57298aSChristoph Hellwig buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); 793e3aff4f6Saliguori 794e3aff4f6Saliguori gettimeofday(&t1, NULL); 795e3aff4f6Saliguori cnt = do_aio_writev(&qiov, offset, &total); 796e3aff4f6Saliguori gettimeofday(&t2, NULL); 797e3aff4f6Saliguori 798e3aff4f6Saliguori if (cnt < 0) { 799e3aff4f6Saliguori printf("writev failed: %s\n", strerror(-cnt)); 8007d8abfcbSKevin Wolf goto out; 801e3aff4f6Saliguori } 802e3aff4f6Saliguori 803e3aff4f6Saliguori if (qflag) 8047d8abfcbSKevin Wolf goto out; 805e3aff4f6Saliguori 806e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 807e3aff4f6Saliguori t2 = tsub(t2, t1); 808e3aff4f6Saliguori print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 8097d8abfcbSKevin Wolf out: 810e3aff4f6Saliguori qemu_io_free(buf); 811e3aff4f6Saliguori return 0; 812e3aff4f6Saliguori } 813e3aff4f6Saliguori 81495533d5fSChristoph Hellwig struct aio_ctx { 81595533d5fSChristoph Hellwig QEMUIOVector qiov; 81695533d5fSChristoph Hellwig int64_t offset; 81795533d5fSChristoph Hellwig char *buf; 81895533d5fSChristoph Hellwig int qflag; 81995533d5fSChristoph Hellwig int vflag; 82095533d5fSChristoph Hellwig int Cflag; 82195533d5fSChristoph Hellwig int Pflag; 82295533d5fSChristoph Hellwig int pattern; 82395533d5fSChristoph Hellwig struct timeval t1; 82495533d5fSChristoph Hellwig }; 82595533d5fSChristoph Hellwig 82695533d5fSChristoph Hellwig static void 82795533d5fSChristoph Hellwig aio_write_done(void *opaque, int ret) 82895533d5fSChristoph Hellwig { 82995533d5fSChristoph Hellwig struct aio_ctx *ctx = opaque; 83095533d5fSChristoph Hellwig struct timeval t2; 83195533d5fSChristoph Hellwig 83295533d5fSChristoph Hellwig gettimeofday(&t2, NULL); 83395533d5fSChristoph Hellwig 83495533d5fSChristoph Hellwig 83595533d5fSChristoph Hellwig if (ret < 0) { 83695533d5fSChristoph Hellwig printf("aio_write failed: %s\n", strerror(-ret)); 8377d8abfcbSKevin Wolf goto out; 83895533d5fSChristoph Hellwig } 83995533d5fSChristoph Hellwig 840230d4fa4SChristoph Hellwig if (ctx->qflag) { 8417d8abfcbSKevin Wolf goto out; 842230d4fa4SChristoph Hellwig } 84395533d5fSChristoph Hellwig 84495533d5fSChristoph Hellwig /* Finally, report back -- -C gives a parsable format */ 84595533d5fSChristoph Hellwig t2 = tsub(t2, ctx->t1); 846230d4fa4SChristoph Hellwig print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 847230d4fa4SChristoph Hellwig ctx->qiov.size, 1, ctx->Cflag); 8487d8abfcbSKevin Wolf out: 84995533d5fSChristoph Hellwig qemu_io_free(ctx->buf); 85095533d5fSChristoph Hellwig free(ctx); 85195533d5fSChristoph Hellwig } 85295533d5fSChristoph Hellwig 85395533d5fSChristoph Hellwig static void 85495533d5fSChristoph Hellwig aio_read_done(void *opaque, int ret) 85595533d5fSChristoph Hellwig { 85695533d5fSChristoph Hellwig struct aio_ctx *ctx = opaque; 85795533d5fSChristoph Hellwig struct timeval t2; 85895533d5fSChristoph Hellwig 85995533d5fSChristoph Hellwig gettimeofday(&t2, NULL); 86095533d5fSChristoph Hellwig 86195533d5fSChristoph Hellwig if (ret < 0) { 86295533d5fSChristoph Hellwig printf("readv failed: %s\n", strerror(-ret)); 8637d8abfcbSKevin Wolf goto out; 86495533d5fSChristoph Hellwig } 86595533d5fSChristoph Hellwig 86695533d5fSChristoph Hellwig if (ctx->Pflag) { 867230d4fa4SChristoph Hellwig void *cmp_buf = malloc(ctx->qiov.size); 86895533d5fSChristoph Hellwig 869230d4fa4SChristoph Hellwig memset(cmp_buf, ctx->pattern, ctx->qiov.size); 870230d4fa4SChristoph Hellwig if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 871*0bfcd599SBlue Swirl printf("Pattern verification failed at offset %" 872*0bfcd599SBlue Swirl PRId64 ", %zd bytes\n", 873*0bfcd599SBlue Swirl ctx->offset, ctx->qiov.size); 87495533d5fSChristoph Hellwig } 87595533d5fSChristoph Hellwig free(cmp_buf); 87695533d5fSChristoph Hellwig } 87795533d5fSChristoph Hellwig 878230d4fa4SChristoph Hellwig if (ctx->qflag) { 8797d8abfcbSKevin Wolf goto out; 880230d4fa4SChristoph Hellwig } 88195533d5fSChristoph Hellwig 882230d4fa4SChristoph Hellwig if (ctx->vflag) { 883230d4fa4SChristoph Hellwig dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 884230d4fa4SChristoph Hellwig } 88595533d5fSChristoph Hellwig 88695533d5fSChristoph Hellwig /* Finally, report back -- -C gives a parsable format */ 88795533d5fSChristoph Hellwig t2 = tsub(t2, ctx->t1); 888230d4fa4SChristoph Hellwig print_report("read", &t2, ctx->offset, ctx->qiov.size, 889230d4fa4SChristoph Hellwig ctx->qiov.size, 1, ctx->Cflag); 8907d8abfcbSKevin Wolf out: 89195533d5fSChristoph Hellwig qemu_io_free(ctx->buf); 89295533d5fSChristoph Hellwig free(ctx); 89395533d5fSChristoph Hellwig } 89495533d5fSChristoph Hellwig 89595533d5fSChristoph Hellwig static void 89695533d5fSChristoph Hellwig aio_read_help(void) 89795533d5fSChristoph Hellwig { 89895533d5fSChristoph Hellwig printf( 89995533d5fSChristoph Hellwig "\n" 90095533d5fSChristoph Hellwig " asynchronously reads a range of bytes from the given offset\n" 90195533d5fSChristoph Hellwig "\n" 90295533d5fSChristoph Hellwig " Example:\n" 90395533d5fSChristoph Hellwig " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 90495533d5fSChristoph Hellwig "\n" 90595533d5fSChristoph Hellwig " Reads a segment of the currently open file, optionally dumping it to the\n" 90695533d5fSChristoph Hellwig " standard output stream (with -v option) for subsequent inspection.\n" 907e432cef9SChristoph Hellwig " The read is performed asynchronously and the aio_flush command must be\n" 908e432cef9SChristoph Hellwig " used to ensure all outstanding aio requests have been completed\n" 90995533d5fSChristoph Hellwig " -C, -- report statistics in a machine parsable format\n" 91095533d5fSChristoph Hellwig " -P, -- use a pattern to verify read data\n" 91195533d5fSChristoph Hellwig " -v, -- dump buffer to standard output\n" 91295533d5fSChristoph Hellwig " -q, -- quite mode, do not show I/O statistics\n" 91395533d5fSChristoph Hellwig "\n"); 91495533d5fSChristoph Hellwig } 91595533d5fSChristoph Hellwig 91622a2bdcbSBlue Swirl static int aio_read_f(int argc, char **argv); 91722a2bdcbSBlue Swirl 91822a2bdcbSBlue Swirl static const cmdinfo_t aio_read_cmd = { 91922a2bdcbSBlue Swirl .name = "aio_read", 92022a2bdcbSBlue Swirl .cfunc = aio_read_f, 92122a2bdcbSBlue Swirl .argmin = 2, 92222a2bdcbSBlue Swirl .argmax = -1, 92322a2bdcbSBlue Swirl .args = "[-Cqv] [-P pattern ] off len [len..]", 92422a2bdcbSBlue Swirl .oneline = "asynchronously reads a number of bytes", 92522a2bdcbSBlue Swirl .help = aio_read_help, 92622a2bdcbSBlue Swirl }; 92722a2bdcbSBlue Swirl 92895533d5fSChristoph Hellwig static int 92995533d5fSChristoph Hellwig aio_read_f(int argc, char **argv) 93095533d5fSChristoph Hellwig { 931cf57298aSChristoph Hellwig int nr_iov, c; 93295533d5fSChristoph Hellwig struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 93395533d5fSChristoph Hellwig BlockDriverAIOCB *acb; 93495533d5fSChristoph Hellwig 93595533d5fSChristoph Hellwig while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 93695533d5fSChristoph Hellwig switch (c) { 93795533d5fSChristoph Hellwig case 'C': 93895533d5fSChristoph Hellwig ctx->Cflag = 1; 93995533d5fSChristoph Hellwig break; 94095533d5fSChristoph Hellwig case 'P': 94195533d5fSChristoph Hellwig ctx->Pflag = 1; 942cf070d7eSChristoph Hellwig ctx->pattern = parse_pattern(optarg); 943cf070d7eSChristoph Hellwig if (ctx->pattern < 0) 944cf070d7eSChristoph Hellwig return 0; 94595533d5fSChristoph Hellwig break; 94695533d5fSChristoph Hellwig case 'q': 94795533d5fSChristoph Hellwig ctx->qflag = 1; 94895533d5fSChristoph Hellwig break; 94995533d5fSChristoph Hellwig case 'v': 95095533d5fSChristoph Hellwig ctx->vflag = 1; 95195533d5fSChristoph Hellwig break; 95295533d5fSChristoph Hellwig default: 9537d8abfcbSKevin Wolf free(ctx); 95495533d5fSChristoph Hellwig return command_usage(&aio_read_cmd); 95595533d5fSChristoph Hellwig } 95695533d5fSChristoph Hellwig } 95795533d5fSChristoph Hellwig 9587d8abfcbSKevin Wolf if (optind > argc - 2) { 9597d8abfcbSKevin Wolf free(ctx); 96095533d5fSChristoph Hellwig return command_usage(&aio_read_cmd); 9617d8abfcbSKevin Wolf } 96295533d5fSChristoph Hellwig 96395533d5fSChristoph Hellwig ctx->offset = cvtnum(argv[optind]); 96495533d5fSChristoph Hellwig if (ctx->offset < 0) { 96595533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[optind]); 9667d8abfcbSKevin Wolf free(ctx); 96795533d5fSChristoph Hellwig return 0; 96895533d5fSChristoph Hellwig } 96995533d5fSChristoph Hellwig optind++; 97095533d5fSChristoph Hellwig 97195533d5fSChristoph Hellwig if (ctx->offset & 0x1ff) { 972*0bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 973*0bfcd599SBlue Swirl ctx->offset); 9747d8abfcbSKevin Wolf free(ctx); 97595533d5fSChristoph Hellwig return 0; 97695533d5fSChristoph Hellwig } 97795533d5fSChristoph Hellwig 97895533d5fSChristoph Hellwig nr_iov = argc - optind; 979cf57298aSChristoph Hellwig ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); 98095533d5fSChristoph Hellwig 98195533d5fSChristoph Hellwig gettimeofday(&ctx->t1, NULL); 98295533d5fSChristoph Hellwig acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 98395533d5fSChristoph Hellwig ctx->qiov.size >> 9, aio_read_done, ctx); 9847d8abfcbSKevin Wolf if (!acb) { 9857d8abfcbSKevin Wolf free(ctx->buf); 9867d8abfcbSKevin Wolf free(ctx); 98795533d5fSChristoph Hellwig return -EIO; 9887d8abfcbSKevin Wolf } 98995533d5fSChristoph Hellwig 99095533d5fSChristoph Hellwig return 0; 99195533d5fSChristoph Hellwig } 99295533d5fSChristoph Hellwig 99395533d5fSChristoph Hellwig static void 99495533d5fSChristoph Hellwig aio_write_help(void) 99595533d5fSChristoph Hellwig { 99695533d5fSChristoph Hellwig printf( 99795533d5fSChristoph Hellwig "\n" 99895533d5fSChristoph Hellwig " asynchronously writes a range of bytes from the given offset source \n" 99995533d5fSChristoph Hellwig " from multiple buffers\n" 100095533d5fSChristoph Hellwig "\n" 100195533d5fSChristoph Hellwig " Example:\n" 100295533d5fSChristoph Hellwig " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 100395533d5fSChristoph Hellwig "\n" 100495533d5fSChristoph Hellwig " Writes into a segment of the currently open file, using a buffer\n" 100595533d5fSChristoph Hellwig " filled with a set pattern (0xcdcdcdcd).\n" 1006e432cef9SChristoph Hellwig " The write is performed asynchronously and the aio_flush command must be\n" 1007e432cef9SChristoph Hellwig " used to ensure all outstanding aio requests have been completed\n" 100895533d5fSChristoph Hellwig " -P, -- use different pattern to fill file\n" 100995533d5fSChristoph Hellwig " -C, -- report statistics in a machine parsable format\n" 101095533d5fSChristoph Hellwig " -q, -- quite mode, do not show I/O statistics\n" 101195533d5fSChristoph Hellwig "\n"); 101295533d5fSChristoph Hellwig } 101395533d5fSChristoph Hellwig 101422a2bdcbSBlue Swirl static int aio_write_f(int argc, char **argv); 101522a2bdcbSBlue Swirl 101622a2bdcbSBlue Swirl static const cmdinfo_t aio_write_cmd = { 101722a2bdcbSBlue Swirl .name = "aio_write", 101822a2bdcbSBlue Swirl .cfunc = aio_write_f, 101922a2bdcbSBlue Swirl .argmin = 2, 102022a2bdcbSBlue Swirl .argmax = -1, 102122a2bdcbSBlue Swirl .args = "[-Cq] [-P pattern ] off len [len..]", 102222a2bdcbSBlue Swirl .oneline = "asynchronously writes a number of bytes", 102322a2bdcbSBlue Swirl .help = aio_write_help, 102422a2bdcbSBlue Swirl }; 102595533d5fSChristoph Hellwig 102695533d5fSChristoph Hellwig static int 102795533d5fSChristoph Hellwig aio_write_f(int argc, char **argv) 102895533d5fSChristoph Hellwig { 1029cf57298aSChristoph Hellwig int nr_iov, c; 103095533d5fSChristoph Hellwig int pattern = 0xcd; 103195533d5fSChristoph Hellwig struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 103295533d5fSChristoph Hellwig BlockDriverAIOCB *acb; 103395533d5fSChristoph Hellwig 103495533d5fSChristoph Hellwig while ((c = getopt(argc, argv, "CqP:")) != EOF) { 103595533d5fSChristoph Hellwig switch (c) { 103695533d5fSChristoph Hellwig case 'C': 103795533d5fSChristoph Hellwig ctx->Cflag = 1; 103895533d5fSChristoph Hellwig break; 103995533d5fSChristoph Hellwig case 'q': 104095533d5fSChristoph Hellwig ctx->qflag = 1; 104195533d5fSChristoph Hellwig break; 104295533d5fSChristoph Hellwig case 'P': 1043cf070d7eSChristoph Hellwig pattern = parse_pattern(optarg); 1044cf070d7eSChristoph Hellwig if (pattern < 0) 1045cf070d7eSChristoph Hellwig return 0; 104695533d5fSChristoph Hellwig break; 104795533d5fSChristoph Hellwig default: 10487d8abfcbSKevin Wolf free(ctx); 104995533d5fSChristoph Hellwig return command_usage(&aio_write_cmd); 105095533d5fSChristoph Hellwig } 105195533d5fSChristoph Hellwig } 105295533d5fSChristoph Hellwig 10537d8abfcbSKevin Wolf if (optind > argc - 2) { 10547d8abfcbSKevin Wolf free(ctx); 105595533d5fSChristoph Hellwig return command_usage(&aio_write_cmd); 10567d8abfcbSKevin Wolf } 105795533d5fSChristoph Hellwig 105895533d5fSChristoph Hellwig ctx->offset = cvtnum(argv[optind]); 105995533d5fSChristoph Hellwig if (ctx->offset < 0) { 106095533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[optind]); 10617d8abfcbSKevin Wolf free(ctx); 106295533d5fSChristoph Hellwig return 0; 106395533d5fSChristoph Hellwig } 106495533d5fSChristoph Hellwig optind++; 106595533d5fSChristoph Hellwig 106695533d5fSChristoph Hellwig if (ctx->offset & 0x1ff) { 1067*0bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 1068*0bfcd599SBlue Swirl ctx->offset); 10697d8abfcbSKevin Wolf free(ctx); 107095533d5fSChristoph Hellwig return 0; 107195533d5fSChristoph Hellwig } 107295533d5fSChristoph Hellwig 107395533d5fSChristoph Hellwig nr_iov = argc - optind; 1074cf57298aSChristoph Hellwig ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); 107595533d5fSChristoph Hellwig 107695533d5fSChristoph Hellwig gettimeofday(&ctx->t1, NULL); 107795533d5fSChristoph Hellwig acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 107895533d5fSChristoph Hellwig ctx->qiov.size >> 9, aio_write_done, ctx); 10797d8abfcbSKevin Wolf if (!acb) { 10807d8abfcbSKevin Wolf free(ctx->buf); 10817d8abfcbSKevin Wolf free(ctx); 108295533d5fSChristoph Hellwig return -EIO; 10837d8abfcbSKevin Wolf } 108495533d5fSChristoph Hellwig 108595533d5fSChristoph Hellwig return 0; 108695533d5fSChristoph Hellwig } 108795533d5fSChristoph Hellwig 108895533d5fSChristoph Hellwig static int 108995533d5fSChristoph Hellwig aio_flush_f(int argc, char **argv) 109095533d5fSChristoph Hellwig { 109195533d5fSChristoph Hellwig qemu_aio_flush(); 109295533d5fSChristoph Hellwig return 0; 109395533d5fSChristoph Hellwig } 109495533d5fSChristoph Hellwig 109595533d5fSChristoph Hellwig static const cmdinfo_t aio_flush_cmd = { 109695533d5fSChristoph Hellwig .name = "aio_flush", 109795533d5fSChristoph Hellwig .cfunc = aio_flush_f, 1098e432cef9SChristoph Hellwig .oneline = "completes all outstanding aio requests" 109995533d5fSChristoph Hellwig }; 110095533d5fSChristoph Hellwig 1101e3aff4f6Saliguori static int 1102e3aff4f6Saliguori flush_f(int argc, char **argv) 1103e3aff4f6Saliguori { 1104e3aff4f6Saliguori bdrv_flush(bs); 1105e3aff4f6Saliguori return 0; 1106e3aff4f6Saliguori } 1107e3aff4f6Saliguori 1108e3aff4f6Saliguori static const cmdinfo_t flush_cmd = { 1109e3aff4f6Saliguori .name = "flush", 1110e3aff4f6Saliguori .altname = "f", 1111e3aff4f6Saliguori .cfunc = flush_f, 1112e3aff4f6Saliguori .oneline = "flush all in-core file state to disk", 1113e3aff4f6Saliguori }; 1114e3aff4f6Saliguori 1115e3aff4f6Saliguori static int 1116e3aff4f6Saliguori truncate_f(int argc, char **argv) 1117e3aff4f6Saliguori { 1118e3aff4f6Saliguori int64_t offset; 1119e3aff4f6Saliguori int ret; 1120e3aff4f6Saliguori 1121e3aff4f6Saliguori offset = cvtnum(argv[1]); 1122e3aff4f6Saliguori if (offset < 0) { 1123e3aff4f6Saliguori printf("non-numeric truncate argument -- %s\n", argv[1]); 1124e3aff4f6Saliguori return 0; 1125e3aff4f6Saliguori } 1126e3aff4f6Saliguori 1127e3aff4f6Saliguori ret = bdrv_truncate(bs, offset); 1128e3aff4f6Saliguori if (ret < 0) { 1129e3aff4f6Saliguori printf("truncate: %s", strerror(ret)); 1130e3aff4f6Saliguori return 0; 1131e3aff4f6Saliguori } 1132e3aff4f6Saliguori 1133e3aff4f6Saliguori return 0; 1134e3aff4f6Saliguori } 1135e3aff4f6Saliguori 1136e3aff4f6Saliguori static const cmdinfo_t truncate_cmd = { 1137e3aff4f6Saliguori .name = "truncate", 1138e3aff4f6Saliguori .altname = "t", 1139e3aff4f6Saliguori .cfunc = truncate_f, 1140e3aff4f6Saliguori .argmin = 1, 1141e3aff4f6Saliguori .argmax = 1, 1142e3aff4f6Saliguori .args = "off", 1143e3aff4f6Saliguori .oneline = "truncates the current file at the given offset", 1144e3aff4f6Saliguori }; 1145e3aff4f6Saliguori 1146e3aff4f6Saliguori static int 1147e3aff4f6Saliguori length_f(int argc, char **argv) 1148e3aff4f6Saliguori { 1149e3aff4f6Saliguori int64_t size; 1150e3aff4f6Saliguori char s1[64]; 1151e3aff4f6Saliguori 1152e3aff4f6Saliguori size = bdrv_getlength(bs); 1153e3aff4f6Saliguori if (size < 0) { 1154e3aff4f6Saliguori printf("getlength: %s", strerror(size)); 1155e3aff4f6Saliguori return 0; 1156e3aff4f6Saliguori } 1157e3aff4f6Saliguori 1158e3aff4f6Saliguori cvtstr(size, s1, sizeof(s1)); 1159e3aff4f6Saliguori printf("%s\n", s1); 1160e3aff4f6Saliguori return 0; 1161e3aff4f6Saliguori } 1162e3aff4f6Saliguori 1163e3aff4f6Saliguori 1164e3aff4f6Saliguori static const cmdinfo_t length_cmd = { 1165e3aff4f6Saliguori .name = "length", 1166e3aff4f6Saliguori .altname = "l", 1167e3aff4f6Saliguori .cfunc = length_f, 1168e3aff4f6Saliguori .oneline = "gets the length of the current file", 1169e3aff4f6Saliguori }; 1170e3aff4f6Saliguori 1171e3aff4f6Saliguori 1172e3aff4f6Saliguori static int 1173e3aff4f6Saliguori info_f(int argc, char **argv) 1174e3aff4f6Saliguori { 1175e3aff4f6Saliguori BlockDriverInfo bdi; 1176e3aff4f6Saliguori char s1[64], s2[64]; 1177e3aff4f6Saliguori int ret; 1178e3aff4f6Saliguori 1179e3aff4f6Saliguori if (bs->drv && bs->drv->format_name) 1180e3aff4f6Saliguori printf("format name: %s\n", bs->drv->format_name); 1181e3aff4f6Saliguori if (bs->drv && bs->drv->protocol_name) 1182e3aff4f6Saliguori printf("format name: %s\n", bs->drv->protocol_name); 1183e3aff4f6Saliguori 1184e3aff4f6Saliguori ret = bdrv_get_info(bs, &bdi); 1185e3aff4f6Saliguori if (ret) 1186e3aff4f6Saliguori return 0; 1187e3aff4f6Saliguori 1188e3aff4f6Saliguori cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1189e3aff4f6Saliguori cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1190e3aff4f6Saliguori 1191e3aff4f6Saliguori printf("cluster size: %s\n", s1); 1192e3aff4f6Saliguori printf("vm state offset: %s\n", s2); 1193e3aff4f6Saliguori 1194e3aff4f6Saliguori return 0; 1195e3aff4f6Saliguori } 1196e3aff4f6Saliguori 1197e3aff4f6Saliguori 1198e3aff4f6Saliguori 1199e3aff4f6Saliguori static const cmdinfo_t info_cmd = { 1200e3aff4f6Saliguori .name = "info", 1201e3aff4f6Saliguori .altname = "i", 1202e3aff4f6Saliguori .cfunc = info_f, 1203e3aff4f6Saliguori .oneline = "prints information about the current file", 1204e3aff4f6Saliguori }; 1205e3aff4f6Saliguori 1206e3aff4f6Saliguori static int 1207e3aff4f6Saliguori alloc_f(int argc, char **argv) 1208e3aff4f6Saliguori { 1209e3aff4f6Saliguori int64_t offset; 1210a7824a88SKevin Wolf int nb_sectors, remaining; 1211e3aff4f6Saliguori char s1[64]; 1212a7824a88SKevin Wolf int num, sum_alloc; 1213e3aff4f6Saliguori int ret; 1214e3aff4f6Saliguori 1215e3aff4f6Saliguori offset = cvtnum(argv[1]); 1216e3aff4f6Saliguori if (offset & 0x1ff) { 1217*0bfcd599SBlue Swirl printf("offset %" PRId64 " is not sector aligned\n", 1218*0bfcd599SBlue Swirl offset); 1219e3aff4f6Saliguori return 0; 1220e3aff4f6Saliguori } 1221e3aff4f6Saliguori 1222e3aff4f6Saliguori if (argc == 3) 1223e3aff4f6Saliguori nb_sectors = cvtnum(argv[2]); 1224e3aff4f6Saliguori else 1225e3aff4f6Saliguori nb_sectors = 1; 1226e3aff4f6Saliguori 1227a7824a88SKevin Wolf remaining = nb_sectors; 1228a7824a88SKevin Wolf sum_alloc = 0; 1229a7824a88SKevin Wolf while (remaining) { 1230e3aff4f6Saliguori ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); 1231a7824a88SKevin Wolf remaining -= num; 1232a7824a88SKevin Wolf if (ret) { 1233a7824a88SKevin Wolf sum_alloc += num; 1234a7824a88SKevin Wolf } 1235a7824a88SKevin Wolf } 1236e3aff4f6Saliguori 1237e3aff4f6Saliguori cvtstr(offset, s1, sizeof(s1)); 1238e3aff4f6Saliguori 1239e3aff4f6Saliguori if (nb_sectors == 1) 1240a7824a88SKevin Wolf printf("sector allocated at offset %s\n", s1); 1241e3aff4f6Saliguori else 1242a7824a88SKevin Wolf printf("%d/%d sectors allocated at offset %s\n", 1243a7824a88SKevin Wolf sum_alloc, nb_sectors, s1); 1244e3aff4f6Saliguori return 0; 1245e3aff4f6Saliguori } 1246e3aff4f6Saliguori 1247e3aff4f6Saliguori static const cmdinfo_t alloc_cmd = { 1248e3aff4f6Saliguori .name = "alloc", 1249e3aff4f6Saliguori .altname = "a", 1250e3aff4f6Saliguori .argmin = 1, 1251e3aff4f6Saliguori .argmax = 2, 1252e3aff4f6Saliguori .cfunc = alloc_f, 1253e3aff4f6Saliguori .args = "off [sectors]", 1254e3aff4f6Saliguori .oneline = "checks if a sector is present in the file", 1255e3aff4f6Saliguori }; 1256e3aff4f6Saliguori 1257e3aff4f6Saliguori static int 1258e3aff4f6Saliguori close_f(int argc, char **argv) 1259e3aff4f6Saliguori { 1260e3aff4f6Saliguori bdrv_close(bs); 1261e3aff4f6Saliguori bs = NULL; 1262e3aff4f6Saliguori return 0; 1263e3aff4f6Saliguori } 1264e3aff4f6Saliguori 1265e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 1266e3aff4f6Saliguori .name = "close", 1267e3aff4f6Saliguori .altname = "c", 1268e3aff4f6Saliguori .cfunc = close_f, 1269e3aff4f6Saliguori .oneline = "close the current open file", 1270e3aff4f6Saliguori }; 1271e3aff4f6Saliguori 12729c4bab26SChristoph Hellwig static int openfile(char *name, int flags, int growable) 1273e3aff4f6Saliguori { 1274e3aff4f6Saliguori if (bs) { 1275e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 1276e3aff4f6Saliguori return 1; 1277e3aff4f6Saliguori } 1278e3aff4f6Saliguori 12796db95603SChristoph Hellwig if (growable) { 12806db95603SChristoph Hellwig if (bdrv_file_open(&bs, name, flags)) { 12816db95603SChristoph Hellwig fprintf(stderr, "%s: can't open device %s\n", progname, name); 12826db95603SChristoph Hellwig return 1; 12836db95603SChristoph Hellwig } 12846db95603SChristoph Hellwig } else { 1285e3aff4f6Saliguori bs = bdrv_new("hda"); 1286e3aff4f6Saliguori if (!bs) 1287e3aff4f6Saliguori return 1; 1288e3aff4f6Saliguori 1289d6e9098eSKevin Wolf if (bdrv_open(bs, name, flags, NULL) < 0) { 1290e3aff4f6Saliguori fprintf(stderr, "%s: can't open device %s\n", progname, name); 1291e3aff4f6Saliguori bs = NULL; 1292e3aff4f6Saliguori return 1; 1293e3aff4f6Saliguori } 12949c4bab26SChristoph Hellwig } 12956db95603SChristoph Hellwig 1296e3aff4f6Saliguori return 0; 1297e3aff4f6Saliguori } 1298e3aff4f6Saliguori 1299e3aff4f6Saliguori static void 1300e3aff4f6Saliguori open_help(void) 1301e3aff4f6Saliguori { 1302e3aff4f6Saliguori printf( 1303e3aff4f6Saliguori "\n" 1304e3aff4f6Saliguori " opens a new file in the requested mode\n" 1305e3aff4f6Saliguori "\n" 1306e3aff4f6Saliguori " Example:\n" 1307e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 1308e3aff4f6Saliguori "\n" 1309e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 1310e3aff4f6Saliguori " -r, -- open file read-only\n" 1311e3aff4f6Saliguori " -s, -- use snapshot file\n" 1312e3aff4f6Saliguori " -n, -- disable host cache\n" 13139c4bab26SChristoph Hellwig " -g, -- allow file to grow (only applies to protocols)" 1314e3aff4f6Saliguori "\n"); 1315e3aff4f6Saliguori } 1316e3aff4f6Saliguori 131722a2bdcbSBlue Swirl static int open_f(int argc, char **argv); 131822a2bdcbSBlue Swirl 131922a2bdcbSBlue Swirl static const cmdinfo_t open_cmd = { 132022a2bdcbSBlue Swirl .name = "open", 132122a2bdcbSBlue Swirl .altname = "o", 132222a2bdcbSBlue Swirl .cfunc = open_f, 132322a2bdcbSBlue Swirl .argmin = 1, 132422a2bdcbSBlue Swirl .argmax = -1, 132522a2bdcbSBlue Swirl .flags = CMD_NOFILE_OK, 132622a2bdcbSBlue Swirl .args = "[-Crsn] [path]", 132722a2bdcbSBlue Swirl .oneline = "open the file specified by path", 132822a2bdcbSBlue Swirl .help = open_help, 132922a2bdcbSBlue Swirl }; 1330e3aff4f6Saliguori 1331e3aff4f6Saliguori static int 1332e3aff4f6Saliguori open_f(int argc, char **argv) 1333e3aff4f6Saliguori { 1334e3aff4f6Saliguori int flags = 0; 1335e3aff4f6Saliguori int readonly = 0; 13369c4bab26SChristoph Hellwig int growable = 0; 1337e3aff4f6Saliguori int c; 1338e3aff4f6Saliguori 13399a2d77adSChristoph Hellwig while ((c = getopt(argc, argv, "snrg")) != EOF) { 1340e3aff4f6Saliguori switch (c) { 1341e3aff4f6Saliguori case 's': 1342e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1343e3aff4f6Saliguori break; 1344e3aff4f6Saliguori case 'n': 1345e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 1346e3aff4f6Saliguori break; 1347e3aff4f6Saliguori case 'r': 1348e3aff4f6Saliguori readonly = 1; 1349e3aff4f6Saliguori break; 13509c4bab26SChristoph Hellwig case 'g': 13519c4bab26SChristoph Hellwig growable = 1; 13529c4bab26SChristoph Hellwig break; 1353e3aff4f6Saliguori default: 1354e3aff4f6Saliguori return command_usage(&open_cmd); 1355e3aff4f6Saliguori } 1356e3aff4f6Saliguori } 1357e3aff4f6Saliguori 1358f5edb014SNaphtali Sprei if (!readonly) { 1359e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1360f5edb014SNaphtali Sprei } 1361e3aff4f6Saliguori 1362e3aff4f6Saliguori if (optind != argc - 1) 1363e3aff4f6Saliguori return command_usage(&open_cmd); 1364e3aff4f6Saliguori 13659c4bab26SChristoph Hellwig return openfile(argv[optind], flags, growable); 1366e3aff4f6Saliguori } 1367e3aff4f6Saliguori 1368e3aff4f6Saliguori static int 1369e3aff4f6Saliguori init_args_command( 1370e3aff4f6Saliguori int index) 1371e3aff4f6Saliguori { 1372e3aff4f6Saliguori /* only one device allowed so far */ 1373e3aff4f6Saliguori if (index >= 1) 1374e3aff4f6Saliguori return 0; 1375e3aff4f6Saliguori return ++index; 1376e3aff4f6Saliguori } 1377e3aff4f6Saliguori 1378e3aff4f6Saliguori static int 1379e3aff4f6Saliguori init_check_command( 1380e3aff4f6Saliguori const cmdinfo_t *ct) 1381e3aff4f6Saliguori { 1382e3aff4f6Saliguori if (ct->flags & CMD_FLAG_GLOBAL) 1383e3aff4f6Saliguori return 1; 1384e3aff4f6Saliguori if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1385e3aff4f6Saliguori fprintf(stderr, "no file open, try 'help open'\n"); 1386e3aff4f6Saliguori return 0; 1387e3aff4f6Saliguori } 1388e3aff4f6Saliguori return 1; 1389e3aff4f6Saliguori } 1390e3aff4f6Saliguori 1391e3aff4f6Saliguori static void usage(const char *name) 1392e3aff4f6Saliguori { 1393e3aff4f6Saliguori printf( 13949a2d77adSChristoph Hellwig "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" 139584844a20SStefan Weil "QEMU Disk exerciser\n" 1396e3aff4f6Saliguori "\n" 1397e3aff4f6Saliguori " -c, --cmd command to execute\n" 1398e3aff4f6Saliguori " -r, --read-only export read-only\n" 1399e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 1400e3aff4f6Saliguori " -n, --nocache disable host cache\n" 14011db6947dSChristoph Hellwig " -g, --growable allow file to grow (only applies to protocols)\n" 1402e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 14035c6c3a6cSChristoph Hellwig " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 1404e3aff4f6Saliguori " -h, --help display this help and exit\n" 1405e3aff4f6Saliguori " -V, --version output version information and exit\n" 1406e3aff4f6Saliguori "\n", 1407e3aff4f6Saliguori name); 1408e3aff4f6Saliguori } 1409e3aff4f6Saliguori 1410e3aff4f6Saliguori 1411e3aff4f6Saliguori int main(int argc, char **argv) 1412e3aff4f6Saliguori { 1413e3aff4f6Saliguori int readonly = 0; 14149c4bab26SChristoph Hellwig int growable = 0; 14159a2d77adSChristoph Hellwig const char *sopt = "hVc:rsnmgk"; 1416b32bb952SBlue Swirl const struct option lopt[] = { 1417660f11beSBlue Swirl { "help", 0, NULL, 'h' }, 1418660f11beSBlue Swirl { "version", 0, NULL, 'V' }, 1419660f11beSBlue Swirl { "offset", 1, NULL, 'o' }, 1420660f11beSBlue Swirl { "cmd", 1, NULL, 'c' }, 1421660f11beSBlue Swirl { "read-only", 0, NULL, 'r' }, 1422660f11beSBlue Swirl { "snapshot", 0, NULL, 's' }, 1423660f11beSBlue Swirl { "nocache", 0, NULL, 'n' }, 1424660f11beSBlue Swirl { "misalign", 0, NULL, 'm' }, 1425660f11beSBlue Swirl { "growable", 0, NULL, 'g' }, 14265c6c3a6cSChristoph Hellwig { "native-aio", 0, NULL, 'k' }, 1427660f11beSBlue Swirl { NULL, 0, NULL, 0 } 1428e3aff4f6Saliguori }; 1429e3aff4f6Saliguori int c; 1430e3aff4f6Saliguori int opt_index = 0; 1431e3aff4f6Saliguori int flags = 0; 1432e3aff4f6Saliguori 1433e3aff4f6Saliguori progname = basename(argv[0]); 1434e3aff4f6Saliguori 1435e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1436e3aff4f6Saliguori switch (c) { 1437e3aff4f6Saliguori case 's': 1438e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1439e3aff4f6Saliguori break; 1440e3aff4f6Saliguori case 'n': 1441e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 1442e3aff4f6Saliguori break; 1443e3aff4f6Saliguori case 'c': 1444e3aff4f6Saliguori add_user_command(optarg); 1445e3aff4f6Saliguori break; 1446e3aff4f6Saliguori case 'r': 1447e3aff4f6Saliguori readonly = 1; 1448e3aff4f6Saliguori break; 1449e3aff4f6Saliguori case 'm': 1450e3aff4f6Saliguori misalign = 1; 1451e3aff4f6Saliguori break; 14529c4bab26SChristoph Hellwig case 'g': 14539c4bab26SChristoph Hellwig growable = 1; 14549c4bab26SChristoph Hellwig break; 14555c6c3a6cSChristoph Hellwig case 'k': 14565c6c3a6cSChristoph Hellwig flags |= BDRV_O_NATIVE_AIO; 14575c6c3a6cSChristoph Hellwig break; 1458e3aff4f6Saliguori case 'V': 1459e3aff4f6Saliguori printf("%s version %s\n", progname, VERSION); 1460e3aff4f6Saliguori exit(0); 1461e3aff4f6Saliguori case 'h': 1462e3aff4f6Saliguori usage(progname); 1463e3aff4f6Saliguori exit(0); 1464e3aff4f6Saliguori default: 1465e3aff4f6Saliguori usage(progname); 1466e3aff4f6Saliguori exit(1); 1467e3aff4f6Saliguori } 1468e3aff4f6Saliguori } 1469e3aff4f6Saliguori 1470e3aff4f6Saliguori if ((argc - optind) > 1) { 1471e3aff4f6Saliguori usage(progname); 1472e3aff4f6Saliguori exit(1); 1473e3aff4f6Saliguori } 1474e3aff4f6Saliguori 1475e3aff4f6Saliguori bdrv_init(); 1476e3aff4f6Saliguori 1477e3aff4f6Saliguori /* initialize commands */ 1478e3aff4f6Saliguori quit_init(); 1479e3aff4f6Saliguori help_init(); 1480e3aff4f6Saliguori add_command(&open_cmd); 1481e3aff4f6Saliguori add_command(&close_cmd); 1482e3aff4f6Saliguori add_command(&read_cmd); 1483e3aff4f6Saliguori add_command(&readv_cmd); 1484e3aff4f6Saliguori add_command(&write_cmd); 1485e3aff4f6Saliguori add_command(&writev_cmd); 148695533d5fSChristoph Hellwig add_command(&aio_read_cmd); 148795533d5fSChristoph Hellwig add_command(&aio_write_cmd); 148895533d5fSChristoph Hellwig add_command(&aio_flush_cmd); 1489e3aff4f6Saliguori add_command(&flush_cmd); 1490e3aff4f6Saliguori add_command(&truncate_cmd); 1491e3aff4f6Saliguori add_command(&length_cmd); 1492e3aff4f6Saliguori add_command(&info_cmd); 1493e3aff4f6Saliguori add_command(&alloc_cmd); 1494e3aff4f6Saliguori 1495e3aff4f6Saliguori add_args_command(init_args_command); 1496e3aff4f6Saliguori add_check_command(init_check_command); 1497e3aff4f6Saliguori 1498e3aff4f6Saliguori /* open the device */ 1499f5edb014SNaphtali Sprei if (!readonly) { 1500e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1501f5edb014SNaphtali Sprei } 1502e3aff4f6Saliguori 1503e3aff4f6Saliguori if ((argc - optind) == 1) 15049c4bab26SChristoph Hellwig openfile(argv[optind], flags, growable); 1505e3aff4f6Saliguori command_loop(); 1506e3aff4f6Saliguori 150795533d5fSChristoph Hellwig /* 150895533d5fSChristoph Hellwig * Make sure all outstanding requests get flushed the program exits. 150995533d5fSChristoph Hellwig */ 151095533d5fSChristoph Hellwig qemu_aio_flush(); 151195533d5fSChristoph Hellwig 1512e3aff4f6Saliguori if (bs) 1513e3aff4f6Saliguori bdrv_close(bs); 1514e3aff4f6Saliguori return 0; 1515e3aff4f6Saliguori } 1516