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 */ 10e3aff4f6Saliguori #include <sys/types.h> 11e3aff4f6Saliguori #include <stdarg.h> 12e3aff4f6Saliguori #include <stdio.h> 13e3aff4f6Saliguori #include <getopt.h> 14e3aff4f6Saliguori 15e3aff4f6Saliguori #include "qemu-common.h" 16e3aff4f6Saliguori #include "block_int.h" 17e3aff4f6Saliguori #include "cmd.h" 18e3aff4f6Saliguori 19e3aff4f6Saliguori #define VERSION "0.0.1" 20e3aff4f6Saliguori 21e3aff4f6Saliguori #define CMD_NOFILE_OK 0x01 22e3aff4f6Saliguori 23e3aff4f6Saliguori char *progname; 24e3aff4f6Saliguori static BlockDriverState *bs; 25e3aff4f6Saliguori 26e3aff4f6Saliguori static int misalign; 27e3aff4f6Saliguori 28e3aff4f6Saliguori /* 29e3aff4f6Saliguori * Memory allocation helpers. 30e3aff4f6Saliguori * 31e3aff4f6Saliguori * Make sure memory is aligned by default, or purposefully misaligned if 32e3aff4f6Saliguori * that is specified on the command line. 33e3aff4f6Saliguori */ 34e3aff4f6Saliguori 35e3aff4f6Saliguori #define MISALIGN_OFFSET 16 36e3aff4f6Saliguori static void *qemu_io_alloc(size_t len, int pattern) 37e3aff4f6Saliguori { 38e3aff4f6Saliguori void *buf; 39e3aff4f6Saliguori 40e3aff4f6Saliguori if (misalign) 41e3aff4f6Saliguori len += MISALIGN_OFFSET; 42e3aff4f6Saliguori buf = qemu_memalign(512, len); 43e3aff4f6Saliguori memset(buf, pattern, len); 44e3aff4f6Saliguori if (misalign) 45e3aff4f6Saliguori buf += MISALIGN_OFFSET; 46e3aff4f6Saliguori return buf; 47e3aff4f6Saliguori } 48e3aff4f6Saliguori 49e3aff4f6Saliguori static void qemu_io_free(void *p) 50e3aff4f6Saliguori { 51e3aff4f6Saliguori if (misalign) 52e3aff4f6Saliguori p -= MISALIGN_OFFSET; 53e3aff4f6Saliguori qemu_vfree(p); 54e3aff4f6Saliguori } 55e3aff4f6Saliguori 56e3aff4f6Saliguori static void 573abcdf49SStefan Weil dump_buffer(const void *buffer, int64_t offset, int len) 58e3aff4f6Saliguori { 59e3aff4f6Saliguori int i, j; 603abcdf49SStefan Weil const uint8_t *p; 61e3aff4f6Saliguori 62e3aff4f6Saliguori for (i = 0, p = buffer; i < len; i += 16) { 633abcdf49SStefan Weil const uint8_t *s = p; 64e3aff4f6Saliguori 65e3aff4f6Saliguori printf("%08llx: ", (unsigned long long)offset + i); 66e3aff4f6Saliguori for (j = 0; j < 16 && i + j < len; j++, p++) 67e3aff4f6Saliguori printf("%02x ", *p); 68e3aff4f6Saliguori printf(" "); 69e3aff4f6Saliguori for (j = 0; j < 16 && i + j < len; j++, s++) { 703abcdf49SStefan Weil if (isalnum(*s)) 71e3aff4f6Saliguori printf("%c", *s); 72e3aff4f6Saliguori else 73e3aff4f6Saliguori printf("."); 74e3aff4f6Saliguori } 75e3aff4f6Saliguori printf("\n"); 76e3aff4f6Saliguori } 77e3aff4f6Saliguori } 78e3aff4f6Saliguori 79e3aff4f6Saliguori static void 80e3aff4f6Saliguori print_report(const char *op, struct timeval *t, int64_t offset, 81e3aff4f6Saliguori int count, int total, int cnt, int Cflag) 82e3aff4f6Saliguori { 83e3aff4f6Saliguori char s1[64], s2[64], ts[64]; 84e3aff4f6Saliguori 85e3aff4f6Saliguori timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); 86e3aff4f6Saliguori if (!Cflag) { 87e3aff4f6Saliguori cvtstr((double)total, s1, sizeof(s1)); 88e3aff4f6Saliguori cvtstr(tdiv((double)total, *t), s2, sizeof(s2)); 89e3aff4f6Saliguori printf("%s %d/%d bytes at offset %lld\n", 90e3aff4f6Saliguori op, total, count, (long long)offset); 91e3aff4f6Saliguori printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n", 92e3aff4f6Saliguori s1, cnt, ts, s2, tdiv((double)cnt, *t)); 93e3aff4f6Saliguori } else {/* bytes,ops,time,bytes/sec,ops/sec */ 94e3aff4f6Saliguori printf("%d,%d,%s,%.3f,%.3f\n", 95e3aff4f6Saliguori total, cnt, ts, 96e3aff4f6Saliguori tdiv((double)total, *t), 97e3aff4f6Saliguori tdiv((double)cnt, *t)); 98e3aff4f6Saliguori } 99e3aff4f6Saliguori } 100e3aff4f6Saliguori 101e3aff4f6Saliguori static int do_read(char *buf, int64_t offset, int count, int *total) 102e3aff4f6Saliguori { 103e3aff4f6Saliguori int ret; 104e3aff4f6Saliguori 105e3aff4f6Saliguori ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9); 106e3aff4f6Saliguori if (ret < 0) 107e3aff4f6Saliguori return ret; 108e3aff4f6Saliguori *total = count; 109e3aff4f6Saliguori return 1; 110e3aff4f6Saliguori } 111e3aff4f6Saliguori 112e3aff4f6Saliguori static int do_write(char *buf, int64_t offset, int count, int *total) 113e3aff4f6Saliguori { 114e3aff4f6Saliguori int ret; 115e3aff4f6Saliguori 116e3aff4f6Saliguori ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9); 117e3aff4f6Saliguori if (ret < 0) 118e3aff4f6Saliguori return ret; 119e3aff4f6Saliguori *total = count; 120e3aff4f6Saliguori return 1; 121e3aff4f6Saliguori } 122e3aff4f6Saliguori 123e3aff4f6Saliguori static int do_pread(char *buf, int64_t offset, int count, int *total) 124e3aff4f6Saliguori { 125e3aff4f6Saliguori *total = bdrv_pread(bs, offset, (uint8_t *)buf, count); 126e3aff4f6Saliguori if (*total < 0) 127e3aff4f6Saliguori return *total; 128e3aff4f6Saliguori return 1; 129e3aff4f6Saliguori } 130e3aff4f6Saliguori 131e3aff4f6Saliguori static int do_pwrite(char *buf, int64_t offset, int count, int *total) 132e3aff4f6Saliguori { 133e3aff4f6Saliguori *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count); 134e3aff4f6Saliguori if (*total < 0) 135e3aff4f6Saliguori return *total; 136e3aff4f6Saliguori return 1; 137e3aff4f6Saliguori } 138e3aff4f6Saliguori 139e3aff4f6Saliguori #define NOT_DONE 0x7fffffff 140e3aff4f6Saliguori static void aio_rw_done(void *opaque, int ret) 141e3aff4f6Saliguori { 142e3aff4f6Saliguori *(int *)opaque = ret; 143e3aff4f6Saliguori } 144e3aff4f6Saliguori 145e3aff4f6Saliguori static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total) 146e3aff4f6Saliguori { 147e3aff4f6Saliguori BlockDriverAIOCB *acb; 148e3aff4f6Saliguori int async_ret = NOT_DONE; 149e3aff4f6Saliguori 150e3aff4f6Saliguori acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, 151e3aff4f6Saliguori aio_rw_done, &async_ret); 152e3aff4f6Saliguori if (!acb) 153e3aff4f6Saliguori return -EIO; 154e3aff4f6Saliguori 155e3aff4f6Saliguori while (async_ret == NOT_DONE) 156e3aff4f6Saliguori qemu_aio_wait(); 157e3aff4f6Saliguori 158e3aff4f6Saliguori *total = qiov->size; 159e3aff4f6Saliguori return async_ret < 0 ? async_ret : 1; 160e3aff4f6Saliguori } 161e3aff4f6Saliguori 162e3aff4f6Saliguori static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) 163e3aff4f6Saliguori { 164e3aff4f6Saliguori BlockDriverAIOCB *acb; 165e3aff4f6Saliguori int async_ret = NOT_DONE; 166e3aff4f6Saliguori 167e3aff4f6Saliguori acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, 168e3aff4f6Saliguori aio_rw_done, &async_ret); 169e3aff4f6Saliguori if (!acb) 170e3aff4f6Saliguori return -EIO; 171e3aff4f6Saliguori 172e3aff4f6Saliguori while (async_ret == NOT_DONE) 173e3aff4f6Saliguori qemu_aio_wait(); 174e3aff4f6Saliguori 1757e9bbc9fSaliguori *total = qiov->size; 176e3aff4f6Saliguori return async_ret < 0 ? async_ret : 1; 177e3aff4f6Saliguori } 178e3aff4f6Saliguori 179e3aff4f6Saliguori 180e3aff4f6Saliguori static const cmdinfo_t read_cmd; 181e3aff4f6Saliguori 182e3aff4f6Saliguori static void 183e3aff4f6Saliguori read_help(void) 184e3aff4f6Saliguori { 185e3aff4f6Saliguori printf( 186e3aff4f6Saliguori "\n" 187e3aff4f6Saliguori " reads a range of bytes from the given offset\n" 188e3aff4f6Saliguori "\n" 189e3aff4f6Saliguori " Example:\n" 190e3aff4f6Saliguori " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 191e3aff4f6Saliguori "\n" 192e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 193e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 194d9654a58SKevin Wolf " -C, -- report statistics in a machine parsable format\n" 195d9654a58SKevin Wolf " -l, -- length for pattern verification (only with -P)\n" 196e3aff4f6Saliguori " -p, -- use bdrv_pread to read the file\n" 197c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 198e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 199d9654a58SKevin Wolf " -s, -- start offset for pattern verification (only with -P)\n" 200d9654a58SKevin Wolf " -v, -- dump buffer to standard output\n" 201e3aff4f6Saliguori "\n"); 202e3aff4f6Saliguori } 203e3aff4f6Saliguori 204e3aff4f6Saliguori static int 205e3aff4f6Saliguori read_f(int argc, char **argv) 206e3aff4f6Saliguori { 207e3aff4f6Saliguori struct timeval t1, t2; 208e3aff4f6Saliguori int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 209d9654a58SKevin Wolf int Pflag = 0, sflag = 0, lflag = 0; 210e3aff4f6Saliguori int c, cnt; 211e3aff4f6Saliguori char *buf; 212e3aff4f6Saliguori int64_t offset; 213d4ec5228SPaul Brook int count; 214d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 215d4ec5228SPaul Brook int total = 0; 216d9654a58SKevin Wolf int pattern = 0, pattern_offset = 0, pattern_count = 0; 217e3aff4f6Saliguori 218d9654a58SKevin Wolf while ((c = getopt(argc, argv, "Cl:pP:qs:v")) != EOF) { 219e3aff4f6Saliguori switch (c) { 220e3aff4f6Saliguori case 'C': 221e3aff4f6Saliguori Cflag = 1; 222e3aff4f6Saliguori break; 223d9654a58SKevin Wolf case 'l': 224d9654a58SKevin Wolf lflag = 1; 225d9654a58SKevin Wolf pattern_count = cvtnum(optarg); 226d9654a58SKevin Wolf if (pattern_count < 0) { 227d9654a58SKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 228d9654a58SKevin Wolf return 0; 229d9654a58SKevin Wolf } 230d9654a58SKevin Wolf break; 231e3aff4f6Saliguori case 'p': 232e3aff4f6Saliguori pflag = 1; 233e3aff4f6Saliguori break; 234c48101aeSaliguori case 'P': 235c48101aeSaliguori Pflag = 1; 236c48101aeSaliguori pattern = atoi(optarg); 237c48101aeSaliguori break; 238e3aff4f6Saliguori case 'q': 239e3aff4f6Saliguori qflag = 1; 240e3aff4f6Saliguori break; 241d9654a58SKevin Wolf case 's': 242d9654a58SKevin Wolf sflag = 1; 243d9654a58SKevin Wolf pattern_offset = cvtnum(optarg); 244d9654a58SKevin Wolf if (pattern_offset < 0) { 245d9654a58SKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 246d9654a58SKevin Wolf return 0; 247d9654a58SKevin Wolf } 248d9654a58SKevin Wolf break; 249e3aff4f6Saliguori case 'v': 250e3aff4f6Saliguori vflag = 1; 251e3aff4f6Saliguori break; 252e3aff4f6Saliguori default: 253e3aff4f6Saliguori return command_usage(&read_cmd); 254e3aff4f6Saliguori } 255e3aff4f6Saliguori } 256e3aff4f6Saliguori 257e3aff4f6Saliguori if (optind != argc - 2) 258e3aff4f6Saliguori return command_usage(&read_cmd); 259e3aff4f6Saliguori 260e3aff4f6Saliguori offset = cvtnum(argv[optind]); 261e3aff4f6Saliguori if (offset < 0) { 262e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 263e3aff4f6Saliguori return 0; 264e3aff4f6Saliguori } 265e3aff4f6Saliguori 266e3aff4f6Saliguori optind++; 267e3aff4f6Saliguori count = cvtnum(argv[optind]); 268e3aff4f6Saliguori if (count < 0) { 269e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 270e3aff4f6Saliguori return 0; 271e3aff4f6Saliguori } 272e3aff4f6Saliguori 273d9654a58SKevin Wolf if (!Pflag && (lflag || sflag)) { 274d9654a58SKevin Wolf return command_usage(&read_cmd); 275d9654a58SKevin Wolf } 276d9654a58SKevin Wolf 277d9654a58SKevin Wolf if (!lflag) { 278d9654a58SKevin Wolf pattern_count = count - pattern_offset; 279d9654a58SKevin Wolf } 280d9654a58SKevin Wolf 281d9654a58SKevin Wolf if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 282d9654a58SKevin Wolf printf("pattern verfication range exceeds end of read data\n"); 283d9654a58SKevin Wolf return 0; 284d9654a58SKevin Wolf } 285d9654a58SKevin Wolf 286e3aff4f6Saliguori if (!pflag) 287e3aff4f6Saliguori if (offset & 0x1ff) { 288e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 289e3aff4f6Saliguori (long long)offset); 290e3aff4f6Saliguori return 0; 291e3aff4f6Saliguori 292e3aff4f6Saliguori if (count & 0x1ff) { 293e3aff4f6Saliguori printf("count %d is not sector aligned\n", 294e3aff4f6Saliguori count); 295e3aff4f6Saliguori return 0; 296e3aff4f6Saliguori } 297e3aff4f6Saliguori } 298e3aff4f6Saliguori 299e3aff4f6Saliguori buf = qemu_io_alloc(count, 0xab); 300e3aff4f6Saliguori 301e3aff4f6Saliguori gettimeofday(&t1, NULL); 302e3aff4f6Saliguori if (pflag) 303e3aff4f6Saliguori cnt = do_pread(buf, offset, count, &total); 304e3aff4f6Saliguori else 305e3aff4f6Saliguori cnt = do_read(buf, offset, count, &total); 306e3aff4f6Saliguori gettimeofday(&t2, NULL); 307e3aff4f6Saliguori 308e3aff4f6Saliguori if (cnt < 0) { 309e3aff4f6Saliguori printf("read failed: %s\n", strerror(-cnt)); 310e3aff4f6Saliguori return 0; 311e3aff4f6Saliguori } 312e3aff4f6Saliguori 313c48101aeSaliguori if (Pflag) { 314d9654a58SKevin Wolf void* cmp_buf = malloc(pattern_count); 315d9654a58SKevin Wolf memset(cmp_buf, pattern, pattern_count); 316d9654a58SKevin Wolf if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 317c48101aeSaliguori printf("Pattern verification failed at offset %lld, " 318c48101aeSaliguori "%d bytes\n", 319d9654a58SKevin Wolf (long long) offset + pattern_offset, pattern_count); 320c48101aeSaliguori } 321c48101aeSaliguori free(cmp_buf); 322c48101aeSaliguori } 323c48101aeSaliguori 324e3aff4f6Saliguori if (qflag) 325e3aff4f6Saliguori return 0; 326e3aff4f6Saliguori 327e3aff4f6Saliguori if (vflag) 328e3aff4f6Saliguori dump_buffer(buf, offset, count); 329e3aff4f6Saliguori 330e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 331e3aff4f6Saliguori t2 = tsub(t2, t1); 332e3aff4f6Saliguori print_report("read", &t2, offset, count, total, cnt, Cflag); 333e3aff4f6Saliguori 334e3aff4f6Saliguori qemu_io_free(buf); 335e3aff4f6Saliguori 336e3aff4f6Saliguori return 0; 337e3aff4f6Saliguori } 338e3aff4f6Saliguori 339e3aff4f6Saliguori static const cmdinfo_t read_cmd = { 340e3aff4f6Saliguori .name = "read", 341e3aff4f6Saliguori .altname = "r", 342e3aff4f6Saliguori .cfunc = read_f, 343e3aff4f6Saliguori .argmin = 2, 344e3aff4f6Saliguori .argmax = -1, 345d9654a58SKevin Wolf .args = "[-aCpqv] [-P pattern [-s off] [-l len]] off len", 346e3aff4f6Saliguori .oneline = "reads a number of bytes at a specified offset", 347e3aff4f6Saliguori .help = read_help, 348e3aff4f6Saliguori }; 349e3aff4f6Saliguori 350e3aff4f6Saliguori static const cmdinfo_t readv_cmd; 351e3aff4f6Saliguori 352e3aff4f6Saliguori static void 353e3aff4f6Saliguori readv_help(void) 354e3aff4f6Saliguori { 355e3aff4f6Saliguori printf( 356e3aff4f6Saliguori "\n" 357e3aff4f6Saliguori " reads a range of bytes from the given offset into multiple buffers\n" 358e3aff4f6Saliguori "\n" 359e3aff4f6Saliguori " Example:\n" 360e3aff4f6Saliguori " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 361e3aff4f6Saliguori "\n" 362e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 363e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 364e3aff4f6Saliguori " Uses multiple iovec buffers if more than one byte range is specified.\n" 365e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 366c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 367e3aff4f6Saliguori " -v, -- dump buffer to standard output\n" 368e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 369e3aff4f6Saliguori "\n"); 370e3aff4f6Saliguori } 371e3aff4f6Saliguori 372e3aff4f6Saliguori static int 373e3aff4f6Saliguori readv_f(int argc, char **argv) 374e3aff4f6Saliguori { 375e3aff4f6Saliguori struct timeval t1, t2; 376e3aff4f6Saliguori int Cflag = 0, qflag = 0, vflag = 0; 377e3aff4f6Saliguori int c, cnt; 378e3aff4f6Saliguori char *buf, *p; 379e3aff4f6Saliguori int64_t offset; 380e3aff4f6Saliguori int count = 0, total; 381e3aff4f6Saliguori int nr_iov, i; 382e3aff4f6Saliguori QEMUIOVector qiov; 383c48101aeSaliguori int pattern = 0; 384c48101aeSaliguori int Pflag = 0; 385e3aff4f6Saliguori 386c48101aeSaliguori while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 387e3aff4f6Saliguori switch (c) { 388e3aff4f6Saliguori case 'C': 389e3aff4f6Saliguori Cflag = 1; 390e3aff4f6Saliguori break; 391c48101aeSaliguori case 'P': 392c48101aeSaliguori Pflag = 1; 393c48101aeSaliguori pattern = atoi(optarg); 394c48101aeSaliguori break; 395e3aff4f6Saliguori case 'q': 396e3aff4f6Saliguori qflag = 1; 397e3aff4f6Saliguori break; 398e3aff4f6Saliguori case 'v': 399e3aff4f6Saliguori vflag = 1; 400e3aff4f6Saliguori break; 401e3aff4f6Saliguori default: 402e3aff4f6Saliguori return command_usage(&readv_cmd); 403e3aff4f6Saliguori } 404e3aff4f6Saliguori } 405e3aff4f6Saliguori 406e3aff4f6Saliguori if (optind > argc - 2) 407e3aff4f6Saliguori return command_usage(&readv_cmd); 408e3aff4f6Saliguori 409e3aff4f6Saliguori 410e3aff4f6Saliguori offset = cvtnum(argv[optind]); 411e3aff4f6Saliguori if (offset < 0) { 412e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 413e3aff4f6Saliguori return 0; 414e3aff4f6Saliguori } 415e3aff4f6Saliguori optind++; 416e3aff4f6Saliguori 417e3aff4f6Saliguori if (offset & 0x1ff) { 418e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 419e3aff4f6Saliguori (long long)offset); 420e3aff4f6Saliguori return 0; 421e3aff4f6Saliguori } 422e3aff4f6Saliguori 423e3aff4f6Saliguori if (count & 0x1ff) { 424e3aff4f6Saliguori printf("count %d is not sector aligned\n", 425e3aff4f6Saliguori count); 426e3aff4f6Saliguori return 0; 427e3aff4f6Saliguori } 428e3aff4f6Saliguori 429e3aff4f6Saliguori for (i = optind; i < argc; i++) { 430e3aff4f6Saliguori size_t len; 431e3aff4f6Saliguori 432e3aff4f6Saliguori len = cvtnum(argv[i]); 433e3aff4f6Saliguori if (len < 0) { 434e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[i]); 435e3aff4f6Saliguori return 0; 436e3aff4f6Saliguori } 437e3aff4f6Saliguori count += len; 438e3aff4f6Saliguori } 439e3aff4f6Saliguori 440e3aff4f6Saliguori nr_iov = argc - optind; 441e3aff4f6Saliguori qemu_iovec_init(&qiov, nr_iov); 442e3aff4f6Saliguori buf = p = qemu_io_alloc(count, 0xab); 443e3aff4f6Saliguori for (i = 0; i < nr_iov; i++) { 444e3aff4f6Saliguori size_t len; 445e3aff4f6Saliguori 446e3aff4f6Saliguori len = cvtnum(argv[optind]); 447e3aff4f6Saliguori if (len < 0) { 448e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", 449e3aff4f6Saliguori argv[optind]); 450e3aff4f6Saliguori return 0; 451e3aff4f6Saliguori } 452e3aff4f6Saliguori 453e3aff4f6Saliguori qemu_iovec_add(&qiov, p, len); 454e3aff4f6Saliguori p += len; 455e3aff4f6Saliguori optind++; 456e3aff4f6Saliguori } 457e3aff4f6Saliguori 458e3aff4f6Saliguori gettimeofday(&t1, NULL); 459e3aff4f6Saliguori cnt = do_aio_readv(&qiov, offset, &total); 460e3aff4f6Saliguori gettimeofday(&t2, NULL); 461e3aff4f6Saliguori 462e3aff4f6Saliguori if (cnt < 0) { 463e3aff4f6Saliguori printf("readv failed: %s\n", strerror(-cnt)); 464e3aff4f6Saliguori return 0; 465e3aff4f6Saliguori } 466e3aff4f6Saliguori 467c48101aeSaliguori if (Pflag) { 468c48101aeSaliguori void* cmp_buf = malloc(count); 469c48101aeSaliguori memset(cmp_buf, pattern, count); 470c48101aeSaliguori if (memcmp(buf, cmp_buf, count)) { 471c48101aeSaliguori printf("Pattern verification failed at offset %lld, " 472c48101aeSaliguori "%d bytes\n", 473c48101aeSaliguori (long long) offset, count); 474c48101aeSaliguori } 475c48101aeSaliguori free(cmp_buf); 476c48101aeSaliguori } 477c48101aeSaliguori 478e3aff4f6Saliguori if (qflag) 479e3aff4f6Saliguori return 0; 480e3aff4f6Saliguori 481e3aff4f6Saliguori if (vflag) 482e3aff4f6Saliguori dump_buffer(buf, offset, qiov.size); 483e3aff4f6Saliguori 484e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 485e3aff4f6Saliguori t2 = tsub(t2, t1); 486e3aff4f6Saliguori print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 487e3aff4f6Saliguori 488e3aff4f6Saliguori qemu_io_free(buf); 489e3aff4f6Saliguori 490e3aff4f6Saliguori return 0; 491e3aff4f6Saliguori } 492e3aff4f6Saliguori 493e3aff4f6Saliguori static const cmdinfo_t readv_cmd = { 494e3aff4f6Saliguori .name = "readv", 495e3aff4f6Saliguori .cfunc = readv_f, 496e3aff4f6Saliguori .argmin = 2, 497e3aff4f6Saliguori .argmax = -1, 498c48101aeSaliguori .args = "[-Cqv] [-P pattern ] off len [len..]", 499e3aff4f6Saliguori .oneline = "reads a number of bytes at a specified offset", 500e3aff4f6Saliguori .help = readv_help, 501e3aff4f6Saliguori }; 502e3aff4f6Saliguori 503e3aff4f6Saliguori static const cmdinfo_t write_cmd; 504e3aff4f6Saliguori 505e3aff4f6Saliguori static void 506e3aff4f6Saliguori write_help(void) 507e3aff4f6Saliguori { 508e3aff4f6Saliguori printf( 509e3aff4f6Saliguori "\n" 510e3aff4f6Saliguori " writes a range of bytes from the given offset\n" 511e3aff4f6Saliguori "\n" 512e3aff4f6Saliguori " Example:\n" 513e3aff4f6Saliguori " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 514e3aff4f6Saliguori "\n" 515e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 516e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 517e3aff4f6Saliguori " -p, -- use bdrv_pwrite to write the file\n" 518e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 519e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 520e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 521e3aff4f6Saliguori "\n"); 522e3aff4f6Saliguori } 523e3aff4f6Saliguori 524e3aff4f6Saliguori static int 525e3aff4f6Saliguori write_f(int argc, char **argv) 526e3aff4f6Saliguori { 527e3aff4f6Saliguori struct timeval t1, t2; 528e3aff4f6Saliguori int Cflag = 0, pflag = 0, qflag = 0; 529e3aff4f6Saliguori int c, cnt; 530e3aff4f6Saliguori char *buf; 531e3aff4f6Saliguori int64_t offset; 532d4ec5228SPaul Brook int count; 533d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 534d4ec5228SPaul Brook int total = 0; 535e3aff4f6Saliguori int pattern = 0xcd; 536e3aff4f6Saliguori 537e3aff4f6Saliguori while ((c = getopt(argc, argv, "CpP:q")) != EOF) { 538e3aff4f6Saliguori switch (c) { 539e3aff4f6Saliguori case 'C': 540e3aff4f6Saliguori Cflag = 1; 541e3aff4f6Saliguori break; 542e3aff4f6Saliguori case 'p': 543e3aff4f6Saliguori pflag = 1; 544e3aff4f6Saliguori break; 545e3aff4f6Saliguori case 'P': 546e3aff4f6Saliguori pattern = atoi(optarg); 547e3aff4f6Saliguori break; 548e3aff4f6Saliguori case 'q': 549e3aff4f6Saliguori qflag = 1; 550e3aff4f6Saliguori break; 551e3aff4f6Saliguori default: 552e3aff4f6Saliguori return command_usage(&write_cmd); 553e3aff4f6Saliguori } 554e3aff4f6Saliguori } 555e3aff4f6Saliguori 556e3aff4f6Saliguori if (optind != argc - 2) 557e3aff4f6Saliguori return command_usage(&write_cmd); 558e3aff4f6Saliguori 559e3aff4f6Saliguori offset = cvtnum(argv[optind]); 560e3aff4f6Saliguori if (offset < 0) { 561e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 562e3aff4f6Saliguori return 0; 563e3aff4f6Saliguori } 564e3aff4f6Saliguori 565e3aff4f6Saliguori optind++; 566e3aff4f6Saliguori count = cvtnum(argv[optind]); 567e3aff4f6Saliguori if (count < 0) { 568e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 569e3aff4f6Saliguori return 0; 570e3aff4f6Saliguori } 571e3aff4f6Saliguori 572e3aff4f6Saliguori if (!pflag) { 573e3aff4f6Saliguori if (offset & 0x1ff) { 574e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 575e3aff4f6Saliguori (long long)offset); 576e3aff4f6Saliguori return 0; 577e3aff4f6Saliguori } 578e3aff4f6Saliguori 579e3aff4f6Saliguori if (count & 0x1ff) { 580e3aff4f6Saliguori printf("count %d is not sector aligned\n", 581e3aff4f6Saliguori count); 582e3aff4f6Saliguori return 0; 583e3aff4f6Saliguori } 584e3aff4f6Saliguori } 585e3aff4f6Saliguori 586e3aff4f6Saliguori buf = qemu_io_alloc(count, pattern); 587e3aff4f6Saliguori 588e3aff4f6Saliguori gettimeofday(&t1, NULL); 589e3aff4f6Saliguori if (pflag) 590e3aff4f6Saliguori cnt = do_pwrite(buf, offset, count, &total); 591e3aff4f6Saliguori else 592e3aff4f6Saliguori cnt = do_write(buf, offset, count, &total); 593e3aff4f6Saliguori gettimeofday(&t2, NULL); 594e3aff4f6Saliguori 595e3aff4f6Saliguori if (cnt < 0) { 596e3aff4f6Saliguori printf("write failed: %s\n", strerror(-cnt)); 597e3aff4f6Saliguori return 0; 598e3aff4f6Saliguori } 599e3aff4f6Saliguori 600e3aff4f6Saliguori if (qflag) 601e3aff4f6Saliguori return 0; 602e3aff4f6Saliguori 603e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 604e3aff4f6Saliguori t2 = tsub(t2, t1); 605e3aff4f6Saliguori print_report("wrote", &t2, offset, count, total, cnt, Cflag); 606e3aff4f6Saliguori 607e3aff4f6Saliguori qemu_io_free(buf); 608e3aff4f6Saliguori 609e3aff4f6Saliguori return 0; 610e3aff4f6Saliguori } 611e3aff4f6Saliguori 612e3aff4f6Saliguori static const cmdinfo_t write_cmd = { 613e3aff4f6Saliguori .name = "write", 614e3aff4f6Saliguori .altname = "w", 615e3aff4f6Saliguori .cfunc = write_f, 616e3aff4f6Saliguori .argmin = 2, 617e3aff4f6Saliguori .argmax = -1, 618e3aff4f6Saliguori .args = "[-aCpq] [-P pattern ] off len", 619e3aff4f6Saliguori .oneline = "writes a number of bytes at a specified offset", 620e3aff4f6Saliguori .help = write_help, 621e3aff4f6Saliguori }; 622e3aff4f6Saliguori 623e3aff4f6Saliguori static const cmdinfo_t writev_cmd; 624e3aff4f6Saliguori 625e3aff4f6Saliguori static void 626e3aff4f6Saliguori writev_help(void) 627e3aff4f6Saliguori { 628e3aff4f6Saliguori printf( 629e3aff4f6Saliguori "\n" 630e3aff4f6Saliguori " writes a range of bytes from the given offset source from multiple buffers\n" 631e3aff4f6Saliguori "\n" 632e3aff4f6Saliguori " Example:\n" 633e3aff4f6Saliguori " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 634e3aff4f6Saliguori "\n" 635e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 636e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 637e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 638e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 639e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 640e3aff4f6Saliguori "\n"); 641e3aff4f6Saliguori } 642e3aff4f6Saliguori 643e3aff4f6Saliguori static int 644e3aff4f6Saliguori writev_f(int argc, char **argv) 645e3aff4f6Saliguori { 646e3aff4f6Saliguori struct timeval t1, t2; 647e3aff4f6Saliguori int Cflag = 0, qflag = 0; 648e3aff4f6Saliguori int c, cnt; 649e3aff4f6Saliguori char *buf, *p; 650e3aff4f6Saliguori int64_t offset; 651e3aff4f6Saliguori int count = 0, total; 652e3aff4f6Saliguori int nr_iov, i; 653e3aff4f6Saliguori int pattern = 0xcd; 654e3aff4f6Saliguori QEMUIOVector qiov; 655e3aff4f6Saliguori 656e3aff4f6Saliguori while ((c = getopt(argc, argv, "CqP:")) != EOF) { 657e3aff4f6Saliguori switch (c) { 658e3aff4f6Saliguori case 'C': 659e3aff4f6Saliguori Cflag = 1; 660e3aff4f6Saliguori break; 661e3aff4f6Saliguori case 'q': 662e3aff4f6Saliguori qflag = 1; 663e3aff4f6Saliguori break; 664e3aff4f6Saliguori case 'P': 665e3aff4f6Saliguori pattern = atoi(optarg); 666e3aff4f6Saliguori break; 667e3aff4f6Saliguori default: 668e3aff4f6Saliguori return command_usage(&writev_cmd); 669e3aff4f6Saliguori } 670e3aff4f6Saliguori } 671e3aff4f6Saliguori 672e3aff4f6Saliguori if (optind > argc - 2) 673e3aff4f6Saliguori return command_usage(&writev_cmd); 674e3aff4f6Saliguori 675e3aff4f6Saliguori offset = cvtnum(argv[optind]); 676e3aff4f6Saliguori if (offset < 0) { 677e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 678e3aff4f6Saliguori return 0; 679e3aff4f6Saliguori } 680e3aff4f6Saliguori optind++; 681e3aff4f6Saliguori 682e3aff4f6Saliguori if (offset & 0x1ff) { 683e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 684e3aff4f6Saliguori (long long)offset); 685e3aff4f6Saliguori return 0; 686e3aff4f6Saliguori } 687e3aff4f6Saliguori 688e3aff4f6Saliguori if (count & 0x1ff) { 689e3aff4f6Saliguori printf("count %d is not sector aligned\n", 690e3aff4f6Saliguori count); 691e3aff4f6Saliguori return 0; 692e3aff4f6Saliguori } 693e3aff4f6Saliguori 694e3aff4f6Saliguori 695e3aff4f6Saliguori for (i = optind; i < argc; i++) { 696e3aff4f6Saliguori size_t len; 697e3aff4f6Saliguori 698e3aff4f6Saliguori len = cvtnum(argv[optind]); 699e3aff4f6Saliguori if (len < 0) { 700e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[i]); 701e3aff4f6Saliguori return 0; 702e3aff4f6Saliguori } 703e3aff4f6Saliguori count += len; 704e3aff4f6Saliguori } 705e3aff4f6Saliguori 706e3aff4f6Saliguori nr_iov = argc - optind; 707e3aff4f6Saliguori qemu_iovec_init(&qiov, nr_iov); 7087e9bbc9fSaliguori buf = p = qemu_io_alloc(count, pattern); 709e3aff4f6Saliguori for (i = 0; i < nr_iov; i++) { 710e3aff4f6Saliguori size_t len; 711e3aff4f6Saliguori 712e3aff4f6Saliguori len = cvtnum(argv[optind]); 713e3aff4f6Saliguori if (len < 0) { 714e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", 715e3aff4f6Saliguori argv[optind]); 716e3aff4f6Saliguori return 0; 717e3aff4f6Saliguori } 718e3aff4f6Saliguori 719e3aff4f6Saliguori qemu_iovec_add(&qiov, p, len); 720e3aff4f6Saliguori p += len; 721e3aff4f6Saliguori optind++; 722e3aff4f6Saliguori } 723e3aff4f6Saliguori 724e3aff4f6Saliguori gettimeofday(&t1, NULL); 725e3aff4f6Saliguori cnt = do_aio_writev(&qiov, offset, &total); 726e3aff4f6Saliguori gettimeofday(&t2, NULL); 727e3aff4f6Saliguori 728e3aff4f6Saliguori if (cnt < 0) { 729e3aff4f6Saliguori printf("writev failed: %s\n", strerror(-cnt)); 730e3aff4f6Saliguori return 0; 731e3aff4f6Saliguori } 732e3aff4f6Saliguori 733e3aff4f6Saliguori if (qflag) 734e3aff4f6Saliguori return 0; 735e3aff4f6Saliguori 736e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 737e3aff4f6Saliguori t2 = tsub(t2, t1); 738e3aff4f6Saliguori print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 739e3aff4f6Saliguori 740e3aff4f6Saliguori qemu_io_free(buf); 741e3aff4f6Saliguori 742e3aff4f6Saliguori return 0; 743e3aff4f6Saliguori } 744e3aff4f6Saliguori 745e3aff4f6Saliguori static const cmdinfo_t writev_cmd = { 746e3aff4f6Saliguori .name = "writev", 747e3aff4f6Saliguori .cfunc = writev_f, 748e3aff4f6Saliguori .argmin = 2, 749e3aff4f6Saliguori .argmax = -1, 750e3aff4f6Saliguori .args = "[-Cq] [-P pattern ] off len [len..]", 751e3aff4f6Saliguori .oneline = "writes a number of bytes at a specified offset", 752e3aff4f6Saliguori .help = writev_help, 753e3aff4f6Saliguori }; 754e3aff4f6Saliguori 75595533d5fSChristoph Hellwig struct aio_ctx { 75695533d5fSChristoph Hellwig QEMUIOVector qiov; 75795533d5fSChristoph Hellwig int64_t offset; 75895533d5fSChristoph Hellwig char *buf; 75995533d5fSChristoph Hellwig int qflag; 76095533d5fSChristoph Hellwig int vflag; 76195533d5fSChristoph Hellwig int Cflag; 76295533d5fSChristoph Hellwig int Pflag; 76395533d5fSChristoph Hellwig int pattern; 76495533d5fSChristoph Hellwig struct timeval t1; 76595533d5fSChristoph Hellwig }; 76695533d5fSChristoph Hellwig 76795533d5fSChristoph Hellwig static void 76895533d5fSChristoph Hellwig aio_write_done(void *opaque, int ret) 76995533d5fSChristoph Hellwig { 77095533d5fSChristoph Hellwig struct aio_ctx *ctx = opaque; 77195533d5fSChristoph Hellwig struct timeval t2; 77295533d5fSChristoph Hellwig 77395533d5fSChristoph Hellwig gettimeofday(&t2, NULL); 77495533d5fSChristoph Hellwig 77595533d5fSChristoph Hellwig 77695533d5fSChristoph Hellwig if (ret < 0) { 77795533d5fSChristoph Hellwig printf("aio_write failed: %s\n", strerror(-ret)); 77895533d5fSChristoph Hellwig return; 77995533d5fSChristoph Hellwig } 78095533d5fSChristoph Hellwig 781*230d4fa4SChristoph Hellwig if (ctx->qflag) { 78295533d5fSChristoph Hellwig return; 783*230d4fa4SChristoph Hellwig } 78495533d5fSChristoph Hellwig 78595533d5fSChristoph Hellwig /* Finally, report back -- -C gives a parsable format */ 78695533d5fSChristoph Hellwig t2 = tsub(t2, ctx->t1); 787*230d4fa4SChristoph Hellwig print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 788*230d4fa4SChristoph Hellwig ctx->qiov.size, 1, ctx->Cflag); 78995533d5fSChristoph Hellwig 79095533d5fSChristoph Hellwig qemu_io_free(ctx->buf); 79195533d5fSChristoph Hellwig free(ctx); 79295533d5fSChristoph Hellwig } 79395533d5fSChristoph Hellwig 79495533d5fSChristoph Hellwig static const cmdinfo_t aio_read_cmd; 79595533d5fSChristoph Hellwig 79695533d5fSChristoph Hellwig static void 79795533d5fSChristoph Hellwig aio_read_done(void *opaque, int ret) 79895533d5fSChristoph Hellwig { 79995533d5fSChristoph Hellwig struct aio_ctx *ctx = opaque; 80095533d5fSChristoph Hellwig struct timeval t2; 80195533d5fSChristoph Hellwig 80295533d5fSChristoph Hellwig gettimeofday(&t2, NULL); 80395533d5fSChristoph Hellwig 80495533d5fSChristoph Hellwig if (ret < 0) { 80595533d5fSChristoph Hellwig printf("readv failed: %s\n", strerror(-ret)); 80695533d5fSChristoph Hellwig return; 80795533d5fSChristoph Hellwig } 80895533d5fSChristoph Hellwig 80995533d5fSChristoph Hellwig if (ctx->Pflag) { 810*230d4fa4SChristoph Hellwig void *cmp_buf = malloc(ctx->qiov.size); 81195533d5fSChristoph Hellwig 812*230d4fa4SChristoph Hellwig memset(cmp_buf, ctx->pattern, ctx->qiov.size); 813*230d4fa4SChristoph Hellwig if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 81495533d5fSChristoph Hellwig printf("Pattern verification failed at offset %lld, " 815*230d4fa4SChristoph Hellwig "%zd bytes\n", 816*230d4fa4SChristoph Hellwig (long long) ctx->offset, ctx->qiov.size); 81795533d5fSChristoph Hellwig } 81895533d5fSChristoph Hellwig free(cmp_buf); 81995533d5fSChristoph Hellwig } 82095533d5fSChristoph Hellwig 821*230d4fa4SChristoph Hellwig if (ctx->qflag) { 82295533d5fSChristoph Hellwig return; 823*230d4fa4SChristoph Hellwig } 82495533d5fSChristoph Hellwig 825*230d4fa4SChristoph Hellwig if (ctx->vflag) { 826*230d4fa4SChristoph Hellwig dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 827*230d4fa4SChristoph Hellwig } 82895533d5fSChristoph Hellwig 82995533d5fSChristoph Hellwig /* Finally, report back -- -C gives a parsable format */ 83095533d5fSChristoph Hellwig t2 = tsub(t2, ctx->t1); 831*230d4fa4SChristoph Hellwig print_report("read", &t2, ctx->offset, ctx->qiov.size, 832*230d4fa4SChristoph Hellwig ctx->qiov.size, 1, ctx->Cflag); 83395533d5fSChristoph Hellwig 83495533d5fSChristoph Hellwig qemu_io_free(ctx->buf); 83595533d5fSChristoph Hellwig free(ctx); 83695533d5fSChristoph Hellwig } 83795533d5fSChristoph Hellwig 83895533d5fSChristoph Hellwig static void 83995533d5fSChristoph Hellwig aio_read_help(void) 84095533d5fSChristoph Hellwig { 84195533d5fSChristoph Hellwig printf( 84295533d5fSChristoph Hellwig "\n" 84395533d5fSChristoph Hellwig " asynchronously reads a range of bytes from the given offset\n" 84495533d5fSChristoph Hellwig "\n" 84595533d5fSChristoph Hellwig " Example:\n" 84695533d5fSChristoph Hellwig " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 84795533d5fSChristoph Hellwig "\n" 84895533d5fSChristoph Hellwig " Reads a segment of the currently open file, optionally dumping it to the\n" 84995533d5fSChristoph Hellwig " standard output stream (with -v option) for subsequent inspection.\n" 85095533d5fSChristoph Hellwig " The read is performed asynchronously and should the aio_flush command \n" 85195533d5fSChristoph Hellwig " should be used to ensure all outstanding aio requests have been completed\n" 85295533d5fSChristoph Hellwig " -C, -- report statistics in a machine parsable format\n" 85395533d5fSChristoph Hellwig " -P, -- use a pattern to verify read data\n" 85495533d5fSChristoph Hellwig " -v, -- dump buffer to standard output\n" 85595533d5fSChristoph Hellwig " -q, -- quite mode, do not show I/O statistics\n" 85695533d5fSChristoph Hellwig "\n"); 85795533d5fSChristoph Hellwig } 85895533d5fSChristoph Hellwig 85995533d5fSChristoph Hellwig static int 86095533d5fSChristoph Hellwig aio_read_f(int argc, char **argv) 86195533d5fSChristoph Hellwig { 86295533d5fSChristoph Hellwig char *p; 86395533d5fSChristoph Hellwig int count = 0; 86495533d5fSChristoph Hellwig int nr_iov, i, c; 86595533d5fSChristoph Hellwig struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 86695533d5fSChristoph Hellwig BlockDriverAIOCB *acb; 86795533d5fSChristoph Hellwig 86895533d5fSChristoph Hellwig while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 86995533d5fSChristoph Hellwig switch (c) { 87095533d5fSChristoph Hellwig case 'C': 87195533d5fSChristoph Hellwig ctx->Cflag = 1; 87295533d5fSChristoph Hellwig break; 87395533d5fSChristoph Hellwig case 'P': 87495533d5fSChristoph Hellwig ctx->Pflag = 1; 87595533d5fSChristoph Hellwig ctx->pattern = atoi(optarg); 87695533d5fSChristoph Hellwig break; 87795533d5fSChristoph Hellwig case 'q': 87895533d5fSChristoph Hellwig ctx->qflag = 1; 87995533d5fSChristoph Hellwig break; 88095533d5fSChristoph Hellwig case 'v': 88195533d5fSChristoph Hellwig ctx->vflag = 1; 88295533d5fSChristoph Hellwig break; 88395533d5fSChristoph Hellwig default: 88495533d5fSChristoph Hellwig return command_usage(&aio_read_cmd); 88595533d5fSChristoph Hellwig } 88695533d5fSChristoph Hellwig } 88795533d5fSChristoph Hellwig 88895533d5fSChristoph Hellwig if (optind > argc - 2) 88995533d5fSChristoph Hellwig return command_usage(&aio_read_cmd); 89095533d5fSChristoph Hellwig 89195533d5fSChristoph Hellwig 89295533d5fSChristoph Hellwig ctx->offset = cvtnum(argv[optind]); 89395533d5fSChristoph Hellwig if (ctx->offset < 0) { 89495533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[optind]); 89595533d5fSChristoph Hellwig return 0; 89695533d5fSChristoph Hellwig } 89795533d5fSChristoph Hellwig optind++; 89895533d5fSChristoph Hellwig 89995533d5fSChristoph Hellwig if (ctx->offset & 0x1ff) { 90095533d5fSChristoph Hellwig printf("offset %lld is not sector aligned\n", 90195533d5fSChristoph Hellwig (long long)ctx->offset); 90295533d5fSChristoph Hellwig return 0; 90395533d5fSChristoph Hellwig } 90495533d5fSChristoph Hellwig 90595533d5fSChristoph Hellwig if (count & 0x1ff) { 90695533d5fSChristoph Hellwig printf("count %d is not sector aligned\n", 90795533d5fSChristoph Hellwig count); 90895533d5fSChristoph Hellwig return 0; 90995533d5fSChristoph Hellwig } 91095533d5fSChristoph Hellwig 91195533d5fSChristoph Hellwig for (i = optind; i < argc; i++) { 91295533d5fSChristoph Hellwig size_t len; 91395533d5fSChristoph Hellwig 91495533d5fSChristoph Hellwig len = cvtnum(argv[i]); 91595533d5fSChristoph Hellwig if (len < 0) { 91695533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[i]); 91795533d5fSChristoph Hellwig return 0; 91895533d5fSChristoph Hellwig } 91995533d5fSChristoph Hellwig count += len; 92095533d5fSChristoph Hellwig } 92195533d5fSChristoph Hellwig 92295533d5fSChristoph Hellwig nr_iov = argc - optind; 92395533d5fSChristoph Hellwig qemu_iovec_init(&ctx->qiov, nr_iov); 92495533d5fSChristoph Hellwig ctx->buf = p = qemu_io_alloc(count, 0xab); 92595533d5fSChristoph Hellwig for (i = 0; i < nr_iov; i++) { 92695533d5fSChristoph Hellwig size_t len; 92795533d5fSChristoph Hellwig 92895533d5fSChristoph Hellwig len = cvtnum(argv[optind]); 92995533d5fSChristoph Hellwig if (len < 0) { 93095533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", 93195533d5fSChristoph Hellwig argv[optind]); 93295533d5fSChristoph Hellwig return 0; 93395533d5fSChristoph Hellwig } 93495533d5fSChristoph Hellwig 93595533d5fSChristoph Hellwig qemu_iovec_add(&ctx->qiov, p, len); 93695533d5fSChristoph Hellwig p += len; 93795533d5fSChristoph Hellwig optind++; 93895533d5fSChristoph Hellwig } 93995533d5fSChristoph Hellwig 94095533d5fSChristoph Hellwig gettimeofday(&ctx->t1, NULL); 94195533d5fSChristoph Hellwig acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 94295533d5fSChristoph Hellwig ctx->qiov.size >> 9, aio_read_done, ctx); 94395533d5fSChristoph Hellwig if (!acb) 94495533d5fSChristoph Hellwig return -EIO; 94595533d5fSChristoph Hellwig 94695533d5fSChristoph Hellwig return 0; 94795533d5fSChristoph Hellwig } 94895533d5fSChristoph Hellwig 94995533d5fSChristoph Hellwig static const cmdinfo_t aio_read_cmd = { 95095533d5fSChristoph Hellwig .name = "aio_read", 95195533d5fSChristoph Hellwig .cfunc = aio_read_f, 95295533d5fSChristoph Hellwig .argmin = 2, 95395533d5fSChristoph Hellwig .argmax = -1, 95495533d5fSChristoph Hellwig .args = "[-Cqv] [-P pattern ] off len [len..]", 95595533d5fSChristoph Hellwig .oneline = "asynchronously reads a number of bytes", 95695533d5fSChristoph Hellwig .help = aio_read_help, 95795533d5fSChristoph Hellwig }; 95895533d5fSChristoph Hellwig 95995533d5fSChristoph Hellwig static const cmdinfo_t aio_write_cmd; 96095533d5fSChristoph Hellwig 96195533d5fSChristoph Hellwig static void 96295533d5fSChristoph Hellwig aio_write_help(void) 96395533d5fSChristoph Hellwig { 96495533d5fSChristoph Hellwig printf( 96595533d5fSChristoph Hellwig "\n" 96695533d5fSChristoph Hellwig " asynchronously writes a range of bytes from the given offset source \n" 96795533d5fSChristoph Hellwig " from multiple buffers\n" 96895533d5fSChristoph Hellwig "\n" 96995533d5fSChristoph Hellwig " Example:\n" 97095533d5fSChristoph Hellwig " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 97195533d5fSChristoph Hellwig "\n" 97295533d5fSChristoph Hellwig " Writes into a segment of the currently open file, using a buffer\n" 97395533d5fSChristoph Hellwig " filled with a set pattern (0xcdcdcdcd).\n" 97495533d5fSChristoph Hellwig " The write is performed asynchronously and should the aio_flush command \n" 97595533d5fSChristoph Hellwig " should be used to ensure all outstanding aio requests have been completed\n" 97695533d5fSChristoph Hellwig " -P, -- use different pattern to fill file\n" 97795533d5fSChristoph Hellwig " -C, -- report statistics in a machine parsable format\n" 97895533d5fSChristoph Hellwig " -q, -- quite mode, do not show I/O statistics\n" 97995533d5fSChristoph Hellwig "\n"); 98095533d5fSChristoph Hellwig } 98195533d5fSChristoph Hellwig 98295533d5fSChristoph Hellwig 98395533d5fSChristoph Hellwig static int 98495533d5fSChristoph Hellwig aio_write_f(int argc, char **argv) 98595533d5fSChristoph Hellwig { 98695533d5fSChristoph Hellwig char *p; 98795533d5fSChristoph Hellwig int count = 0; 98895533d5fSChristoph Hellwig int nr_iov, i, c; 98995533d5fSChristoph Hellwig int pattern = 0xcd; 99095533d5fSChristoph Hellwig struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); 99195533d5fSChristoph Hellwig BlockDriverAIOCB *acb; 99295533d5fSChristoph Hellwig 99395533d5fSChristoph Hellwig while ((c = getopt(argc, argv, "CqP:")) != EOF) { 99495533d5fSChristoph Hellwig switch (c) { 99595533d5fSChristoph Hellwig case 'C': 99695533d5fSChristoph Hellwig ctx->Cflag = 1; 99795533d5fSChristoph Hellwig break; 99895533d5fSChristoph Hellwig case 'q': 99995533d5fSChristoph Hellwig ctx->qflag = 1; 100095533d5fSChristoph Hellwig break; 100195533d5fSChristoph Hellwig case 'P': 100295533d5fSChristoph Hellwig pattern = atoi(optarg); 100395533d5fSChristoph Hellwig break; 100495533d5fSChristoph Hellwig default: 100595533d5fSChristoph Hellwig return command_usage(&aio_write_cmd); 100695533d5fSChristoph Hellwig } 100795533d5fSChristoph Hellwig } 100895533d5fSChristoph Hellwig 100995533d5fSChristoph Hellwig if (optind > argc - 2) 101095533d5fSChristoph Hellwig return command_usage(&aio_write_cmd); 101195533d5fSChristoph Hellwig 101295533d5fSChristoph Hellwig ctx->offset = cvtnum(argv[optind]); 101395533d5fSChristoph Hellwig if (ctx->offset < 0) { 101495533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[optind]); 101595533d5fSChristoph Hellwig return 0; 101695533d5fSChristoph Hellwig } 101795533d5fSChristoph Hellwig optind++; 101895533d5fSChristoph Hellwig 101995533d5fSChristoph Hellwig if (ctx->offset & 0x1ff) { 102095533d5fSChristoph Hellwig printf("offset %lld is not sector aligned\n", 102195533d5fSChristoph Hellwig (long long)ctx->offset); 102295533d5fSChristoph Hellwig return 0; 102395533d5fSChristoph Hellwig } 102495533d5fSChristoph Hellwig 102595533d5fSChristoph Hellwig if (count & 0x1ff) { 102695533d5fSChristoph Hellwig printf("count %d is not sector aligned\n", 102795533d5fSChristoph Hellwig count); 102895533d5fSChristoph Hellwig return 0; 102995533d5fSChristoph Hellwig } 103095533d5fSChristoph Hellwig 103195533d5fSChristoph Hellwig for (i = optind; i < argc; i++) { 103295533d5fSChristoph Hellwig size_t len; 103395533d5fSChristoph Hellwig 103495533d5fSChristoph Hellwig len = cvtnum(argv[optind]); 103595533d5fSChristoph Hellwig if (len < 0) { 103695533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", argv[i]); 103795533d5fSChristoph Hellwig return 0; 103895533d5fSChristoph Hellwig } 103995533d5fSChristoph Hellwig count += len; 104095533d5fSChristoph Hellwig } 104195533d5fSChristoph Hellwig 104295533d5fSChristoph Hellwig nr_iov = argc - optind; 104395533d5fSChristoph Hellwig qemu_iovec_init(&ctx->qiov, nr_iov); 104495533d5fSChristoph Hellwig ctx->buf = p = qemu_io_alloc(count, pattern); 104595533d5fSChristoph Hellwig for (i = 0; i < nr_iov; i++) { 104695533d5fSChristoph Hellwig size_t len; 104795533d5fSChristoph Hellwig 104895533d5fSChristoph Hellwig len = cvtnum(argv[optind]); 104995533d5fSChristoph Hellwig if (len < 0) { 105095533d5fSChristoph Hellwig printf("non-numeric length argument -- %s\n", 105195533d5fSChristoph Hellwig argv[optind]); 105295533d5fSChristoph Hellwig return 0; 105395533d5fSChristoph Hellwig } 105495533d5fSChristoph Hellwig 105595533d5fSChristoph Hellwig qemu_iovec_add(&ctx->qiov, p, len); 105695533d5fSChristoph Hellwig p += len; 105795533d5fSChristoph Hellwig optind++; 105895533d5fSChristoph Hellwig } 105995533d5fSChristoph Hellwig 106095533d5fSChristoph Hellwig gettimeofday(&ctx->t1, NULL); 106195533d5fSChristoph Hellwig acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 106295533d5fSChristoph Hellwig ctx->qiov.size >> 9, aio_write_done, ctx); 106395533d5fSChristoph Hellwig if (!acb) 106495533d5fSChristoph Hellwig return -EIO; 106595533d5fSChristoph Hellwig 106695533d5fSChristoph Hellwig return 0; 106795533d5fSChristoph Hellwig } 106895533d5fSChristoph Hellwig 106995533d5fSChristoph Hellwig static const cmdinfo_t aio_write_cmd = { 107095533d5fSChristoph Hellwig .name = "aio_write", 107195533d5fSChristoph Hellwig .cfunc = aio_write_f, 107295533d5fSChristoph Hellwig .argmin = 2, 107395533d5fSChristoph Hellwig .argmax = -1, 107495533d5fSChristoph Hellwig .args = "[-Cq] [-P pattern ] off len [len..]", 107595533d5fSChristoph Hellwig .oneline = "asynchronously writes a number of bytes", 107695533d5fSChristoph Hellwig .help = aio_write_help, 107795533d5fSChristoph Hellwig }; 107895533d5fSChristoph Hellwig 107995533d5fSChristoph Hellwig static int 108095533d5fSChristoph Hellwig aio_flush_f(int argc, char **argv) 108195533d5fSChristoph Hellwig { 108295533d5fSChristoph Hellwig qemu_aio_flush(); 108395533d5fSChristoph Hellwig return 0; 108495533d5fSChristoph Hellwig } 108595533d5fSChristoph Hellwig 108695533d5fSChristoph Hellwig static const cmdinfo_t aio_flush_cmd = { 108795533d5fSChristoph Hellwig .name = "aio_flush", 108895533d5fSChristoph Hellwig .cfunc = aio_flush_f, 108995533d5fSChristoph Hellwig .oneline = "completes all outstanding aio requets" 109095533d5fSChristoph Hellwig }; 109195533d5fSChristoph Hellwig 1092e3aff4f6Saliguori static int 1093e3aff4f6Saliguori flush_f(int argc, char **argv) 1094e3aff4f6Saliguori { 1095e3aff4f6Saliguori bdrv_flush(bs); 1096e3aff4f6Saliguori return 0; 1097e3aff4f6Saliguori } 1098e3aff4f6Saliguori 1099e3aff4f6Saliguori static const cmdinfo_t flush_cmd = { 1100e3aff4f6Saliguori .name = "flush", 1101e3aff4f6Saliguori .altname = "f", 1102e3aff4f6Saliguori .cfunc = flush_f, 1103e3aff4f6Saliguori .oneline = "flush all in-core file state to disk", 1104e3aff4f6Saliguori }; 1105e3aff4f6Saliguori 1106e3aff4f6Saliguori static int 1107e3aff4f6Saliguori truncate_f(int argc, char **argv) 1108e3aff4f6Saliguori { 1109e3aff4f6Saliguori int64_t offset; 1110e3aff4f6Saliguori int ret; 1111e3aff4f6Saliguori 1112e3aff4f6Saliguori offset = cvtnum(argv[1]); 1113e3aff4f6Saliguori if (offset < 0) { 1114e3aff4f6Saliguori printf("non-numeric truncate argument -- %s\n", argv[1]); 1115e3aff4f6Saliguori return 0; 1116e3aff4f6Saliguori } 1117e3aff4f6Saliguori 1118e3aff4f6Saliguori ret = bdrv_truncate(bs, offset); 1119e3aff4f6Saliguori if (ret < 0) { 1120e3aff4f6Saliguori printf("truncate: %s", strerror(ret)); 1121e3aff4f6Saliguori return 0; 1122e3aff4f6Saliguori } 1123e3aff4f6Saliguori 1124e3aff4f6Saliguori return 0; 1125e3aff4f6Saliguori } 1126e3aff4f6Saliguori 1127e3aff4f6Saliguori static const cmdinfo_t truncate_cmd = { 1128e3aff4f6Saliguori .name = "truncate", 1129e3aff4f6Saliguori .altname = "t", 1130e3aff4f6Saliguori .cfunc = truncate_f, 1131e3aff4f6Saliguori .argmin = 1, 1132e3aff4f6Saliguori .argmax = 1, 1133e3aff4f6Saliguori .args = "off", 1134e3aff4f6Saliguori .oneline = "truncates the current file at the given offset", 1135e3aff4f6Saliguori }; 1136e3aff4f6Saliguori 1137e3aff4f6Saliguori static int 1138e3aff4f6Saliguori length_f(int argc, char **argv) 1139e3aff4f6Saliguori { 1140e3aff4f6Saliguori int64_t size; 1141e3aff4f6Saliguori char s1[64]; 1142e3aff4f6Saliguori 1143e3aff4f6Saliguori size = bdrv_getlength(bs); 1144e3aff4f6Saliguori if (size < 0) { 1145e3aff4f6Saliguori printf("getlength: %s", strerror(size)); 1146e3aff4f6Saliguori return 0; 1147e3aff4f6Saliguori } 1148e3aff4f6Saliguori 1149e3aff4f6Saliguori cvtstr(size, s1, sizeof(s1)); 1150e3aff4f6Saliguori printf("%s\n", s1); 1151e3aff4f6Saliguori return 0; 1152e3aff4f6Saliguori } 1153e3aff4f6Saliguori 1154e3aff4f6Saliguori 1155e3aff4f6Saliguori static const cmdinfo_t length_cmd = { 1156e3aff4f6Saliguori .name = "length", 1157e3aff4f6Saliguori .altname = "l", 1158e3aff4f6Saliguori .cfunc = length_f, 1159e3aff4f6Saliguori .oneline = "gets the length of the current file", 1160e3aff4f6Saliguori }; 1161e3aff4f6Saliguori 1162e3aff4f6Saliguori 1163e3aff4f6Saliguori static int 1164e3aff4f6Saliguori info_f(int argc, char **argv) 1165e3aff4f6Saliguori { 1166e3aff4f6Saliguori BlockDriverInfo bdi; 1167e3aff4f6Saliguori char s1[64], s2[64]; 1168e3aff4f6Saliguori int ret; 1169e3aff4f6Saliguori 1170e3aff4f6Saliguori if (bs->drv && bs->drv->format_name) 1171e3aff4f6Saliguori printf("format name: %s\n", bs->drv->format_name); 1172e3aff4f6Saliguori if (bs->drv && bs->drv->protocol_name) 1173e3aff4f6Saliguori printf("format name: %s\n", bs->drv->protocol_name); 1174e3aff4f6Saliguori 1175e3aff4f6Saliguori ret = bdrv_get_info(bs, &bdi); 1176e3aff4f6Saliguori if (ret) 1177e3aff4f6Saliguori return 0; 1178e3aff4f6Saliguori 1179e3aff4f6Saliguori cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1180e3aff4f6Saliguori cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1181e3aff4f6Saliguori 1182e3aff4f6Saliguori printf("cluster size: %s\n", s1); 1183e3aff4f6Saliguori printf("vm state offset: %s\n", s2); 1184e3aff4f6Saliguori 1185e3aff4f6Saliguori return 0; 1186e3aff4f6Saliguori } 1187e3aff4f6Saliguori 1188e3aff4f6Saliguori 1189e3aff4f6Saliguori 1190e3aff4f6Saliguori static const cmdinfo_t info_cmd = { 1191e3aff4f6Saliguori .name = "info", 1192e3aff4f6Saliguori .altname = "i", 1193e3aff4f6Saliguori .cfunc = info_f, 1194e3aff4f6Saliguori .oneline = "prints information about the current file", 1195e3aff4f6Saliguori }; 1196e3aff4f6Saliguori 1197e3aff4f6Saliguori static int 1198e3aff4f6Saliguori alloc_f(int argc, char **argv) 1199e3aff4f6Saliguori { 1200e3aff4f6Saliguori int64_t offset; 1201e3aff4f6Saliguori int nb_sectors; 1202e3aff4f6Saliguori char s1[64]; 1203e3aff4f6Saliguori int num; 1204e3aff4f6Saliguori int ret; 1205838ab728Saliguori const char *retstr; 1206e3aff4f6Saliguori 1207e3aff4f6Saliguori offset = cvtnum(argv[1]); 1208e3aff4f6Saliguori if (offset & 0x1ff) { 1209e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 1210e3aff4f6Saliguori (long long)offset); 1211e3aff4f6Saliguori return 0; 1212e3aff4f6Saliguori } 1213e3aff4f6Saliguori 1214e3aff4f6Saliguori if (argc == 3) 1215e3aff4f6Saliguori nb_sectors = cvtnum(argv[2]); 1216e3aff4f6Saliguori else 1217e3aff4f6Saliguori nb_sectors = 1; 1218e3aff4f6Saliguori 1219e3aff4f6Saliguori ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); 1220e3aff4f6Saliguori 1221e3aff4f6Saliguori cvtstr(offset, s1, sizeof(s1)); 1222e3aff4f6Saliguori 1223838ab728Saliguori retstr = ret ? "allocated" : "not allocated"; 1224e3aff4f6Saliguori if (nb_sectors == 1) 1225838ab728Saliguori printf("sector %s at offset %s\n", retstr, s1); 1226e3aff4f6Saliguori else 1227838ab728Saliguori printf("%d/%d sectors %s at offset %s\n", 1228838ab728Saliguori num, nb_sectors, retstr, s1); 1229e3aff4f6Saliguori return 0; 1230e3aff4f6Saliguori } 1231e3aff4f6Saliguori 1232e3aff4f6Saliguori static const cmdinfo_t alloc_cmd = { 1233e3aff4f6Saliguori .name = "alloc", 1234e3aff4f6Saliguori .altname = "a", 1235e3aff4f6Saliguori .argmin = 1, 1236e3aff4f6Saliguori .argmax = 2, 1237e3aff4f6Saliguori .cfunc = alloc_f, 1238e3aff4f6Saliguori .args = "off [sectors]", 1239e3aff4f6Saliguori .oneline = "checks if a sector is present in the file", 1240e3aff4f6Saliguori }; 1241e3aff4f6Saliguori 1242e3aff4f6Saliguori static int 1243e3aff4f6Saliguori close_f(int argc, char **argv) 1244e3aff4f6Saliguori { 1245e3aff4f6Saliguori bdrv_close(bs); 1246e3aff4f6Saliguori bs = NULL; 1247e3aff4f6Saliguori return 0; 1248e3aff4f6Saliguori } 1249e3aff4f6Saliguori 1250e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 1251e3aff4f6Saliguori .name = "close", 1252e3aff4f6Saliguori .altname = "c", 1253e3aff4f6Saliguori .cfunc = close_f, 1254e3aff4f6Saliguori .oneline = "close the current open file", 1255e3aff4f6Saliguori }; 1256e3aff4f6Saliguori 1257e3aff4f6Saliguori static int openfile(char *name, int flags) 1258e3aff4f6Saliguori { 1259e3aff4f6Saliguori if (bs) { 1260e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 1261e3aff4f6Saliguori return 1; 1262e3aff4f6Saliguori } 1263e3aff4f6Saliguori 1264e3aff4f6Saliguori bs = bdrv_new("hda"); 1265e3aff4f6Saliguori if (!bs) 1266e3aff4f6Saliguori return 1; 1267e3aff4f6Saliguori 1268e3aff4f6Saliguori if (bdrv_open(bs, name, flags) == -1) { 1269e3aff4f6Saliguori fprintf(stderr, "%s: can't open device %s\n", progname, name); 1270e3aff4f6Saliguori bs = NULL; 1271e3aff4f6Saliguori return 1; 1272e3aff4f6Saliguori } 1273e3aff4f6Saliguori 1274e3aff4f6Saliguori return 0; 1275e3aff4f6Saliguori } 1276e3aff4f6Saliguori 1277e3aff4f6Saliguori static void 1278e3aff4f6Saliguori open_help(void) 1279e3aff4f6Saliguori { 1280e3aff4f6Saliguori printf( 1281e3aff4f6Saliguori "\n" 1282e3aff4f6Saliguori " opens a new file in the requested mode\n" 1283e3aff4f6Saliguori "\n" 1284e3aff4f6Saliguori " Example:\n" 1285e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 1286e3aff4f6Saliguori "\n" 1287e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 1288e3aff4f6Saliguori " -C, -- create new file if it doesn't exist\n" 1289e3aff4f6Saliguori " -r, -- open file read-only\n" 1290e3aff4f6Saliguori " -s, -- use snapshot file\n" 1291e3aff4f6Saliguori " -n, -- disable host cache\n" 1292e3aff4f6Saliguori "\n"); 1293e3aff4f6Saliguori } 1294e3aff4f6Saliguori 1295e3aff4f6Saliguori static const cmdinfo_t open_cmd; 1296e3aff4f6Saliguori 1297e3aff4f6Saliguori static int 1298e3aff4f6Saliguori open_f(int argc, char **argv) 1299e3aff4f6Saliguori { 1300e3aff4f6Saliguori int flags = 0; 1301e3aff4f6Saliguori int readonly = 0; 1302e3aff4f6Saliguori int c; 1303e3aff4f6Saliguori 1304e3aff4f6Saliguori while ((c = getopt(argc, argv, "snCr")) != EOF) { 1305e3aff4f6Saliguori switch (c) { 1306e3aff4f6Saliguori case 's': 1307e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1308e3aff4f6Saliguori break; 1309e3aff4f6Saliguori case 'n': 1310e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 1311e3aff4f6Saliguori break; 1312e3aff4f6Saliguori case 'C': 1313e3aff4f6Saliguori flags |= BDRV_O_CREAT; 1314e3aff4f6Saliguori break; 1315e3aff4f6Saliguori case 'r': 1316e3aff4f6Saliguori readonly = 1; 1317e3aff4f6Saliguori break; 1318e3aff4f6Saliguori default: 1319e3aff4f6Saliguori return command_usage(&open_cmd); 1320e3aff4f6Saliguori } 1321e3aff4f6Saliguori } 1322e3aff4f6Saliguori 1323e3aff4f6Saliguori if (readonly) 1324e3aff4f6Saliguori flags |= BDRV_O_RDONLY; 1325e3aff4f6Saliguori else 1326e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1327e3aff4f6Saliguori 1328e3aff4f6Saliguori if (optind != argc - 1) 1329e3aff4f6Saliguori return command_usage(&open_cmd); 1330e3aff4f6Saliguori 1331e3aff4f6Saliguori return openfile(argv[optind], flags); 1332e3aff4f6Saliguori } 1333e3aff4f6Saliguori 1334e3aff4f6Saliguori static const cmdinfo_t open_cmd = { 1335e3aff4f6Saliguori .name = "open", 1336e3aff4f6Saliguori .altname = "o", 1337e3aff4f6Saliguori .cfunc = open_f, 1338e3aff4f6Saliguori .argmin = 1, 1339e3aff4f6Saliguori .argmax = -1, 1340e3aff4f6Saliguori .flags = CMD_NOFILE_OK, 1341e3aff4f6Saliguori .args = "[-Crsn] [path]", 1342e3aff4f6Saliguori .oneline = "open the file specified by path", 1343e3aff4f6Saliguori .help = open_help, 1344e3aff4f6Saliguori }; 1345e3aff4f6Saliguori 1346e3aff4f6Saliguori static int 1347e3aff4f6Saliguori init_args_command( 1348e3aff4f6Saliguori int index) 1349e3aff4f6Saliguori { 1350e3aff4f6Saliguori /* only one device allowed so far */ 1351e3aff4f6Saliguori if (index >= 1) 1352e3aff4f6Saliguori return 0; 1353e3aff4f6Saliguori return ++index; 1354e3aff4f6Saliguori } 1355e3aff4f6Saliguori 1356e3aff4f6Saliguori static int 1357e3aff4f6Saliguori init_check_command( 1358e3aff4f6Saliguori const cmdinfo_t *ct) 1359e3aff4f6Saliguori { 1360e3aff4f6Saliguori if (ct->flags & CMD_FLAG_GLOBAL) 1361e3aff4f6Saliguori return 1; 1362e3aff4f6Saliguori if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1363e3aff4f6Saliguori fprintf(stderr, "no file open, try 'help open'\n"); 1364e3aff4f6Saliguori return 0; 1365e3aff4f6Saliguori } 1366e3aff4f6Saliguori return 1; 1367e3aff4f6Saliguori } 1368e3aff4f6Saliguori 1369e3aff4f6Saliguori static void usage(const char *name) 1370e3aff4f6Saliguori { 1371e3aff4f6Saliguori printf( 1372e3aff4f6Saliguori "Usage: %s [-h] [-V] [-Crsnm] [-c cmd] ... [file]\n" 137384844a20SStefan Weil "QEMU Disk exerciser\n" 1374e3aff4f6Saliguori "\n" 1375e3aff4f6Saliguori " -C, --create create new file if it doesn't exist\n" 1376e3aff4f6Saliguori " -c, --cmd command to execute\n" 1377e3aff4f6Saliguori " -r, --read-only export read-only\n" 1378e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 1379e3aff4f6Saliguori " -n, --nocache disable host cache\n" 1380e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 1381e3aff4f6Saliguori " -h, --help display this help and exit\n" 1382e3aff4f6Saliguori " -V, --version output version information and exit\n" 1383e3aff4f6Saliguori "\n", 1384e3aff4f6Saliguori name); 1385e3aff4f6Saliguori } 1386e3aff4f6Saliguori 1387e3aff4f6Saliguori 1388e3aff4f6Saliguori int main(int argc, char **argv) 1389e3aff4f6Saliguori { 1390e3aff4f6Saliguori int readonly = 0; 1391e3aff4f6Saliguori const char *sopt = "hVc:Crsnm"; 1392e3aff4f6Saliguori struct option lopt[] = { 1393e3aff4f6Saliguori { "help", 0, 0, 'h' }, 1394e3aff4f6Saliguori { "version", 0, 0, 'V' }, 1395e3aff4f6Saliguori { "offset", 1, 0, 'o' }, 1396e3aff4f6Saliguori { "cmd", 1, 0, 'c' }, 1397e3aff4f6Saliguori { "create", 0, 0, 'C' }, 1398e3aff4f6Saliguori { "read-only", 0, 0, 'r' }, 1399e3aff4f6Saliguori { "snapshot", 0, 0, 's' }, 1400e3aff4f6Saliguori { "nocache", 0, 0, 'n' }, 1401e3aff4f6Saliguori { "misalign", 0, 0, 'm' }, 1402e3aff4f6Saliguori { NULL, 0, 0, 0 } 1403e3aff4f6Saliguori }; 1404e3aff4f6Saliguori int c; 1405e3aff4f6Saliguori int opt_index = 0; 1406e3aff4f6Saliguori int flags = 0; 1407e3aff4f6Saliguori 1408e3aff4f6Saliguori progname = basename(argv[0]); 1409e3aff4f6Saliguori 1410e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1411e3aff4f6Saliguori switch (c) { 1412e3aff4f6Saliguori case 's': 1413e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1414e3aff4f6Saliguori break; 1415e3aff4f6Saliguori case 'n': 1416e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 1417e3aff4f6Saliguori break; 1418e3aff4f6Saliguori case 'c': 1419e3aff4f6Saliguori add_user_command(optarg); 1420e3aff4f6Saliguori break; 1421e3aff4f6Saliguori case 'C': 1422e3aff4f6Saliguori flags |= BDRV_O_CREAT; 1423e3aff4f6Saliguori break; 1424e3aff4f6Saliguori case 'r': 1425e3aff4f6Saliguori readonly = 1; 1426e3aff4f6Saliguori break; 1427e3aff4f6Saliguori case 'm': 1428e3aff4f6Saliguori misalign = 1; 1429e3aff4f6Saliguori break; 1430e3aff4f6Saliguori case 'V': 1431e3aff4f6Saliguori printf("%s version %s\n", progname, VERSION); 1432e3aff4f6Saliguori exit(0); 1433e3aff4f6Saliguori case 'h': 1434e3aff4f6Saliguori usage(progname); 1435e3aff4f6Saliguori exit(0); 1436e3aff4f6Saliguori default: 1437e3aff4f6Saliguori usage(progname); 1438e3aff4f6Saliguori exit(1); 1439e3aff4f6Saliguori } 1440e3aff4f6Saliguori } 1441e3aff4f6Saliguori 1442e3aff4f6Saliguori if ((argc - optind) > 1) { 1443e3aff4f6Saliguori usage(progname); 1444e3aff4f6Saliguori exit(1); 1445e3aff4f6Saliguori } 1446e3aff4f6Saliguori 1447e3aff4f6Saliguori bdrv_init(); 1448e3aff4f6Saliguori 1449e3aff4f6Saliguori /* initialize commands */ 1450e3aff4f6Saliguori quit_init(); 1451e3aff4f6Saliguori help_init(); 1452e3aff4f6Saliguori add_command(&open_cmd); 1453e3aff4f6Saliguori add_command(&close_cmd); 1454e3aff4f6Saliguori add_command(&read_cmd); 1455e3aff4f6Saliguori add_command(&readv_cmd); 1456e3aff4f6Saliguori add_command(&write_cmd); 1457e3aff4f6Saliguori add_command(&writev_cmd); 145895533d5fSChristoph Hellwig add_command(&aio_read_cmd); 145995533d5fSChristoph Hellwig add_command(&aio_write_cmd); 146095533d5fSChristoph Hellwig add_command(&aio_flush_cmd); 1461e3aff4f6Saliguori add_command(&flush_cmd); 1462e3aff4f6Saliguori add_command(&truncate_cmd); 1463e3aff4f6Saliguori add_command(&length_cmd); 1464e3aff4f6Saliguori add_command(&info_cmd); 1465e3aff4f6Saliguori add_command(&alloc_cmd); 1466e3aff4f6Saliguori 1467e3aff4f6Saliguori add_args_command(init_args_command); 1468e3aff4f6Saliguori add_check_command(init_check_command); 1469e3aff4f6Saliguori 1470e3aff4f6Saliguori /* open the device */ 1471e3aff4f6Saliguori if (readonly) 1472e3aff4f6Saliguori flags |= BDRV_O_RDONLY; 1473e3aff4f6Saliguori else 1474e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1475e3aff4f6Saliguori 1476e3aff4f6Saliguori if ((argc - optind) == 1) 1477e3aff4f6Saliguori openfile(argv[optind], flags); 1478e3aff4f6Saliguori command_loop(); 1479e3aff4f6Saliguori 148095533d5fSChristoph Hellwig /* 148195533d5fSChristoph Hellwig * Make sure all outstanding requests get flushed the program exits. 148295533d5fSChristoph Hellwig */ 148395533d5fSChristoph Hellwig qemu_aio_flush(); 148495533d5fSChristoph Hellwig 1485e3aff4f6Saliguori if (bs) 1486e3aff4f6Saliguori bdrv_close(bs); 1487e3aff4f6Saliguori return 0; 1488e3aff4f6Saliguori } 1489