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" 194e3aff4f6Saliguori " -p, -- use bdrv_pread to read the file\n" 195*c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 196e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 197e3aff4f6Saliguori " -v, -- dump buffer to standard output\n" 198e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 199e3aff4f6Saliguori "\n"); 200e3aff4f6Saliguori } 201e3aff4f6Saliguori 202e3aff4f6Saliguori static int 203e3aff4f6Saliguori read_f(int argc, char **argv) 204e3aff4f6Saliguori { 205e3aff4f6Saliguori struct timeval t1, t2; 206e3aff4f6Saliguori int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 207e3aff4f6Saliguori int c, cnt; 208e3aff4f6Saliguori char *buf; 209e3aff4f6Saliguori int64_t offset; 210e3aff4f6Saliguori int count, total; 211*c48101aeSaliguori int pattern = 0; 212*c48101aeSaliguori int Pflag = 0; 213e3aff4f6Saliguori 214*c48101aeSaliguori while ((c = getopt(argc, argv, "CpP:qv")) != EOF) { 215e3aff4f6Saliguori switch (c) { 216e3aff4f6Saliguori case 'C': 217e3aff4f6Saliguori Cflag = 1; 218e3aff4f6Saliguori break; 219e3aff4f6Saliguori case 'p': 220e3aff4f6Saliguori pflag = 1; 221e3aff4f6Saliguori break; 222*c48101aeSaliguori case 'P': 223*c48101aeSaliguori Pflag = 1; 224*c48101aeSaliguori pattern = atoi(optarg); 225*c48101aeSaliguori break; 226e3aff4f6Saliguori case 'q': 227e3aff4f6Saliguori qflag = 1; 228e3aff4f6Saliguori break; 229e3aff4f6Saliguori case 'v': 230e3aff4f6Saliguori vflag = 1; 231e3aff4f6Saliguori break; 232e3aff4f6Saliguori default: 233e3aff4f6Saliguori return command_usage(&read_cmd); 234e3aff4f6Saliguori } 235e3aff4f6Saliguori } 236e3aff4f6Saliguori 237e3aff4f6Saliguori if (optind != argc - 2) 238e3aff4f6Saliguori return command_usage(&read_cmd); 239e3aff4f6Saliguori 240e3aff4f6Saliguori offset = cvtnum(argv[optind]); 241e3aff4f6Saliguori if (offset < 0) { 242e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 243e3aff4f6Saliguori return 0; 244e3aff4f6Saliguori } 245e3aff4f6Saliguori 246e3aff4f6Saliguori optind++; 247e3aff4f6Saliguori count = cvtnum(argv[optind]); 248e3aff4f6Saliguori if (count < 0) { 249e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 250e3aff4f6Saliguori return 0; 251e3aff4f6Saliguori } 252e3aff4f6Saliguori 253e3aff4f6Saliguori if (!pflag) 254e3aff4f6Saliguori if (offset & 0x1ff) { 255e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 256e3aff4f6Saliguori (long long)offset); 257e3aff4f6Saliguori return 0; 258e3aff4f6Saliguori 259e3aff4f6Saliguori if (count & 0x1ff) { 260e3aff4f6Saliguori printf("count %d is not sector aligned\n", 261e3aff4f6Saliguori count); 262e3aff4f6Saliguori return 0; 263e3aff4f6Saliguori } 264e3aff4f6Saliguori } 265e3aff4f6Saliguori 266e3aff4f6Saliguori buf = qemu_io_alloc(count, 0xab); 267e3aff4f6Saliguori 268e3aff4f6Saliguori gettimeofday(&t1, NULL); 269e3aff4f6Saliguori if (pflag) 270e3aff4f6Saliguori cnt = do_pread(buf, offset, count, &total); 271e3aff4f6Saliguori else 272e3aff4f6Saliguori cnt = do_read(buf, offset, count, &total); 273e3aff4f6Saliguori gettimeofday(&t2, NULL); 274e3aff4f6Saliguori 275e3aff4f6Saliguori if (cnt < 0) { 276e3aff4f6Saliguori printf("read failed: %s\n", strerror(-cnt)); 277e3aff4f6Saliguori return 0; 278e3aff4f6Saliguori } 279e3aff4f6Saliguori 280*c48101aeSaliguori if (Pflag) { 281*c48101aeSaliguori void* cmp_buf = malloc(count); 282*c48101aeSaliguori memset(cmp_buf, pattern, count); 283*c48101aeSaliguori if (memcmp(buf, cmp_buf, count)) { 284*c48101aeSaliguori printf("Pattern verification failed at offset %lld, " 285*c48101aeSaliguori "%d bytes\n", 286*c48101aeSaliguori (long long) offset, count); 287*c48101aeSaliguori } 288*c48101aeSaliguori free(cmp_buf); 289*c48101aeSaliguori } 290*c48101aeSaliguori 291e3aff4f6Saliguori if (qflag) 292e3aff4f6Saliguori return 0; 293e3aff4f6Saliguori 294e3aff4f6Saliguori if (vflag) 295e3aff4f6Saliguori dump_buffer(buf, offset, count); 296e3aff4f6Saliguori 297e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 298e3aff4f6Saliguori t2 = tsub(t2, t1); 299e3aff4f6Saliguori print_report("read", &t2, offset, count, total, cnt, Cflag); 300e3aff4f6Saliguori 301e3aff4f6Saliguori qemu_io_free(buf); 302e3aff4f6Saliguori 303e3aff4f6Saliguori return 0; 304e3aff4f6Saliguori } 305e3aff4f6Saliguori 306e3aff4f6Saliguori static const cmdinfo_t read_cmd = { 307e3aff4f6Saliguori .name = "read", 308e3aff4f6Saliguori .altname = "r", 309e3aff4f6Saliguori .cfunc = read_f, 310e3aff4f6Saliguori .argmin = 2, 311e3aff4f6Saliguori .argmax = -1, 312*c48101aeSaliguori .args = "[-aCpqv] [-P pattern ] off len", 313e3aff4f6Saliguori .oneline = "reads a number of bytes at a specified offset", 314e3aff4f6Saliguori .help = read_help, 315e3aff4f6Saliguori }; 316e3aff4f6Saliguori 317e3aff4f6Saliguori static const cmdinfo_t readv_cmd; 318e3aff4f6Saliguori 319e3aff4f6Saliguori static void 320e3aff4f6Saliguori readv_help(void) 321e3aff4f6Saliguori { 322e3aff4f6Saliguori printf( 323e3aff4f6Saliguori "\n" 324e3aff4f6Saliguori " reads a range of bytes from the given offset into multiple buffers\n" 325e3aff4f6Saliguori "\n" 326e3aff4f6Saliguori " Example:\n" 327e3aff4f6Saliguori " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 328e3aff4f6Saliguori "\n" 329e3aff4f6Saliguori " Reads a segment of the currently open file, optionally dumping it to the\n" 330e3aff4f6Saliguori " standard output stream (with -v option) for subsequent inspection.\n" 331e3aff4f6Saliguori " Uses multiple iovec buffers if more than one byte range is specified.\n" 332e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 333*c48101aeSaliguori " -P, -- use a pattern to verify read data\n" 334e3aff4f6Saliguori " -v, -- dump buffer to standard output\n" 335e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 336e3aff4f6Saliguori "\n"); 337e3aff4f6Saliguori } 338e3aff4f6Saliguori 339e3aff4f6Saliguori static int 340e3aff4f6Saliguori readv_f(int argc, char **argv) 341e3aff4f6Saliguori { 342e3aff4f6Saliguori struct timeval t1, t2; 343e3aff4f6Saliguori int Cflag = 0, qflag = 0, vflag = 0; 344e3aff4f6Saliguori int c, cnt; 345e3aff4f6Saliguori char *buf, *p; 346e3aff4f6Saliguori int64_t offset; 347e3aff4f6Saliguori int count = 0, total; 348e3aff4f6Saliguori int nr_iov, i; 349e3aff4f6Saliguori QEMUIOVector qiov; 350*c48101aeSaliguori int pattern = 0; 351*c48101aeSaliguori int Pflag = 0; 352e3aff4f6Saliguori 353*c48101aeSaliguori while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 354e3aff4f6Saliguori switch (c) { 355e3aff4f6Saliguori case 'C': 356e3aff4f6Saliguori Cflag = 1; 357e3aff4f6Saliguori break; 358*c48101aeSaliguori case 'P': 359*c48101aeSaliguori Pflag = 1; 360*c48101aeSaliguori pattern = atoi(optarg); 361*c48101aeSaliguori break; 362e3aff4f6Saliguori case 'q': 363e3aff4f6Saliguori qflag = 1; 364e3aff4f6Saliguori break; 365e3aff4f6Saliguori case 'v': 366e3aff4f6Saliguori vflag = 1; 367e3aff4f6Saliguori break; 368e3aff4f6Saliguori default: 369e3aff4f6Saliguori return command_usage(&readv_cmd); 370e3aff4f6Saliguori } 371e3aff4f6Saliguori } 372e3aff4f6Saliguori 373e3aff4f6Saliguori if (optind > argc - 2) 374e3aff4f6Saliguori return command_usage(&readv_cmd); 375e3aff4f6Saliguori 376e3aff4f6Saliguori 377e3aff4f6Saliguori offset = cvtnum(argv[optind]); 378e3aff4f6Saliguori if (offset < 0) { 379e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 380e3aff4f6Saliguori return 0; 381e3aff4f6Saliguori } 382e3aff4f6Saliguori optind++; 383e3aff4f6Saliguori 384e3aff4f6Saliguori if (offset & 0x1ff) { 385e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 386e3aff4f6Saliguori (long long)offset); 387e3aff4f6Saliguori return 0; 388e3aff4f6Saliguori } 389e3aff4f6Saliguori 390e3aff4f6Saliguori if (count & 0x1ff) { 391e3aff4f6Saliguori printf("count %d is not sector aligned\n", 392e3aff4f6Saliguori count); 393e3aff4f6Saliguori return 0; 394e3aff4f6Saliguori } 395e3aff4f6Saliguori 396e3aff4f6Saliguori for (i = optind; i < argc; i++) { 397e3aff4f6Saliguori size_t len; 398e3aff4f6Saliguori 399e3aff4f6Saliguori len = cvtnum(argv[i]); 400e3aff4f6Saliguori if (len < 0) { 401e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[i]); 402e3aff4f6Saliguori return 0; 403e3aff4f6Saliguori } 404e3aff4f6Saliguori count += len; 405e3aff4f6Saliguori } 406e3aff4f6Saliguori 407e3aff4f6Saliguori nr_iov = argc - optind; 408e3aff4f6Saliguori qemu_iovec_init(&qiov, nr_iov); 409e3aff4f6Saliguori buf = p = qemu_io_alloc(count, 0xab); 410e3aff4f6Saliguori for (i = 0; i < nr_iov; i++) { 411e3aff4f6Saliguori size_t len; 412e3aff4f6Saliguori 413e3aff4f6Saliguori len = cvtnum(argv[optind]); 414e3aff4f6Saliguori if (len < 0) { 415e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", 416e3aff4f6Saliguori argv[optind]); 417e3aff4f6Saliguori return 0; 418e3aff4f6Saliguori } 419e3aff4f6Saliguori 420e3aff4f6Saliguori qemu_iovec_add(&qiov, p, len); 421e3aff4f6Saliguori p += len; 422e3aff4f6Saliguori optind++; 423e3aff4f6Saliguori } 424e3aff4f6Saliguori 425e3aff4f6Saliguori gettimeofday(&t1, NULL); 426e3aff4f6Saliguori cnt = do_aio_readv(&qiov, offset, &total); 427e3aff4f6Saliguori gettimeofday(&t2, NULL); 428e3aff4f6Saliguori 429e3aff4f6Saliguori if (cnt < 0) { 430e3aff4f6Saliguori printf("readv failed: %s\n", strerror(-cnt)); 431e3aff4f6Saliguori return 0; 432e3aff4f6Saliguori } 433e3aff4f6Saliguori 434*c48101aeSaliguori if (Pflag) { 435*c48101aeSaliguori void* cmp_buf = malloc(count); 436*c48101aeSaliguori memset(cmp_buf, pattern, count); 437*c48101aeSaliguori if (memcmp(buf, cmp_buf, count)) { 438*c48101aeSaliguori printf("Pattern verification failed at offset %lld, " 439*c48101aeSaliguori "%d bytes\n", 440*c48101aeSaliguori (long long) offset, count); 441*c48101aeSaliguori } 442*c48101aeSaliguori free(cmp_buf); 443*c48101aeSaliguori } 444*c48101aeSaliguori 445e3aff4f6Saliguori if (qflag) 446e3aff4f6Saliguori return 0; 447e3aff4f6Saliguori 448e3aff4f6Saliguori if (vflag) 449e3aff4f6Saliguori dump_buffer(buf, offset, qiov.size); 450e3aff4f6Saliguori 451e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 452e3aff4f6Saliguori t2 = tsub(t2, t1); 453e3aff4f6Saliguori print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 454e3aff4f6Saliguori 455e3aff4f6Saliguori qemu_io_free(buf); 456e3aff4f6Saliguori 457e3aff4f6Saliguori return 0; 458e3aff4f6Saliguori } 459e3aff4f6Saliguori 460e3aff4f6Saliguori static const cmdinfo_t readv_cmd = { 461e3aff4f6Saliguori .name = "readv", 462e3aff4f6Saliguori .cfunc = readv_f, 463e3aff4f6Saliguori .argmin = 2, 464e3aff4f6Saliguori .argmax = -1, 465*c48101aeSaliguori .args = "[-Cqv] [-P pattern ] off len [len..]", 466e3aff4f6Saliguori .oneline = "reads a number of bytes at a specified offset", 467e3aff4f6Saliguori .help = readv_help, 468e3aff4f6Saliguori }; 469e3aff4f6Saliguori 470e3aff4f6Saliguori static const cmdinfo_t write_cmd; 471e3aff4f6Saliguori 472e3aff4f6Saliguori static void 473e3aff4f6Saliguori write_help(void) 474e3aff4f6Saliguori { 475e3aff4f6Saliguori printf( 476e3aff4f6Saliguori "\n" 477e3aff4f6Saliguori " writes a range of bytes from the given offset\n" 478e3aff4f6Saliguori "\n" 479e3aff4f6Saliguori " Example:\n" 480e3aff4f6Saliguori " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 481e3aff4f6Saliguori "\n" 482e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 483e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 484e3aff4f6Saliguori " -p, -- use bdrv_pwrite to write the file\n" 485e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 486e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 487e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 488e3aff4f6Saliguori "\n"); 489e3aff4f6Saliguori } 490e3aff4f6Saliguori 491e3aff4f6Saliguori static int 492e3aff4f6Saliguori write_f(int argc, char **argv) 493e3aff4f6Saliguori { 494e3aff4f6Saliguori struct timeval t1, t2; 495e3aff4f6Saliguori int Cflag = 0, pflag = 0, qflag = 0; 496e3aff4f6Saliguori int c, cnt; 497e3aff4f6Saliguori char *buf; 498e3aff4f6Saliguori int64_t offset; 499e3aff4f6Saliguori int count, total; 500e3aff4f6Saliguori int pattern = 0xcd; 501e3aff4f6Saliguori 502e3aff4f6Saliguori while ((c = getopt(argc, argv, "CpP:q")) != EOF) { 503e3aff4f6Saliguori switch (c) { 504e3aff4f6Saliguori case 'C': 505e3aff4f6Saliguori Cflag = 1; 506e3aff4f6Saliguori break; 507e3aff4f6Saliguori case 'p': 508e3aff4f6Saliguori pflag = 1; 509e3aff4f6Saliguori break; 510e3aff4f6Saliguori case 'P': 511e3aff4f6Saliguori pattern = atoi(optarg); 512e3aff4f6Saliguori break; 513e3aff4f6Saliguori case 'q': 514e3aff4f6Saliguori qflag = 1; 515e3aff4f6Saliguori break; 516e3aff4f6Saliguori default: 517e3aff4f6Saliguori return command_usage(&write_cmd); 518e3aff4f6Saliguori } 519e3aff4f6Saliguori } 520e3aff4f6Saliguori 521e3aff4f6Saliguori if (optind != argc - 2) 522e3aff4f6Saliguori return command_usage(&write_cmd); 523e3aff4f6Saliguori 524e3aff4f6Saliguori offset = cvtnum(argv[optind]); 525e3aff4f6Saliguori if (offset < 0) { 526e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 527e3aff4f6Saliguori return 0; 528e3aff4f6Saliguori } 529e3aff4f6Saliguori 530e3aff4f6Saliguori optind++; 531e3aff4f6Saliguori count = cvtnum(argv[optind]); 532e3aff4f6Saliguori if (count < 0) { 533e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 534e3aff4f6Saliguori return 0; 535e3aff4f6Saliguori } 536e3aff4f6Saliguori 537e3aff4f6Saliguori if (!pflag) { 538e3aff4f6Saliguori if (offset & 0x1ff) { 539e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 540e3aff4f6Saliguori (long long)offset); 541e3aff4f6Saliguori return 0; 542e3aff4f6Saliguori } 543e3aff4f6Saliguori 544e3aff4f6Saliguori if (count & 0x1ff) { 545e3aff4f6Saliguori printf("count %d is not sector aligned\n", 546e3aff4f6Saliguori count); 547e3aff4f6Saliguori return 0; 548e3aff4f6Saliguori } 549e3aff4f6Saliguori } 550e3aff4f6Saliguori 551e3aff4f6Saliguori buf = qemu_io_alloc(count, pattern); 552e3aff4f6Saliguori 553e3aff4f6Saliguori gettimeofday(&t1, NULL); 554e3aff4f6Saliguori if (pflag) 555e3aff4f6Saliguori cnt = do_pwrite(buf, offset, count, &total); 556e3aff4f6Saliguori else 557e3aff4f6Saliguori cnt = do_write(buf, offset, count, &total); 558e3aff4f6Saliguori gettimeofday(&t2, NULL); 559e3aff4f6Saliguori 560e3aff4f6Saliguori if (cnt < 0) { 561e3aff4f6Saliguori printf("write failed: %s\n", strerror(-cnt)); 562e3aff4f6Saliguori return 0; 563e3aff4f6Saliguori } 564e3aff4f6Saliguori 565e3aff4f6Saliguori if (qflag) 566e3aff4f6Saliguori return 0; 567e3aff4f6Saliguori 568e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 569e3aff4f6Saliguori t2 = tsub(t2, t1); 570e3aff4f6Saliguori print_report("wrote", &t2, offset, count, total, cnt, Cflag); 571e3aff4f6Saliguori 572e3aff4f6Saliguori qemu_io_free(buf); 573e3aff4f6Saliguori 574e3aff4f6Saliguori return 0; 575e3aff4f6Saliguori } 576e3aff4f6Saliguori 577e3aff4f6Saliguori static const cmdinfo_t write_cmd = { 578e3aff4f6Saliguori .name = "write", 579e3aff4f6Saliguori .altname = "w", 580e3aff4f6Saliguori .cfunc = write_f, 581e3aff4f6Saliguori .argmin = 2, 582e3aff4f6Saliguori .argmax = -1, 583e3aff4f6Saliguori .args = "[-aCpq] [-P pattern ] off len", 584e3aff4f6Saliguori .oneline = "writes a number of bytes at a specified offset", 585e3aff4f6Saliguori .help = write_help, 586e3aff4f6Saliguori }; 587e3aff4f6Saliguori 588e3aff4f6Saliguori static const cmdinfo_t writev_cmd; 589e3aff4f6Saliguori 590e3aff4f6Saliguori static void 591e3aff4f6Saliguori writev_help(void) 592e3aff4f6Saliguori { 593e3aff4f6Saliguori printf( 594e3aff4f6Saliguori "\n" 595e3aff4f6Saliguori " writes a range of bytes from the given offset source from multiple buffers\n" 596e3aff4f6Saliguori "\n" 597e3aff4f6Saliguori " Example:\n" 598e3aff4f6Saliguori " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 599e3aff4f6Saliguori "\n" 600e3aff4f6Saliguori " Writes into a segment of the currently open file, using a buffer\n" 601e3aff4f6Saliguori " filled with a set pattern (0xcdcdcdcd).\n" 602e3aff4f6Saliguori " -P, -- use different pattern to fill file\n" 603e3aff4f6Saliguori " -C, -- report statistics in a machine parsable format\n" 604e3aff4f6Saliguori " -q, -- quite mode, do not show I/O statistics\n" 605e3aff4f6Saliguori "\n"); 606e3aff4f6Saliguori } 607e3aff4f6Saliguori 608e3aff4f6Saliguori static int 609e3aff4f6Saliguori writev_f(int argc, char **argv) 610e3aff4f6Saliguori { 611e3aff4f6Saliguori struct timeval t1, t2; 612e3aff4f6Saliguori int Cflag = 0, qflag = 0; 613e3aff4f6Saliguori int c, cnt; 614e3aff4f6Saliguori char *buf, *p; 615e3aff4f6Saliguori int64_t offset; 616e3aff4f6Saliguori int count = 0, total; 617e3aff4f6Saliguori int nr_iov, i; 618e3aff4f6Saliguori int pattern = 0xcd; 619e3aff4f6Saliguori QEMUIOVector qiov; 620e3aff4f6Saliguori 621e3aff4f6Saliguori while ((c = getopt(argc, argv, "CqP:")) != EOF) { 622e3aff4f6Saliguori switch (c) { 623e3aff4f6Saliguori case 'C': 624e3aff4f6Saliguori Cflag = 1; 625e3aff4f6Saliguori break; 626e3aff4f6Saliguori case 'q': 627e3aff4f6Saliguori qflag = 1; 628e3aff4f6Saliguori break; 629e3aff4f6Saliguori case 'P': 630e3aff4f6Saliguori pattern = atoi(optarg); 631e3aff4f6Saliguori break; 632e3aff4f6Saliguori default: 633e3aff4f6Saliguori return command_usage(&writev_cmd); 634e3aff4f6Saliguori } 635e3aff4f6Saliguori } 636e3aff4f6Saliguori 637e3aff4f6Saliguori if (optind > argc - 2) 638e3aff4f6Saliguori return command_usage(&writev_cmd); 639e3aff4f6Saliguori 640e3aff4f6Saliguori offset = cvtnum(argv[optind]); 641e3aff4f6Saliguori if (offset < 0) { 642e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[optind]); 643e3aff4f6Saliguori return 0; 644e3aff4f6Saliguori } 645e3aff4f6Saliguori optind++; 646e3aff4f6Saliguori 647e3aff4f6Saliguori if (offset & 0x1ff) { 648e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 649e3aff4f6Saliguori (long long)offset); 650e3aff4f6Saliguori return 0; 651e3aff4f6Saliguori } 652e3aff4f6Saliguori 653e3aff4f6Saliguori if (count & 0x1ff) { 654e3aff4f6Saliguori printf("count %d is not sector aligned\n", 655e3aff4f6Saliguori count); 656e3aff4f6Saliguori return 0; 657e3aff4f6Saliguori } 658e3aff4f6Saliguori 659e3aff4f6Saliguori 660e3aff4f6Saliguori for (i = optind; i < argc; i++) { 661e3aff4f6Saliguori size_t len; 662e3aff4f6Saliguori 663e3aff4f6Saliguori len = cvtnum(argv[optind]); 664e3aff4f6Saliguori if (len < 0) { 665e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", argv[i]); 666e3aff4f6Saliguori return 0; 667e3aff4f6Saliguori } 668e3aff4f6Saliguori count += len; 669e3aff4f6Saliguori } 670e3aff4f6Saliguori 671e3aff4f6Saliguori nr_iov = argc - optind; 672e3aff4f6Saliguori qemu_iovec_init(&qiov, nr_iov); 6737e9bbc9fSaliguori buf = p = qemu_io_alloc(count, pattern); 674e3aff4f6Saliguori for (i = 0; i < nr_iov; i++) { 675e3aff4f6Saliguori size_t len; 676e3aff4f6Saliguori 677e3aff4f6Saliguori len = cvtnum(argv[optind]); 678e3aff4f6Saliguori if (len < 0) { 679e3aff4f6Saliguori printf("non-numeric length argument -- %s\n", 680e3aff4f6Saliguori argv[optind]); 681e3aff4f6Saliguori return 0; 682e3aff4f6Saliguori } 683e3aff4f6Saliguori 684e3aff4f6Saliguori qemu_iovec_add(&qiov, p, len); 685e3aff4f6Saliguori p += len; 686e3aff4f6Saliguori optind++; 687e3aff4f6Saliguori } 688e3aff4f6Saliguori 689e3aff4f6Saliguori gettimeofday(&t1, NULL); 690e3aff4f6Saliguori cnt = do_aio_writev(&qiov, offset, &total); 691e3aff4f6Saliguori gettimeofday(&t2, NULL); 692e3aff4f6Saliguori 693e3aff4f6Saliguori if (cnt < 0) { 694e3aff4f6Saliguori printf("writev failed: %s\n", strerror(-cnt)); 695e3aff4f6Saliguori return 0; 696e3aff4f6Saliguori } 697e3aff4f6Saliguori 698e3aff4f6Saliguori if (qflag) 699e3aff4f6Saliguori return 0; 700e3aff4f6Saliguori 701e3aff4f6Saliguori /* Finally, report back -- -C gives a parsable format */ 702e3aff4f6Saliguori t2 = tsub(t2, t1); 703e3aff4f6Saliguori print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 704e3aff4f6Saliguori 705e3aff4f6Saliguori qemu_io_free(buf); 706e3aff4f6Saliguori 707e3aff4f6Saliguori return 0; 708e3aff4f6Saliguori } 709e3aff4f6Saliguori 710e3aff4f6Saliguori static const cmdinfo_t writev_cmd = { 711e3aff4f6Saliguori .name = "writev", 712e3aff4f6Saliguori .cfunc = writev_f, 713e3aff4f6Saliguori .argmin = 2, 714e3aff4f6Saliguori .argmax = -1, 715e3aff4f6Saliguori .args = "[-Cq] [-P pattern ] off len [len..]", 716e3aff4f6Saliguori .oneline = "writes a number of bytes at a specified offset", 717e3aff4f6Saliguori .help = writev_help, 718e3aff4f6Saliguori }; 719e3aff4f6Saliguori 720e3aff4f6Saliguori static int 721e3aff4f6Saliguori flush_f(int argc, char **argv) 722e3aff4f6Saliguori { 723e3aff4f6Saliguori bdrv_flush(bs); 724e3aff4f6Saliguori return 0; 725e3aff4f6Saliguori } 726e3aff4f6Saliguori 727e3aff4f6Saliguori static const cmdinfo_t flush_cmd = { 728e3aff4f6Saliguori .name = "flush", 729e3aff4f6Saliguori .altname = "f", 730e3aff4f6Saliguori .cfunc = flush_f, 731e3aff4f6Saliguori .oneline = "flush all in-core file state to disk", 732e3aff4f6Saliguori }; 733e3aff4f6Saliguori 734e3aff4f6Saliguori static int 735e3aff4f6Saliguori truncate_f(int argc, char **argv) 736e3aff4f6Saliguori { 737e3aff4f6Saliguori int64_t offset; 738e3aff4f6Saliguori int ret; 739e3aff4f6Saliguori 740e3aff4f6Saliguori offset = cvtnum(argv[1]); 741e3aff4f6Saliguori if (offset < 0) { 742e3aff4f6Saliguori printf("non-numeric truncate argument -- %s\n", argv[1]); 743e3aff4f6Saliguori return 0; 744e3aff4f6Saliguori } 745e3aff4f6Saliguori 746e3aff4f6Saliguori ret = bdrv_truncate(bs, offset); 747e3aff4f6Saliguori if (ret < 0) { 748e3aff4f6Saliguori printf("truncate: %s", strerror(ret)); 749e3aff4f6Saliguori return 0; 750e3aff4f6Saliguori } 751e3aff4f6Saliguori 752e3aff4f6Saliguori return 0; 753e3aff4f6Saliguori } 754e3aff4f6Saliguori 755e3aff4f6Saliguori static const cmdinfo_t truncate_cmd = { 756e3aff4f6Saliguori .name = "truncate", 757e3aff4f6Saliguori .altname = "t", 758e3aff4f6Saliguori .cfunc = truncate_f, 759e3aff4f6Saliguori .argmin = 1, 760e3aff4f6Saliguori .argmax = 1, 761e3aff4f6Saliguori .args = "off", 762e3aff4f6Saliguori .oneline = "truncates the current file at the given offset", 763e3aff4f6Saliguori }; 764e3aff4f6Saliguori 765e3aff4f6Saliguori static int 766e3aff4f6Saliguori length_f(int argc, char **argv) 767e3aff4f6Saliguori { 768e3aff4f6Saliguori int64_t size; 769e3aff4f6Saliguori char s1[64]; 770e3aff4f6Saliguori 771e3aff4f6Saliguori size = bdrv_getlength(bs); 772e3aff4f6Saliguori if (size < 0) { 773e3aff4f6Saliguori printf("getlength: %s", strerror(size)); 774e3aff4f6Saliguori return 0; 775e3aff4f6Saliguori } 776e3aff4f6Saliguori 777e3aff4f6Saliguori cvtstr(size, s1, sizeof(s1)); 778e3aff4f6Saliguori printf("%s\n", s1); 779e3aff4f6Saliguori return 0; 780e3aff4f6Saliguori } 781e3aff4f6Saliguori 782e3aff4f6Saliguori 783e3aff4f6Saliguori static const cmdinfo_t length_cmd = { 784e3aff4f6Saliguori .name = "length", 785e3aff4f6Saliguori .altname = "l", 786e3aff4f6Saliguori .cfunc = length_f, 787e3aff4f6Saliguori .oneline = "gets the length of the current file", 788e3aff4f6Saliguori }; 789e3aff4f6Saliguori 790e3aff4f6Saliguori 791e3aff4f6Saliguori static int 792e3aff4f6Saliguori info_f(int argc, char **argv) 793e3aff4f6Saliguori { 794e3aff4f6Saliguori BlockDriverInfo bdi; 795e3aff4f6Saliguori char s1[64], s2[64]; 796e3aff4f6Saliguori int ret; 797e3aff4f6Saliguori 798e3aff4f6Saliguori if (bs->drv && bs->drv->format_name) 799e3aff4f6Saliguori printf("format name: %s\n", bs->drv->format_name); 800e3aff4f6Saliguori if (bs->drv && bs->drv->protocol_name) 801e3aff4f6Saliguori printf("format name: %s\n", bs->drv->protocol_name); 802e3aff4f6Saliguori 803e3aff4f6Saliguori ret = bdrv_get_info(bs, &bdi); 804e3aff4f6Saliguori if (ret) 805e3aff4f6Saliguori return 0; 806e3aff4f6Saliguori 807e3aff4f6Saliguori cvtstr(bdi.cluster_size, s1, sizeof(s1)); 808e3aff4f6Saliguori cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 809e3aff4f6Saliguori 810e3aff4f6Saliguori printf("cluster size: %s\n", s1); 811e3aff4f6Saliguori printf("vm state offset: %s\n", s2); 812e3aff4f6Saliguori 813e3aff4f6Saliguori return 0; 814e3aff4f6Saliguori } 815e3aff4f6Saliguori 816e3aff4f6Saliguori 817e3aff4f6Saliguori 818e3aff4f6Saliguori static const cmdinfo_t info_cmd = { 819e3aff4f6Saliguori .name = "info", 820e3aff4f6Saliguori .altname = "i", 821e3aff4f6Saliguori .cfunc = info_f, 822e3aff4f6Saliguori .oneline = "prints information about the current file", 823e3aff4f6Saliguori }; 824e3aff4f6Saliguori 825e3aff4f6Saliguori static int 826e3aff4f6Saliguori alloc_f(int argc, char **argv) 827e3aff4f6Saliguori { 828e3aff4f6Saliguori int64_t offset; 829e3aff4f6Saliguori int nb_sectors; 830e3aff4f6Saliguori char s1[64]; 831e3aff4f6Saliguori int num; 832e3aff4f6Saliguori int ret; 833838ab728Saliguori const char *retstr; 834e3aff4f6Saliguori 835e3aff4f6Saliguori offset = cvtnum(argv[1]); 836e3aff4f6Saliguori if (offset & 0x1ff) { 837e3aff4f6Saliguori printf("offset %lld is not sector aligned\n", 838e3aff4f6Saliguori (long long)offset); 839e3aff4f6Saliguori return 0; 840e3aff4f6Saliguori } 841e3aff4f6Saliguori 842e3aff4f6Saliguori if (argc == 3) 843e3aff4f6Saliguori nb_sectors = cvtnum(argv[2]); 844e3aff4f6Saliguori else 845e3aff4f6Saliguori nb_sectors = 1; 846e3aff4f6Saliguori 847e3aff4f6Saliguori ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num); 848e3aff4f6Saliguori 849e3aff4f6Saliguori cvtstr(offset, s1, sizeof(s1)); 850e3aff4f6Saliguori 851838ab728Saliguori retstr = ret ? "allocated" : "not allocated"; 852e3aff4f6Saliguori if (nb_sectors == 1) 853838ab728Saliguori printf("sector %s at offset %s\n", retstr, s1); 854e3aff4f6Saliguori else 855838ab728Saliguori printf("%d/%d sectors %s at offset %s\n", 856838ab728Saliguori num, nb_sectors, retstr, s1); 857e3aff4f6Saliguori return 0; 858e3aff4f6Saliguori } 859e3aff4f6Saliguori 860e3aff4f6Saliguori static const cmdinfo_t alloc_cmd = { 861e3aff4f6Saliguori .name = "alloc", 862e3aff4f6Saliguori .altname = "a", 863e3aff4f6Saliguori .argmin = 1, 864e3aff4f6Saliguori .argmax = 2, 865e3aff4f6Saliguori .cfunc = alloc_f, 866e3aff4f6Saliguori .args = "off [sectors]", 867e3aff4f6Saliguori .oneline = "checks if a sector is present in the file", 868e3aff4f6Saliguori }; 869e3aff4f6Saliguori 870e3aff4f6Saliguori static int 871e3aff4f6Saliguori close_f(int argc, char **argv) 872e3aff4f6Saliguori { 873e3aff4f6Saliguori bdrv_close(bs); 874e3aff4f6Saliguori bs = NULL; 875e3aff4f6Saliguori return 0; 876e3aff4f6Saliguori } 877e3aff4f6Saliguori 878e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 879e3aff4f6Saliguori .name = "close", 880e3aff4f6Saliguori .altname = "c", 881e3aff4f6Saliguori .cfunc = close_f, 882e3aff4f6Saliguori .oneline = "close the current open file", 883e3aff4f6Saliguori }; 884e3aff4f6Saliguori 885e3aff4f6Saliguori static int openfile(char *name, int flags) 886e3aff4f6Saliguori { 887e3aff4f6Saliguori if (bs) { 888e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 889e3aff4f6Saliguori return 1; 890e3aff4f6Saliguori } 891e3aff4f6Saliguori 892e3aff4f6Saliguori bs = bdrv_new("hda"); 893e3aff4f6Saliguori if (!bs) 894e3aff4f6Saliguori return 1; 895e3aff4f6Saliguori 896e3aff4f6Saliguori if (bdrv_open(bs, name, flags) == -1) { 897e3aff4f6Saliguori fprintf(stderr, "%s: can't open device %s\n", progname, name); 898e3aff4f6Saliguori bs = NULL; 899e3aff4f6Saliguori return 1; 900e3aff4f6Saliguori } 901e3aff4f6Saliguori 902e3aff4f6Saliguori return 0; 903e3aff4f6Saliguori } 904e3aff4f6Saliguori 905e3aff4f6Saliguori static void 906e3aff4f6Saliguori open_help(void) 907e3aff4f6Saliguori { 908e3aff4f6Saliguori printf( 909e3aff4f6Saliguori "\n" 910e3aff4f6Saliguori " opens a new file in the requested mode\n" 911e3aff4f6Saliguori "\n" 912e3aff4f6Saliguori " Example:\n" 913e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 914e3aff4f6Saliguori "\n" 915e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 916e3aff4f6Saliguori " -C, -- create new file if it doesn't exist\n" 917e3aff4f6Saliguori " -r, -- open file read-only\n" 918e3aff4f6Saliguori " -s, -- use snapshot file\n" 919e3aff4f6Saliguori " -n, -- disable host cache\n" 920e3aff4f6Saliguori "\n"); 921e3aff4f6Saliguori } 922e3aff4f6Saliguori 923e3aff4f6Saliguori static const cmdinfo_t open_cmd; 924e3aff4f6Saliguori 925e3aff4f6Saliguori static int 926e3aff4f6Saliguori open_f(int argc, char **argv) 927e3aff4f6Saliguori { 928e3aff4f6Saliguori int flags = 0; 929e3aff4f6Saliguori int readonly = 0; 930e3aff4f6Saliguori int c; 931e3aff4f6Saliguori 932e3aff4f6Saliguori while ((c = getopt(argc, argv, "snCr")) != EOF) { 933e3aff4f6Saliguori switch (c) { 934e3aff4f6Saliguori case 's': 935e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 936e3aff4f6Saliguori break; 937e3aff4f6Saliguori case 'n': 938e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 939e3aff4f6Saliguori break; 940e3aff4f6Saliguori case 'C': 941e3aff4f6Saliguori flags |= BDRV_O_CREAT; 942e3aff4f6Saliguori break; 943e3aff4f6Saliguori case 'r': 944e3aff4f6Saliguori readonly = 1; 945e3aff4f6Saliguori break; 946e3aff4f6Saliguori default: 947e3aff4f6Saliguori return command_usage(&open_cmd); 948e3aff4f6Saliguori } 949e3aff4f6Saliguori } 950e3aff4f6Saliguori 951e3aff4f6Saliguori if (readonly) 952e3aff4f6Saliguori flags |= BDRV_O_RDONLY; 953e3aff4f6Saliguori else 954e3aff4f6Saliguori flags |= BDRV_O_RDWR; 955e3aff4f6Saliguori 956e3aff4f6Saliguori if (optind != argc - 1) 957e3aff4f6Saliguori return command_usage(&open_cmd); 958e3aff4f6Saliguori 959e3aff4f6Saliguori return openfile(argv[optind], flags); 960e3aff4f6Saliguori } 961e3aff4f6Saliguori 962e3aff4f6Saliguori static const cmdinfo_t open_cmd = { 963e3aff4f6Saliguori .name = "open", 964e3aff4f6Saliguori .altname = "o", 965e3aff4f6Saliguori .cfunc = open_f, 966e3aff4f6Saliguori .argmin = 1, 967e3aff4f6Saliguori .argmax = -1, 968e3aff4f6Saliguori .flags = CMD_NOFILE_OK, 969e3aff4f6Saliguori .args = "[-Crsn] [path]", 970e3aff4f6Saliguori .oneline = "open the file specified by path", 971e3aff4f6Saliguori .help = open_help, 972e3aff4f6Saliguori }; 973e3aff4f6Saliguori 974e3aff4f6Saliguori static int 975e3aff4f6Saliguori init_args_command( 976e3aff4f6Saliguori int index) 977e3aff4f6Saliguori { 978e3aff4f6Saliguori /* only one device allowed so far */ 979e3aff4f6Saliguori if (index >= 1) 980e3aff4f6Saliguori return 0; 981e3aff4f6Saliguori return ++index; 982e3aff4f6Saliguori } 983e3aff4f6Saliguori 984e3aff4f6Saliguori static int 985e3aff4f6Saliguori init_check_command( 986e3aff4f6Saliguori const cmdinfo_t *ct) 987e3aff4f6Saliguori { 988e3aff4f6Saliguori if (ct->flags & CMD_FLAG_GLOBAL) 989e3aff4f6Saliguori return 1; 990e3aff4f6Saliguori if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 991e3aff4f6Saliguori fprintf(stderr, "no file open, try 'help open'\n"); 992e3aff4f6Saliguori return 0; 993e3aff4f6Saliguori } 994e3aff4f6Saliguori return 1; 995e3aff4f6Saliguori } 996e3aff4f6Saliguori 997e3aff4f6Saliguori static void usage(const char *name) 998e3aff4f6Saliguori { 999e3aff4f6Saliguori printf( 1000e3aff4f6Saliguori "Usage: %s [-h] [-V] [-Crsnm] [-c cmd] ... [file]\n" 1001e3aff4f6Saliguori "QEMU Disk excerciser\n" 1002e3aff4f6Saliguori "\n" 1003e3aff4f6Saliguori " -C, --create create new file if it doesn't exist\n" 1004e3aff4f6Saliguori " -c, --cmd command to execute\n" 1005e3aff4f6Saliguori " -r, --read-only export read-only\n" 1006e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 1007e3aff4f6Saliguori " -n, --nocache disable host cache\n" 1008e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 1009e3aff4f6Saliguori " -h, --help display this help and exit\n" 1010e3aff4f6Saliguori " -V, --version output version information and exit\n" 1011e3aff4f6Saliguori "\n", 1012e3aff4f6Saliguori name); 1013e3aff4f6Saliguori } 1014e3aff4f6Saliguori 1015e3aff4f6Saliguori 1016e3aff4f6Saliguori int main(int argc, char **argv) 1017e3aff4f6Saliguori { 1018e3aff4f6Saliguori int readonly = 0; 1019e3aff4f6Saliguori const char *sopt = "hVc:Crsnm"; 1020e3aff4f6Saliguori struct option lopt[] = { 1021e3aff4f6Saliguori { "help", 0, 0, 'h' }, 1022e3aff4f6Saliguori { "version", 0, 0, 'V' }, 1023e3aff4f6Saliguori { "offset", 1, 0, 'o' }, 1024e3aff4f6Saliguori { "cmd", 1, 0, 'c' }, 1025e3aff4f6Saliguori { "create", 0, 0, 'C' }, 1026e3aff4f6Saliguori { "read-only", 0, 0, 'r' }, 1027e3aff4f6Saliguori { "snapshot", 0, 0, 's' }, 1028e3aff4f6Saliguori { "nocache", 0, 0, 'n' }, 1029e3aff4f6Saliguori { "misalign", 0, 0, 'm' }, 1030e3aff4f6Saliguori { NULL, 0, 0, 0 } 1031e3aff4f6Saliguori }; 1032e3aff4f6Saliguori int c; 1033e3aff4f6Saliguori int opt_index = 0; 1034e3aff4f6Saliguori int flags = 0; 1035e3aff4f6Saliguori 1036e3aff4f6Saliguori progname = basename(argv[0]); 1037e3aff4f6Saliguori 1038e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 1039e3aff4f6Saliguori switch (c) { 1040e3aff4f6Saliguori case 's': 1041e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 1042e3aff4f6Saliguori break; 1043e3aff4f6Saliguori case 'n': 1044e3aff4f6Saliguori flags |= BDRV_O_NOCACHE; 1045e3aff4f6Saliguori break; 1046e3aff4f6Saliguori case 'c': 1047e3aff4f6Saliguori add_user_command(optarg); 1048e3aff4f6Saliguori break; 1049e3aff4f6Saliguori case 'C': 1050e3aff4f6Saliguori flags |= BDRV_O_CREAT; 1051e3aff4f6Saliguori break; 1052e3aff4f6Saliguori case 'r': 1053e3aff4f6Saliguori readonly = 1; 1054e3aff4f6Saliguori break; 1055e3aff4f6Saliguori case 'm': 1056e3aff4f6Saliguori misalign = 1; 1057e3aff4f6Saliguori break; 1058e3aff4f6Saliguori case 'V': 1059e3aff4f6Saliguori printf("%s version %s\n", progname, VERSION); 1060e3aff4f6Saliguori exit(0); 1061e3aff4f6Saliguori case 'h': 1062e3aff4f6Saliguori usage(progname); 1063e3aff4f6Saliguori exit(0); 1064e3aff4f6Saliguori default: 1065e3aff4f6Saliguori usage(progname); 1066e3aff4f6Saliguori exit(1); 1067e3aff4f6Saliguori } 1068e3aff4f6Saliguori } 1069e3aff4f6Saliguori 1070e3aff4f6Saliguori if ((argc - optind) > 1) { 1071e3aff4f6Saliguori usage(progname); 1072e3aff4f6Saliguori exit(1); 1073e3aff4f6Saliguori } 1074e3aff4f6Saliguori 1075e3aff4f6Saliguori bdrv_init(); 1076e3aff4f6Saliguori 1077e3aff4f6Saliguori /* initialize commands */ 1078e3aff4f6Saliguori quit_init(); 1079e3aff4f6Saliguori help_init(); 1080e3aff4f6Saliguori add_command(&open_cmd); 1081e3aff4f6Saliguori add_command(&close_cmd); 1082e3aff4f6Saliguori add_command(&read_cmd); 1083e3aff4f6Saliguori add_command(&readv_cmd); 1084e3aff4f6Saliguori add_command(&write_cmd); 1085e3aff4f6Saliguori add_command(&writev_cmd); 1086e3aff4f6Saliguori add_command(&flush_cmd); 1087e3aff4f6Saliguori add_command(&truncate_cmd); 1088e3aff4f6Saliguori add_command(&length_cmd); 1089e3aff4f6Saliguori add_command(&info_cmd); 1090e3aff4f6Saliguori add_command(&alloc_cmd); 1091e3aff4f6Saliguori 1092e3aff4f6Saliguori add_args_command(init_args_command); 1093e3aff4f6Saliguori add_check_command(init_check_command); 1094e3aff4f6Saliguori 1095e3aff4f6Saliguori /* open the device */ 1096e3aff4f6Saliguori if (readonly) 1097e3aff4f6Saliguori flags |= BDRV_O_RDONLY; 1098e3aff4f6Saliguori else 1099e3aff4f6Saliguori flags |= BDRV_O_RDWR; 1100e3aff4f6Saliguori 1101e3aff4f6Saliguori if ((argc - optind) == 1) 1102e3aff4f6Saliguori openfile(argv[optind], flags); 1103e3aff4f6Saliguori command_loop(); 1104e3aff4f6Saliguori 1105e3aff4f6Saliguori if (bs) 1106e3aff4f6Saliguori bdrv_close(bs); 1107e3aff4f6Saliguori return 0; 1108e3aff4f6Saliguori } 1109