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 57e3aff4f6Saliguori dump_buffer(char *buffer, int64_t offset, int len) 58e3aff4f6Saliguori { 59e3aff4f6Saliguori int i, j; 60e3aff4f6Saliguori char *p; 61e3aff4f6Saliguori 62e3aff4f6Saliguori for (i = 0, p = buffer; i < len; i += 16) { 63e3aff4f6Saliguori char *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++) { 70e3aff4f6Saliguori if (isalnum((int)*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; 213*d4ec5228SPaul Brook int count; 214*d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 215*d4ec5228SPaul 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; 532*d4ec5228SPaul Brook int count; 533*d4ec5228SPaul Brook /* Some compilers get confused and warn if this is not initialized. */ 534*d4ec5228SPaul 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 755e3aff4f6Saliguori static int 756e3aff4f6Saliguori flush_f(int argc, char **argv) 757e3aff4f6Saliguori { 758e3aff4f6Saliguori bdrv_flush(bs); 759e3aff4f6Saliguori return 0; 760e3aff4f6Saliguori } 761e3aff4f6Saliguori 762e3aff4f6Saliguori static const cmdinfo_t flush_cmd = { 763e3aff4f6Saliguori .name = "flush", 764e3aff4f6Saliguori .altname = "f", 765e3aff4f6Saliguori .cfunc = flush_f, 766e3aff4f6Saliguori .oneline = "flush all in-core file state to disk", 767e3aff4f6Saliguori }; 768e3aff4f6Saliguori 769e3aff4f6Saliguori static int 770e3aff4f6Saliguori truncate_f(int argc, char **argv) 771e3aff4f6Saliguori { 772e3aff4f6Saliguori int64_t offset; 773e3aff4f6Saliguori int ret; 774e3aff4f6Saliguori 775e3aff4f6Saliguori offset = cvtnum(argv[1]); 776e3aff4f6Saliguori if (offset < 0) { 777e3aff4f6Saliguori printf("non-numeric truncate argument -- %s\n", argv[1]); 778e3aff4f6Saliguori return 0; 779e3aff4f6Saliguori } 780e3aff4f6Saliguori 781e3aff4f6Saliguori ret = bdrv_truncate(bs, offset); 782e3aff4f6Saliguori if (ret < 0) { 783e3aff4f6Saliguori printf("truncate: %s", strerror(ret)); 784e3aff4f6Saliguori return 0; 785e3aff4f6Saliguori } 786e3aff4f6Saliguori 787e3aff4f6Saliguori return 0; 788e3aff4f6Saliguori } 789e3aff4f6Saliguori 790e3aff4f6Saliguori static const cmdinfo_t truncate_cmd = { 791e3aff4f6Saliguori .name = "truncate", 792e3aff4f6Saliguori .altname = "t", 793e3aff4f6Saliguori .cfunc = truncate_f, 794e3aff4f6Saliguori .argmin = 1, 795e3aff4f6Saliguori .argmax = 1, 796e3aff4f6Saliguori .args = "off", 797e3aff4f6Saliguori .oneline = "truncates the current file at the given offset", 798e3aff4f6Saliguori }; 799e3aff4f6Saliguori 800e3aff4f6Saliguori static int 801e3aff4f6Saliguori length_f(int argc, char **argv) 802e3aff4f6Saliguori { 803e3aff4f6Saliguori int64_t size; 804e3aff4f6Saliguori char s1[64]; 805e3aff4f6Saliguori 806e3aff4f6Saliguori size = bdrv_getlength(bs); 807e3aff4f6Saliguori if (size < 0) { 808e3aff4f6Saliguori printf("getlength: %s", strerror(size)); 809e3aff4f6Saliguori return 0; 810e3aff4f6Saliguori } 811e3aff4f6Saliguori 812e3aff4f6Saliguori cvtstr(size, s1, sizeof(s1)); 813e3aff4f6Saliguori printf("%s\n", s1); 814e3aff4f6Saliguori return 0; 815e3aff4f6Saliguori } 816e3aff4f6Saliguori 817e3aff4f6Saliguori 818e3aff4f6Saliguori static const cmdinfo_t length_cmd = { 819e3aff4f6Saliguori .name = "length", 820e3aff4f6Saliguori .altname = "l", 821e3aff4f6Saliguori .cfunc = length_f, 822e3aff4f6Saliguori .oneline = "gets the length of the current file", 823e3aff4f6Saliguori }; 824e3aff4f6Saliguori 825e3aff4f6Saliguori 826e3aff4f6Saliguori static int 827e3aff4f6Saliguori info_f(int argc, char **argv) 828e3aff4f6Saliguori { 829e3aff4f6Saliguori BlockDriverInfo bdi; 830e3aff4f6Saliguori char s1[64], s2[64]; 831e3aff4f6Saliguori int ret; 832e3aff4f6Saliguori 833e3aff4f6Saliguori if (bs->drv && bs->drv->format_name) 834e3aff4f6Saliguori printf("format name: %s\n", bs->drv->format_name); 835e3aff4f6Saliguori if (bs->drv && bs->drv->protocol_name) 836e3aff4f6Saliguori printf("format name: %s\n", bs->drv->protocol_name); 837e3aff4f6Saliguori 838e3aff4f6Saliguori ret = bdrv_get_info(bs, &bdi); 839e3aff4f6Saliguori if (ret) 840e3aff4f6Saliguori return 0; 841e3aff4f6Saliguori 842e3aff4f6Saliguori cvtstr(bdi.cluster_size, s1, sizeof(s1)); 843e3aff4f6Saliguori cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 844e3aff4f6Saliguori 845e3aff4f6Saliguori printf("cluster size: %s\n", s1); 846e3aff4f6Saliguori printf("vm state offset: %s\n", s2); 847e3aff4f6Saliguori 848e3aff4f6Saliguori return 0; 849e3aff4f6Saliguori } 850e3aff4f6Saliguori 851e3aff4f6Saliguori 852e3aff4f6Saliguori 853e3aff4f6Saliguori static const cmdinfo_t info_cmd = { 854e3aff4f6Saliguori .name = "info", 855e3aff4f6Saliguori .altname = "i", 856e3aff4f6Saliguori .cfunc = info_f, 857e3aff4f6Saliguori .oneline = "prints information about the current file", 858e3aff4f6Saliguori }; 859e3aff4f6Saliguori 860e3aff4f6Saliguori static int 861e3aff4f6Saliguori alloc_f(int argc, char **argv) 862e3aff4f6Saliguori { 863e3aff4f6Saliguori int64_t offset; 864e3aff4f6Saliguori int nb_sectors; 865e3aff4f6Saliguori char s1[64]; 866e3aff4f6Saliguori int num; 867e3aff4f6Saliguori int ret; 868838ab728Saliguori const char *retstr; 869e3aff4f6Saliguori 870e3aff4f6Saliguori offset = cvtnum(argv[1]); 871e3aff4f6Saliguori if (offset & 0x1ff) { 872e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 873e3aff4f6Saliguori (long long)offset); 874e3aff4f6Saliguori return 0; 875e3aff4f6Saliguori } 876e3aff4f6Saliguori 877e3aff4f6Saliguori if (argc == 3) 878e3aff4f6Saliguori nb_sectors = cvtnum(argv[2]); 879e3aff4f6Saliguori else 880e3aff4f6Saliguori nb_sectors = 1; 881e3aff4f6Saliguori 882e3aff4f6Saliguori ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); 883e3aff4f6Saliguori 884e3aff4f6Saliguori cvtstr(offset, s1, sizeof(s1)); 885e3aff4f6Saliguori 886838ab728Saliguori retstr = ret ? "allocated" : "not allocated"; 887e3aff4f6Saliguori if (nb_sectors == 1) 888838ab728Saliguori printf("sector %s at offset %s\n", retstr, s1); 889e3aff4f6Saliguori else 890838ab728Saliguori printf("%d/%d sectors %s at offset %s\n", 891838ab728Saliguori num, nb_sectors, retstr, s1); 892e3aff4f6Saliguori return 0; 893e3aff4f6Saliguori } 894e3aff4f6Saliguori 895e3aff4f6Saliguori static const cmdinfo_t alloc_cmd = { 896e3aff4f6Saliguori .name = "alloc", 897e3aff4f6Saliguori .altname = "a", 898e3aff4f6Saliguori .argmin = 1, 899e3aff4f6Saliguori .argmax = 2, 900e3aff4f6Saliguori .cfunc = alloc_f, 901e3aff4f6Saliguori .args = "off [sectors]", 902e3aff4f6Saliguori .oneline = "checks if a sector is present in the file", 903e3aff4f6Saliguori }; 904e3aff4f6Saliguori 905e3aff4f6Saliguori static int 906e3aff4f6Saliguori close_f(int argc, char **argv) 907e3aff4f6Saliguori { 908e3aff4f6Saliguori bdrv_close(bs); 909e3aff4f6Saliguori bs = NULL; 910e3aff4f6Saliguori return 0; 911e3aff4f6Saliguori } 912e3aff4f6Saliguori 913e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 914e3aff4f6Saliguori .name = "close", 915e3aff4f6Saliguori .altname = "c", 916e3aff4f6Saliguori .cfunc = close_f, 917e3aff4f6Saliguori .oneline = "close the current open file", 918e3aff4f6Saliguori }; 919e3aff4f6Saliguori 920e3aff4f6Saliguori static int openfile(char *name, int flags) 921e3aff4f6Saliguori { 922e3aff4f6Saliguori if (bs) { 923e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 924e3aff4f6Saliguori return 1; 925e3aff4f6Saliguori } 926e3aff4f6Saliguori 927e3aff4f6Saliguori bs = bdrv_new("hda"); 928e3aff4f6Saliguori if (!bs) 929e3aff4f6Saliguori return 1; 930e3aff4f6Saliguori 931e3aff4f6Saliguori if (bdrv_open(bs, name, flags) == -1) { 932e3aff4f6Saliguori fprintf(stderr, "%s: can't open device %s\n", progname, name); 933e3aff4f6Saliguori bs = NULL; 934e3aff4f6Saliguori return 1; 935e3aff4f6Saliguori } 936e3aff4f6Saliguori 937e3aff4f6Saliguori return 0; 938e3aff4f6Saliguori } 939e3aff4f6Saliguori 940e3aff4f6Saliguori static void 941e3aff4f6Saliguori open_help(void) 942e3aff4f6Saliguori { 943e3aff4f6Saliguori printf( 944e3aff4f6Saliguori "\n" 945e3aff4f6Saliguori " opens a new file in the requested mode\n" 946e3aff4f6Saliguori "\n" 947e3aff4f6Saliguori " Example:\n" 948e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 949e3aff4f6Saliguori "\n" 950e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 951e3aff4f6Saliguori " -C, -- create new file if it doesn't exist\n" 952e3aff4f6Saliguori " -r, -- open file read-only\n" 953e3aff4f6Saliguori " -s, -- use snapshot file\n" 954e3aff4f6Saliguori " -n, -- disable host cache\n" 955e3aff4f6Saliguori "\n"); 956e3aff4f6Saliguori } 957e3aff4f6Saliguori 958e3aff4f6Saliguori static const cmdinfo_t open_cmd; 959e3aff4f6Saliguori 960e3aff4f6Saliguori static int 961e3aff4f6Saliguori open_f(int argc, char **argv) 962e3aff4f6Saliguori { 963e3aff4f6Saliguori int flags = 0; 964e3aff4f6Saliguori int readonly = 0; 965e3aff4f6Saliguori int c; 966e3aff4f6Saliguori 967e3aff4f6Saliguori while ((c = getopt(argc, argv, "snCr")) != EOF) { 968e3aff4f6Saliguori switch (c) { 969e3aff4f6Saliguori case 's': 970e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 971e3aff4f6Saliguori break; 972e3aff4f6Saliguori case 'n': 973e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 974e3aff4f6Saliguori break; 975e3aff4f6Saliguori case 'C': 976e3aff4f6Saliguori flags |= BDRV_O_CREAT; 977e3aff4f6Saliguori break; 978e3aff4f6Saliguori case 'r': 979e3aff4f6Saliguori readonly = 1; 980e3aff4f6Saliguori break; 981e3aff4f6Saliguori default: 982e3aff4f6Saliguori return command_usage(&open_cmd); 983e3aff4f6Saliguori } 984e3aff4f6Saliguori } 985e3aff4f6Saliguori 986e3aff4f6Saliguori if (readonly) 987e3aff4f6Saliguori flags |= BDRV_O_RDONLY; 988e3aff4f6Saliguori else 989e3aff4f6Saliguori flags |= BDRV_O_RDWR; 990e3aff4f6Saliguori 991e3aff4f6Saliguori if (optind != argc - 1) 992e3aff4f6Saliguori return command_usage(&open_cmd); 993e3aff4f6Saliguori 994e3aff4f6Saliguori return openfile(argv[optind], flags); 995e3aff4f6Saliguori } 996e3aff4f6Saliguori 997e3aff4f6Saliguori static const cmdinfo_t open_cmd = { 998e3aff4f6Saliguori .name = "open", 999e3aff4f6Saliguori .altname = "o", 1000e3aff4f6Saliguori .cfunc = open_f, 1001e3aff4f6Saliguori .argmin = 1, 1002e3aff4f6Saliguori .argmax = -1, 1003e3aff4f6Saliguori .flags = CMD_NOFILE_OK, 1004e3aff4f6Saliguori .args = "[-Crsn] [path]", 1005e3aff4f6Saliguori .oneline = "open the file specified by path", 1006e3aff4f6Saliguori .help = open_help, 1007e3aff4f6Saliguori }; 1008e3aff4f6Saliguori 1009e3aff4f6Saliguori static int 1010e3aff4f6Saliguori init_args_command( 1011e3aff4f6Saliguori int index) 1012e3aff4f6Saliguori { 1013e3aff4f6Saliguori /* only one device allowed so far */ 1014e3aff4f6Saliguori if (index >= 1) 1015e3aff4f6Saliguori return 0; 1016e3aff4f6Saliguori return ++index; 1017e3aff4f6Saliguori } 1018e3aff4f6Saliguori 1019e3aff4f6Saliguori static int 1020e3aff4f6Saliguori init_check_command( 1021e3aff4f6Saliguori const cmdinfo_t *ct) 1022e3aff4f6Saliguori { 1023e3aff4f6Saliguori if (ct->flags & CMD_FLAG_GLOBAL) 1024e3aff4f6Saliguori return 1; 1025e3aff4f6Saliguori if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1026e3aff4f6Saliguori fprintf(stderr, "no file open, try 'help open'\n"); 1027e3aff4f6Saliguori return 0; 1028e3aff4f6Saliguori } 1029e3aff4f6Saliguori return 1; 1030e3aff4f6Saliguori } 1031e3aff4f6Saliguori 1032e3aff4f6Saliguori static void usage(const char *name) 1033e3aff4f6Saliguori { 1034e3aff4f6Saliguori printf( 1035e3aff4f6Saliguori "Usage: %s [-h] [-V] [-Crsnm] [-c cmd] ... [file]\n" 1036e3aff4f6Saliguori "QEMU Disk excerciser\n" 1037e3aff4f6Saliguori "\n" 1038e3aff4f6Saliguori " -C, --create create new file if it doesn't exist\n" 1039e3aff4f6Saliguori " -c, --cmd command to execute\n" 1040e3aff4f6Saliguori " -r, --read-only export read-only\n" 1041e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 1042e3aff4f6Saliguori " -n, --nocache disable host cache\n" 1043e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 1044e3aff4f6Saliguori " -h, --help display this help and exit\n" 1045e3aff4f6Saliguori " -V, --version output version information and exit\n" 1046e3aff4f6Saliguori "\n", 1047e3aff4f6Saliguori name); 1048e3aff4f6Saliguori } 1049e3aff4f6Saliguori 1050e3aff4f6Saliguori 1051e3aff4f6Saliguori int main(int argc, char **argv) 1052e3aff4f6Saliguori { 1053e3aff4f6Saliguori int readonly = 0; 1054e3aff4f6Saliguori const char *sopt = "hVc:Crsnm"; 1055e3aff4f6Saliguori struct option lopt[] = { 1056e3aff4f6Saliguori { "help", 0, 0, 'h' }, 1057e3aff4f6Saliguori { "version", 0, 0, 'V' }, 1058e3aff4f6Saliguori { "offset", 1, 0, 'o' }, 1059e3aff4f6Saliguori { "cmd", 1, 0, 'c' }, 1060e3aff4f6Saliguori { "create", 0, 0, 'C' }, 1061e3aff4f6Saliguori { "read-only", 0, 0, 'r' }, 1062e3aff4f6Saliguori { "snapshot", 0, 0, 's' }, 1063e3aff4f6Saliguori { "nocache", 0, 0, 'n' }, 1064e3aff4f6Saliguori { "misalign", 0, 0, 'm' }, 1065e3aff4f6Saliguori { NULL, 0, 0, 0 } 1066e3aff4f6Saliguori }; 1067e3aff4f6Saliguori int c; 1068e3aff4f6Saliguori int opt_index = 0; 1069e3aff4f6Saliguori int flags = 0; 1070e3aff4f6Saliguori 1071e3aff4f6Saliguori progname = basename(argv[0]); 1072e3aff4f6Saliguori 1073e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1074e3aff4f6Saliguori switch (c) { 1075e3aff4f6Saliguori case 's': 1076e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1077e3aff4f6Saliguori break; 1078e3aff4f6Saliguori case 'n': 1079e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 1080e3aff4f6Saliguori break; 1081e3aff4f6Saliguori case 'c': 1082e3aff4f6Saliguori add_user_command(optarg); 1083e3aff4f6Saliguori break; 1084e3aff4f6Saliguori case 'C': 1085e3aff4f6Saliguori flags |= BDRV_O_CREAT; 1086e3aff4f6Saliguori break; 1087e3aff4f6Saliguori case 'r': 1088e3aff4f6Saliguori readonly = 1; 1089e3aff4f6Saliguori break; 1090e3aff4f6Saliguori case 'm': 1091e3aff4f6Saliguori misalign = 1; 1092e3aff4f6Saliguori break; 1093e3aff4f6Saliguori case 'V': 1094e3aff4f6Saliguori printf("%s version %s\n", progname, VERSION); 1095e3aff4f6Saliguori exit(0); 1096e3aff4f6Saliguori case 'h': 1097e3aff4f6Saliguori usage(progname); 1098e3aff4f6Saliguori exit(0); 1099e3aff4f6Saliguori default: 1100e3aff4f6Saliguori usage(progname); 1101e3aff4f6Saliguori exit(1); 1102e3aff4f6Saliguori } 1103e3aff4f6Saliguori } 1104e3aff4f6Saliguori 1105e3aff4f6Saliguori if ((argc - optind) > 1) { 1106e3aff4f6Saliguori usage(progname); 1107e3aff4f6Saliguori exit(1); 1108e3aff4f6Saliguori } 1109e3aff4f6Saliguori 1110e3aff4f6Saliguori bdrv_init(); 1111e3aff4f6Saliguori 1112e3aff4f6Saliguori /* initialize commands */ 1113e3aff4f6Saliguori quit_init(); 1114e3aff4f6Saliguori help_init(); 1115e3aff4f6Saliguori add_command(&open_cmd); 1116e3aff4f6Saliguori add_command(&close_cmd); 1117e3aff4f6Saliguori add_command(&read_cmd); 1118e3aff4f6Saliguori add_command(&readv_cmd); 1119e3aff4f6Saliguori add_command(&write_cmd); 1120e3aff4f6Saliguori add_command(&writev_cmd); 1121e3aff4f6Saliguori add_command(&flush_cmd); 1122e3aff4f6Saliguori add_command(&truncate_cmd); 1123e3aff4f6Saliguori add_command(&length_cmd); 1124e3aff4f6Saliguori add_command(&info_cmd); 1125e3aff4f6Saliguori add_command(&alloc_cmd); 1126e3aff4f6Saliguori 1127e3aff4f6Saliguori add_args_command(init_args_command); 1128e3aff4f6Saliguori add_check_command(init_check_command); 1129e3aff4f6Saliguori 1130e3aff4f6Saliguori /* open the device */ 1131e3aff4f6Saliguori if (readonly) 1132e3aff4f6Saliguori flags |= BDRV_O_RDONLY; 1133e3aff4f6Saliguori else 1134e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1135e3aff4f6Saliguori 1136e3aff4f6Saliguori if ((argc - optind) == 1) 1137e3aff4f6Saliguori openfile(argv[optind], flags); 1138e3aff4f6Saliguori command_loop(); 1139e3aff4f6Saliguori 1140e3aff4f6Saliguori if (bs) 1141e3aff4f6Saliguori bdrv_close(bs); 1142e3aff4f6Saliguori return 0; 1143e3aff4f6Saliguori } 1144