1*797ac58cSKevin Wolf /* 2*797ac58cSKevin Wolf * Command line utility to exercise the QEMU I/O path. 3*797ac58cSKevin Wolf * 4*797ac58cSKevin Wolf * Copyright (C) 2009 Red Hat, Inc. 5*797ac58cSKevin Wolf * Copyright (c) 2003-2005 Silicon Graphics, Inc. 6*797ac58cSKevin Wolf * 7*797ac58cSKevin Wolf * This work is licensed under the terms of the GNU GPL, version 2 or later. 8*797ac58cSKevin Wolf * See the COPYING file in the top-level directory. 9*797ac58cSKevin Wolf */ 10*797ac58cSKevin Wolf 11*797ac58cSKevin Wolf #include "qemu-common.h" 12*797ac58cSKevin Wolf #include "block/block_int.h" 13*797ac58cSKevin Wolf #include "cmd.h" 14*797ac58cSKevin Wolf 15*797ac58cSKevin Wolf #define CMD_NOFILE_OK 0x01 16*797ac58cSKevin Wolf 17*797ac58cSKevin Wolf int qemuio_misalign; 18*797ac58cSKevin Wolf 19*797ac58cSKevin Wolf static int64_t cvtnum(const char *s) 20*797ac58cSKevin Wolf { 21*797ac58cSKevin Wolf char *end; 22*797ac58cSKevin Wolf return strtosz_suffix(s, &end, STRTOSZ_DEFSUFFIX_B); 23*797ac58cSKevin Wolf } 24*797ac58cSKevin Wolf 25*797ac58cSKevin Wolf /* 26*797ac58cSKevin Wolf * Parse the pattern argument to various sub-commands. 27*797ac58cSKevin Wolf * 28*797ac58cSKevin Wolf * Because the pattern is used as an argument to memset it must evaluate 29*797ac58cSKevin Wolf * to an unsigned integer that fits into a single byte. 30*797ac58cSKevin Wolf */ 31*797ac58cSKevin Wolf static int parse_pattern(const char *arg) 32*797ac58cSKevin Wolf { 33*797ac58cSKevin Wolf char *endptr = NULL; 34*797ac58cSKevin Wolf long pattern; 35*797ac58cSKevin Wolf 36*797ac58cSKevin Wolf pattern = strtol(arg, &endptr, 0); 37*797ac58cSKevin Wolf if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') { 38*797ac58cSKevin Wolf printf("%s is not a valid pattern byte\n", arg); 39*797ac58cSKevin Wolf return -1; 40*797ac58cSKevin Wolf } 41*797ac58cSKevin Wolf 42*797ac58cSKevin Wolf return pattern; 43*797ac58cSKevin Wolf } 44*797ac58cSKevin Wolf 45*797ac58cSKevin Wolf /* 46*797ac58cSKevin Wolf * Memory allocation helpers. 47*797ac58cSKevin Wolf * 48*797ac58cSKevin Wolf * Make sure memory is aligned by default, or purposefully misaligned if 49*797ac58cSKevin Wolf * that is specified on the command line. 50*797ac58cSKevin Wolf */ 51*797ac58cSKevin Wolf 52*797ac58cSKevin Wolf #define MISALIGN_OFFSET 16 53*797ac58cSKevin Wolf static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern) 54*797ac58cSKevin Wolf { 55*797ac58cSKevin Wolf void *buf; 56*797ac58cSKevin Wolf 57*797ac58cSKevin Wolf if (qemuio_misalign) { 58*797ac58cSKevin Wolf len += MISALIGN_OFFSET; 59*797ac58cSKevin Wolf } 60*797ac58cSKevin Wolf buf = qemu_blockalign(bs, len); 61*797ac58cSKevin Wolf memset(buf, pattern, len); 62*797ac58cSKevin Wolf if (qemuio_misalign) { 63*797ac58cSKevin Wolf buf += MISALIGN_OFFSET; 64*797ac58cSKevin Wolf } 65*797ac58cSKevin Wolf return buf; 66*797ac58cSKevin Wolf } 67*797ac58cSKevin Wolf 68*797ac58cSKevin Wolf static void qemu_io_free(void *p) 69*797ac58cSKevin Wolf { 70*797ac58cSKevin Wolf if (qemuio_misalign) { 71*797ac58cSKevin Wolf p -= MISALIGN_OFFSET; 72*797ac58cSKevin Wolf } 73*797ac58cSKevin Wolf qemu_vfree(p); 74*797ac58cSKevin Wolf } 75*797ac58cSKevin Wolf 76*797ac58cSKevin Wolf static void dump_buffer(const void *buffer, int64_t offset, int len) 77*797ac58cSKevin Wolf { 78*797ac58cSKevin Wolf int i, j; 79*797ac58cSKevin Wolf const uint8_t *p; 80*797ac58cSKevin Wolf 81*797ac58cSKevin Wolf for (i = 0, p = buffer; i < len; i += 16) { 82*797ac58cSKevin Wolf const uint8_t *s = p; 83*797ac58cSKevin Wolf 84*797ac58cSKevin Wolf printf("%08" PRIx64 ": ", offset + i); 85*797ac58cSKevin Wolf for (j = 0; j < 16 && i + j < len; j++, p++) { 86*797ac58cSKevin Wolf printf("%02x ", *p); 87*797ac58cSKevin Wolf } 88*797ac58cSKevin Wolf printf(" "); 89*797ac58cSKevin Wolf for (j = 0; j < 16 && i + j < len; j++, s++) { 90*797ac58cSKevin Wolf if (isalnum(*s)) { 91*797ac58cSKevin Wolf printf("%c", *s); 92*797ac58cSKevin Wolf } else { 93*797ac58cSKevin Wolf printf("."); 94*797ac58cSKevin Wolf } 95*797ac58cSKevin Wolf } 96*797ac58cSKevin Wolf printf("\n"); 97*797ac58cSKevin Wolf } 98*797ac58cSKevin Wolf } 99*797ac58cSKevin Wolf 100*797ac58cSKevin Wolf static void print_report(const char *op, struct timeval *t, int64_t offset, 101*797ac58cSKevin Wolf int count, int total, int cnt, int Cflag) 102*797ac58cSKevin Wolf { 103*797ac58cSKevin Wolf char s1[64], s2[64], ts[64]; 104*797ac58cSKevin Wolf 105*797ac58cSKevin Wolf timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0); 106*797ac58cSKevin Wolf if (!Cflag) { 107*797ac58cSKevin Wolf cvtstr((double)total, s1, sizeof(s1)); 108*797ac58cSKevin Wolf cvtstr(tdiv((double)total, *t), s2, sizeof(s2)); 109*797ac58cSKevin Wolf printf("%s %d/%d bytes at offset %" PRId64 "\n", 110*797ac58cSKevin Wolf op, total, count, offset); 111*797ac58cSKevin Wolf printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n", 112*797ac58cSKevin Wolf s1, cnt, ts, s2, tdiv((double)cnt, *t)); 113*797ac58cSKevin Wolf } else {/* bytes,ops,time,bytes/sec,ops/sec */ 114*797ac58cSKevin Wolf printf("%d,%d,%s,%.3f,%.3f\n", 115*797ac58cSKevin Wolf total, cnt, ts, 116*797ac58cSKevin Wolf tdiv((double)total, *t), 117*797ac58cSKevin Wolf tdiv((double)cnt, *t)); 118*797ac58cSKevin Wolf } 119*797ac58cSKevin Wolf } 120*797ac58cSKevin Wolf 121*797ac58cSKevin Wolf /* 122*797ac58cSKevin Wolf * Parse multiple length statements for vectored I/O, and construct an I/O 123*797ac58cSKevin Wolf * vector matching it. 124*797ac58cSKevin Wolf */ 125*797ac58cSKevin Wolf static void * 126*797ac58cSKevin Wolf create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov, 127*797ac58cSKevin Wolf int pattern) 128*797ac58cSKevin Wolf { 129*797ac58cSKevin Wolf size_t *sizes = g_new0(size_t, nr_iov); 130*797ac58cSKevin Wolf size_t count = 0; 131*797ac58cSKevin Wolf void *buf = NULL; 132*797ac58cSKevin Wolf void *p; 133*797ac58cSKevin Wolf int i; 134*797ac58cSKevin Wolf 135*797ac58cSKevin Wolf for (i = 0; i < nr_iov; i++) { 136*797ac58cSKevin Wolf char *arg = argv[i]; 137*797ac58cSKevin Wolf int64_t len; 138*797ac58cSKevin Wolf 139*797ac58cSKevin Wolf len = cvtnum(arg); 140*797ac58cSKevin Wolf if (len < 0) { 141*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", arg); 142*797ac58cSKevin Wolf goto fail; 143*797ac58cSKevin Wolf } 144*797ac58cSKevin Wolf 145*797ac58cSKevin Wolf /* should be SIZE_T_MAX, but that doesn't exist */ 146*797ac58cSKevin Wolf if (len > INT_MAX) { 147*797ac58cSKevin Wolf printf("too large length argument -- %s\n", arg); 148*797ac58cSKevin Wolf goto fail; 149*797ac58cSKevin Wolf } 150*797ac58cSKevin Wolf 151*797ac58cSKevin Wolf if (len & 0x1ff) { 152*797ac58cSKevin Wolf printf("length argument %" PRId64 153*797ac58cSKevin Wolf " is not sector aligned\n", len); 154*797ac58cSKevin Wolf goto fail; 155*797ac58cSKevin Wolf } 156*797ac58cSKevin Wolf 157*797ac58cSKevin Wolf sizes[i] = len; 158*797ac58cSKevin Wolf count += len; 159*797ac58cSKevin Wolf } 160*797ac58cSKevin Wolf 161*797ac58cSKevin Wolf qemu_iovec_init(qiov, nr_iov); 162*797ac58cSKevin Wolf 163*797ac58cSKevin Wolf buf = p = qemu_io_alloc(bs, count, pattern); 164*797ac58cSKevin Wolf 165*797ac58cSKevin Wolf for (i = 0; i < nr_iov; i++) { 166*797ac58cSKevin Wolf qemu_iovec_add(qiov, p, sizes[i]); 167*797ac58cSKevin Wolf p += sizes[i]; 168*797ac58cSKevin Wolf } 169*797ac58cSKevin Wolf 170*797ac58cSKevin Wolf fail: 171*797ac58cSKevin Wolf g_free(sizes); 172*797ac58cSKevin Wolf return buf; 173*797ac58cSKevin Wolf } 174*797ac58cSKevin Wolf 175*797ac58cSKevin Wolf static int do_read(BlockDriverState *bs, char *buf, int64_t offset, int count, 176*797ac58cSKevin Wolf int *total) 177*797ac58cSKevin Wolf { 178*797ac58cSKevin Wolf int ret; 179*797ac58cSKevin Wolf 180*797ac58cSKevin Wolf ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9); 181*797ac58cSKevin Wolf if (ret < 0) { 182*797ac58cSKevin Wolf return ret; 183*797ac58cSKevin Wolf } 184*797ac58cSKevin Wolf *total = count; 185*797ac58cSKevin Wolf return 1; 186*797ac58cSKevin Wolf } 187*797ac58cSKevin Wolf 188*797ac58cSKevin Wolf static int do_write(BlockDriverState *bs, char *buf, int64_t offset, int count, 189*797ac58cSKevin Wolf int *total) 190*797ac58cSKevin Wolf { 191*797ac58cSKevin Wolf int ret; 192*797ac58cSKevin Wolf 193*797ac58cSKevin Wolf ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9); 194*797ac58cSKevin Wolf if (ret < 0) { 195*797ac58cSKevin Wolf return ret; 196*797ac58cSKevin Wolf } 197*797ac58cSKevin Wolf *total = count; 198*797ac58cSKevin Wolf return 1; 199*797ac58cSKevin Wolf } 200*797ac58cSKevin Wolf 201*797ac58cSKevin Wolf static int do_pread(BlockDriverState *bs, char *buf, int64_t offset, int count, 202*797ac58cSKevin Wolf int *total) 203*797ac58cSKevin Wolf { 204*797ac58cSKevin Wolf *total = bdrv_pread(bs, offset, (uint8_t *)buf, count); 205*797ac58cSKevin Wolf if (*total < 0) { 206*797ac58cSKevin Wolf return *total; 207*797ac58cSKevin Wolf } 208*797ac58cSKevin Wolf return 1; 209*797ac58cSKevin Wolf } 210*797ac58cSKevin Wolf 211*797ac58cSKevin Wolf static int do_pwrite(BlockDriverState *bs, char *buf, int64_t offset, int count, 212*797ac58cSKevin Wolf int *total) 213*797ac58cSKevin Wolf { 214*797ac58cSKevin Wolf *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count); 215*797ac58cSKevin Wolf if (*total < 0) { 216*797ac58cSKevin Wolf return *total; 217*797ac58cSKevin Wolf } 218*797ac58cSKevin Wolf return 1; 219*797ac58cSKevin Wolf } 220*797ac58cSKevin Wolf 221*797ac58cSKevin Wolf typedef struct { 222*797ac58cSKevin Wolf BlockDriverState *bs; 223*797ac58cSKevin Wolf int64_t offset; 224*797ac58cSKevin Wolf int count; 225*797ac58cSKevin Wolf int *total; 226*797ac58cSKevin Wolf int ret; 227*797ac58cSKevin Wolf bool done; 228*797ac58cSKevin Wolf } CoWriteZeroes; 229*797ac58cSKevin Wolf 230*797ac58cSKevin Wolf static void coroutine_fn co_write_zeroes_entry(void *opaque) 231*797ac58cSKevin Wolf { 232*797ac58cSKevin Wolf CoWriteZeroes *data = opaque; 233*797ac58cSKevin Wolf 234*797ac58cSKevin Wolf data->ret = bdrv_co_write_zeroes(data->bs, data->offset / BDRV_SECTOR_SIZE, 235*797ac58cSKevin Wolf data->count / BDRV_SECTOR_SIZE); 236*797ac58cSKevin Wolf data->done = true; 237*797ac58cSKevin Wolf if (data->ret < 0) { 238*797ac58cSKevin Wolf *data->total = data->ret; 239*797ac58cSKevin Wolf return; 240*797ac58cSKevin Wolf } 241*797ac58cSKevin Wolf 242*797ac58cSKevin Wolf *data->total = data->count; 243*797ac58cSKevin Wolf } 244*797ac58cSKevin Wolf 245*797ac58cSKevin Wolf static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count, 246*797ac58cSKevin Wolf int *total) 247*797ac58cSKevin Wolf { 248*797ac58cSKevin Wolf Coroutine *co; 249*797ac58cSKevin Wolf CoWriteZeroes data = { 250*797ac58cSKevin Wolf .bs = bs, 251*797ac58cSKevin Wolf .offset = offset, 252*797ac58cSKevin Wolf .count = count, 253*797ac58cSKevin Wolf .total = total, 254*797ac58cSKevin Wolf .done = false, 255*797ac58cSKevin Wolf }; 256*797ac58cSKevin Wolf 257*797ac58cSKevin Wolf co = qemu_coroutine_create(co_write_zeroes_entry); 258*797ac58cSKevin Wolf qemu_coroutine_enter(co, &data); 259*797ac58cSKevin Wolf while (!data.done) { 260*797ac58cSKevin Wolf qemu_aio_wait(); 261*797ac58cSKevin Wolf } 262*797ac58cSKevin Wolf if (data.ret < 0) { 263*797ac58cSKevin Wolf return data.ret; 264*797ac58cSKevin Wolf } else { 265*797ac58cSKevin Wolf return 1; 266*797ac58cSKevin Wolf } 267*797ac58cSKevin Wolf } 268*797ac58cSKevin Wolf 269*797ac58cSKevin Wolf static int do_write_compressed(BlockDriverState *bs, char *buf, int64_t offset, 270*797ac58cSKevin Wolf int count, int *total) 271*797ac58cSKevin Wolf { 272*797ac58cSKevin Wolf int ret; 273*797ac58cSKevin Wolf 274*797ac58cSKevin Wolf ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9); 275*797ac58cSKevin Wolf if (ret < 0) { 276*797ac58cSKevin Wolf return ret; 277*797ac58cSKevin Wolf } 278*797ac58cSKevin Wolf *total = count; 279*797ac58cSKevin Wolf return 1; 280*797ac58cSKevin Wolf } 281*797ac58cSKevin Wolf 282*797ac58cSKevin Wolf static int do_load_vmstate(BlockDriverState *bs, char *buf, int64_t offset, 283*797ac58cSKevin Wolf int count, int *total) 284*797ac58cSKevin Wolf { 285*797ac58cSKevin Wolf *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count); 286*797ac58cSKevin Wolf if (*total < 0) { 287*797ac58cSKevin Wolf return *total; 288*797ac58cSKevin Wolf } 289*797ac58cSKevin Wolf return 1; 290*797ac58cSKevin Wolf } 291*797ac58cSKevin Wolf 292*797ac58cSKevin Wolf static int do_save_vmstate(BlockDriverState *bs, char *buf, int64_t offset, 293*797ac58cSKevin Wolf int count, int *total) 294*797ac58cSKevin Wolf { 295*797ac58cSKevin Wolf *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count); 296*797ac58cSKevin Wolf if (*total < 0) { 297*797ac58cSKevin Wolf return *total; 298*797ac58cSKevin Wolf } 299*797ac58cSKevin Wolf return 1; 300*797ac58cSKevin Wolf } 301*797ac58cSKevin Wolf 302*797ac58cSKevin Wolf #define NOT_DONE 0x7fffffff 303*797ac58cSKevin Wolf static void aio_rw_done(void *opaque, int ret) 304*797ac58cSKevin Wolf { 305*797ac58cSKevin Wolf *(int *)opaque = ret; 306*797ac58cSKevin Wolf } 307*797ac58cSKevin Wolf 308*797ac58cSKevin Wolf static int do_aio_readv(BlockDriverState *bs, QEMUIOVector *qiov, 309*797ac58cSKevin Wolf int64_t offset, int *total) 310*797ac58cSKevin Wolf { 311*797ac58cSKevin Wolf int async_ret = NOT_DONE; 312*797ac58cSKevin Wolf 313*797ac58cSKevin Wolf bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, 314*797ac58cSKevin Wolf aio_rw_done, &async_ret); 315*797ac58cSKevin Wolf while (async_ret == NOT_DONE) { 316*797ac58cSKevin Wolf main_loop_wait(false); 317*797ac58cSKevin Wolf } 318*797ac58cSKevin Wolf 319*797ac58cSKevin Wolf *total = qiov->size; 320*797ac58cSKevin Wolf return async_ret < 0 ? async_ret : 1; 321*797ac58cSKevin Wolf } 322*797ac58cSKevin Wolf 323*797ac58cSKevin Wolf static int do_aio_writev(BlockDriverState *bs, QEMUIOVector *qiov, 324*797ac58cSKevin Wolf int64_t offset, int *total) 325*797ac58cSKevin Wolf { 326*797ac58cSKevin Wolf int async_ret = NOT_DONE; 327*797ac58cSKevin Wolf 328*797ac58cSKevin Wolf bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, 329*797ac58cSKevin Wolf aio_rw_done, &async_ret); 330*797ac58cSKevin Wolf while (async_ret == NOT_DONE) { 331*797ac58cSKevin Wolf main_loop_wait(false); 332*797ac58cSKevin Wolf } 333*797ac58cSKevin Wolf 334*797ac58cSKevin Wolf *total = qiov->size; 335*797ac58cSKevin Wolf return async_ret < 0 ? async_ret : 1; 336*797ac58cSKevin Wolf } 337*797ac58cSKevin Wolf 338*797ac58cSKevin Wolf struct multiwrite_async_ret { 339*797ac58cSKevin Wolf int num_done; 340*797ac58cSKevin Wolf int error; 341*797ac58cSKevin Wolf }; 342*797ac58cSKevin Wolf 343*797ac58cSKevin Wolf static void multiwrite_cb(void *opaque, int ret) 344*797ac58cSKevin Wolf { 345*797ac58cSKevin Wolf struct multiwrite_async_ret *async_ret = opaque; 346*797ac58cSKevin Wolf 347*797ac58cSKevin Wolf async_ret->num_done++; 348*797ac58cSKevin Wolf if (ret < 0) { 349*797ac58cSKevin Wolf async_ret->error = ret; 350*797ac58cSKevin Wolf } 351*797ac58cSKevin Wolf } 352*797ac58cSKevin Wolf 353*797ac58cSKevin Wolf static int do_aio_multiwrite(BlockDriverState *bs, BlockRequest* reqs, 354*797ac58cSKevin Wolf int num_reqs, int *total) 355*797ac58cSKevin Wolf { 356*797ac58cSKevin Wolf int i, ret; 357*797ac58cSKevin Wolf struct multiwrite_async_ret async_ret = { 358*797ac58cSKevin Wolf .num_done = 0, 359*797ac58cSKevin Wolf .error = 0, 360*797ac58cSKevin Wolf }; 361*797ac58cSKevin Wolf 362*797ac58cSKevin Wolf *total = 0; 363*797ac58cSKevin Wolf for (i = 0; i < num_reqs; i++) { 364*797ac58cSKevin Wolf reqs[i].cb = multiwrite_cb; 365*797ac58cSKevin Wolf reqs[i].opaque = &async_ret; 366*797ac58cSKevin Wolf *total += reqs[i].qiov->size; 367*797ac58cSKevin Wolf } 368*797ac58cSKevin Wolf 369*797ac58cSKevin Wolf ret = bdrv_aio_multiwrite(bs, reqs, num_reqs); 370*797ac58cSKevin Wolf if (ret < 0) { 371*797ac58cSKevin Wolf return ret; 372*797ac58cSKevin Wolf } 373*797ac58cSKevin Wolf 374*797ac58cSKevin Wolf while (async_ret.num_done < num_reqs) { 375*797ac58cSKevin Wolf main_loop_wait(false); 376*797ac58cSKevin Wolf } 377*797ac58cSKevin Wolf 378*797ac58cSKevin Wolf return async_ret.error < 0 ? async_ret.error : 1; 379*797ac58cSKevin Wolf } 380*797ac58cSKevin Wolf 381*797ac58cSKevin Wolf static void read_help(void) 382*797ac58cSKevin Wolf { 383*797ac58cSKevin Wolf printf( 384*797ac58cSKevin Wolf "\n" 385*797ac58cSKevin Wolf " reads a range of bytes from the given offset\n" 386*797ac58cSKevin Wolf "\n" 387*797ac58cSKevin Wolf " Example:\n" 388*797ac58cSKevin Wolf " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" 389*797ac58cSKevin Wolf "\n" 390*797ac58cSKevin Wolf " Reads a segment of the currently open file, optionally dumping it to the\n" 391*797ac58cSKevin Wolf " standard output stream (with -v option) for subsequent inspection.\n" 392*797ac58cSKevin Wolf " -b, -- read from the VM state rather than the virtual disk\n" 393*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 394*797ac58cSKevin Wolf " -l, -- length for pattern verification (only with -P)\n" 395*797ac58cSKevin Wolf " -p, -- use bdrv_pread to read the file\n" 396*797ac58cSKevin Wolf " -P, -- use a pattern to verify read data\n" 397*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 398*797ac58cSKevin Wolf " -s, -- start offset for pattern verification (only with -P)\n" 399*797ac58cSKevin Wolf " -v, -- dump buffer to standard output\n" 400*797ac58cSKevin Wolf "\n"); 401*797ac58cSKevin Wolf } 402*797ac58cSKevin Wolf 403*797ac58cSKevin Wolf static int read_f(BlockDriverState *bs, int argc, char **argv); 404*797ac58cSKevin Wolf 405*797ac58cSKevin Wolf static const cmdinfo_t read_cmd = { 406*797ac58cSKevin Wolf .name = "read", 407*797ac58cSKevin Wolf .altname = "r", 408*797ac58cSKevin Wolf .cfunc = read_f, 409*797ac58cSKevin Wolf .argmin = 2, 410*797ac58cSKevin Wolf .argmax = -1, 411*797ac58cSKevin Wolf .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", 412*797ac58cSKevin Wolf .oneline = "reads a number of bytes at a specified offset", 413*797ac58cSKevin Wolf .help = read_help, 414*797ac58cSKevin Wolf }; 415*797ac58cSKevin Wolf 416*797ac58cSKevin Wolf static int read_f(BlockDriverState *bs, int argc, char **argv) 417*797ac58cSKevin Wolf { 418*797ac58cSKevin Wolf struct timeval t1, t2; 419*797ac58cSKevin Wolf int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; 420*797ac58cSKevin Wolf int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; 421*797ac58cSKevin Wolf int c, cnt; 422*797ac58cSKevin Wolf char *buf; 423*797ac58cSKevin Wolf int64_t offset; 424*797ac58cSKevin Wolf int count; 425*797ac58cSKevin Wolf /* Some compilers get confused and warn if this is not initialized. */ 426*797ac58cSKevin Wolf int total = 0; 427*797ac58cSKevin Wolf int pattern = 0, pattern_offset = 0, pattern_count = 0; 428*797ac58cSKevin Wolf 429*797ac58cSKevin Wolf while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { 430*797ac58cSKevin Wolf switch (c) { 431*797ac58cSKevin Wolf case 'b': 432*797ac58cSKevin Wolf bflag = 1; 433*797ac58cSKevin Wolf break; 434*797ac58cSKevin Wolf case 'C': 435*797ac58cSKevin Wolf Cflag = 1; 436*797ac58cSKevin Wolf break; 437*797ac58cSKevin Wolf case 'l': 438*797ac58cSKevin Wolf lflag = 1; 439*797ac58cSKevin Wolf pattern_count = cvtnum(optarg); 440*797ac58cSKevin Wolf if (pattern_count < 0) { 441*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 442*797ac58cSKevin Wolf return 0; 443*797ac58cSKevin Wolf } 444*797ac58cSKevin Wolf break; 445*797ac58cSKevin Wolf case 'p': 446*797ac58cSKevin Wolf pflag = 1; 447*797ac58cSKevin Wolf break; 448*797ac58cSKevin Wolf case 'P': 449*797ac58cSKevin Wolf Pflag = 1; 450*797ac58cSKevin Wolf pattern = parse_pattern(optarg); 451*797ac58cSKevin Wolf if (pattern < 0) { 452*797ac58cSKevin Wolf return 0; 453*797ac58cSKevin Wolf } 454*797ac58cSKevin Wolf break; 455*797ac58cSKevin Wolf case 'q': 456*797ac58cSKevin Wolf qflag = 1; 457*797ac58cSKevin Wolf break; 458*797ac58cSKevin Wolf case 's': 459*797ac58cSKevin Wolf sflag = 1; 460*797ac58cSKevin Wolf pattern_offset = cvtnum(optarg); 461*797ac58cSKevin Wolf if (pattern_offset < 0) { 462*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", optarg); 463*797ac58cSKevin Wolf return 0; 464*797ac58cSKevin Wolf } 465*797ac58cSKevin Wolf break; 466*797ac58cSKevin Wolf case 'v': 467*797ac58cSKevin Wolf vflag = 1; 468*797ac58cSKevin Wolf break; 469*797ac58cSKevin Wolf default: 470*797ac58cSKevin Wolf return command_usage(&read_cmd); 471*797ac58cSKevin Wolf } 472*797ac58cSKevin Wolf } 473*797ac58cSKevin Wolf 474*797ac58cSKevin Wolf if (optind != argc - 2) { 475*797ac58cSKevin Wolf return command_usage(&read_cmd); 476*797ac58cSKevin Wolf } 477*797ac58cSKevin Wolf 478*797ac58cSKevin Wolf if (bflag && pflag) { 479*797ac58cSKevin Wolf printf("-b and -p cannot be specified at the same time\n"); 480*797ac58cSKevin Wolf return 0; 481*797ac58cSKevin Wolf } 482*797ac58cSKevin Wolf 483*797ac58cSKevin Wolf offset = cvtnum(argv[optind]); 484*797ac58cSKevin Wolf if (offset < 0) { 485*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 486*797ac58cSKevin Wolf return 0; 487*797ac58cSKevin Wolf } 488*797ac58cSKevin Wolf 489*797ac58cSKevin Wolf optind++; 490*797ac58cSKevin Wolf count = cvtnum(argv[optind]); 491*797ac58cSKevin Wolf if (count < 0) { 492*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 493*797ac58cSKevin Wolf return 0; 494*797ac58cSKevin Wolf } 495*797ac58cSKevin Wolf 496*797ac58cSKevin Wolf if (!Pflag && (lflag || sflag)) { 497*797ac58cSKevin Wolf return command_usage(&read_cmd); 498*797ac58cSKevin Wolf } 499*797ac58cSKevin Wolf 500*797ac58cSKevin Wolf if (!lflag) { 501*797ac58cSKevin Wolf pattern_count = count - pattern_offset; 502*797ac58cSKevin Wolf } 503*797ac58cSKevin Wolf 504*797ac58cSKevin Wolf if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { 505*797ac58cSKevin Wolf printf("pattern verification range exceeds end of read data\n"); 506*797ac58cSKevin Wolf return 0; 507*797ac58cSKevin Wolf } 508*797ac58cSKevin Wolf 509*797ac58cSKevin Wolf if (!pflag) { 510*797ac58cSKevin Wolf if (offset & 0x1ff) { 511*797ac58cSKevin Wolf printf("offset %" PRId64 " is not sector aligned\n", 512*797ac58cSKevin Wolf offset); 513*797ac58cSKevin Wolf return 0; 514*797ac58cSKevin Wolf } 515*797ac58cSKevin Wolf if (count & 0x1ff) { 516*797ac58cSKevin Wolf printf("count %d is not sector aligned\n", 517*797ac58cSKevin Wolf count); 518*797ac58cSKevin Wolf return 0; 519*797ac58cSKevin Wolf } 520*797ac58cSKevin Wolf } 521*797ac58cSKevin Wolf 522*797ac58cSKevin Wolf buf = qemu_io_alloc(bs, count, 0xab); 523*797ac58cSKevin Wolf 524*797ac58cSKevin Wolf gettimeofday(&t1, NULL); 525*797ac58cSKevin Wolf if (pflag) { 526*797ac58cSKevin Wolf cnt = do_pread(bs, buf, offset, count, &total); 527*797ac58cSKevin Wolf } else if (bflag) { 528*797ac58cSKevin Wolf cnt = do_load_vmstate(bs, buf, offset, count, &total); 529*797ac58cSKevin Wolf } else { 530*797ac58cSKevin Wolf cnt = do_read(bs, buf, offset, count, &total); 531*797ac58cSKevin Wolf } 532*797ac58cSKevin Wolf gettimeofday(&t2, NULL); 533*797ac58cSKevin Wolf 534*797ac58cSKevin Wolf if (cnt < 0) { 535*797ac58cSKevin Wolf printf("read failed: %s\n", strerror(-cnt)); 536*797ac58cSKevin Wolf goto out; 537*797ac58cSKevin Wolf } 538*797ac58cSKevin Wolf 539*797ac58cSKevin Wolf if (Pflag) { 540*797ac58cSKevin Wolf void *cmp_buf = g_malloc(pattern_count); 541*797ac58cSKevin Wolf memset(cmp_buf, pattern, pattern_count); 542*797ac58cSKevin Wolf if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { 543*797ac58cSKevin Wolf printf("Pattern verification failed at offset %" 544*797ac58cSKevin Wolf PRId64 ", %d bytes\n", 545*797ac58cSKevin Wolf offset + pattern_offset, pattern_count); 546*797ac58cSKevin Wolf } 547*797ac58cSKevin Wolf g_free(cmp_buf); 548*797ac58cSKevin Wolf } 549*797ac58cSKevin Wolf 550*797ac58cSKevin Wolf if (qflag) { 551*797ac58cSKevin Wolf goto out; 552*797ac58cSKevin Wolf } 553*797ac58cSKevin Wolf 554*797ac58cSKevin Wolf if (vflag) { 555*797ac58cSKevin Wolf dump_buffer(buf, offset, count); 556*797ac58cSKevin Wolf } 557*797ac58cSKevin Wolf 558*797ac58cSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 559*797ac58cSKevin Wolf t2 = tsub(t2, t1); 560*797ac58cSKevin Wolf print_report("read", &t2, offset, count, total, cnt, Cflag); 561*797ac58cSKevin Wolf 562*797ac58cSKevin Wolf out: 563*797ac58cSKevin Wolf qemu_io_free(buf); 564*797ac58cSKevin Wolf 565*797ac58cSKevin Wolf return 0; 566*797ac58cSKevin Wolf } 567*797ac58cSKevin Wolf 568*797ac58cSKevin Wolf static void readv_help(void) 569*797ac58cSKevin Wolf { 570*797ac58cSKevin Wolf printf( 571*797ac58cSKevin Wolf "\n" 572*797ac58cSKevin Wolf " reads a range of bytes from the given offset into multiple buffers\n" 573*797ac58cSKevin Wolf "\n" 574*797ac58cSKevin Wolf " Example:\n" 575*797ac58cSKevin Wolf " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 576*797ac58cSKevin Wolf "\n" 577*797ac58cSKevin Wolf " Reads a segment of the currently open file, optionally dumping it to the\n" 578*797ac58cSKevin Wolf " standard output stream (with -v option) for subsequent inspection.\n" 579*797ac58cSKevin Wolf " Uses multiple iovec buffers if more than one byte range is specified.\n" 580*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 581*797ac58cSKevin Wolf " -P, -- use a pattern to verify read data\n" 582*797ac58cSKevin Wolf " -v, -- dump buffer to standard output\n" 583*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 584*797ac58cSKevin Wolf "\n"); 585*797ac58cSKevin Wolf } 586*797ac58cSKevin Wolf 587*797ac58cSKevin Wolf static int readv_f(BlockDriverState *bs, int argc, char **argv); 588*797ac58cSKevin Wolf 589*797ac58cSKevin Wolf static const cmdinfo_t readv_cmd = { 590*797ac58cSKevin Wolf .name = "readv", 591*797ac58cSKevin Wolf .cfunc = readv_f, 592*797ac58cSKevin Wolf .argmin = 2, 593*797ac58cSKevin Wolf .argmax = -1, 594*797ac58cSKevin Wolf .args = "[-Cqv] [-P pattern ] off len [len..]", 595*797ac58cSKevin Wolf .oneline = "reads a number of bytes at a specified offset", 596*797ac58cSKevin Wolf .help = readv_help, 597*797ac58cSKevin Wolf }; 598*797ac58cSKevin Wolf 599*797ac58cSKevin Wolf static int readv_f(BlockDriverState *bs, int argc, char **argv) 600*797ac58cSKevin Wolf { 601*797ac58cSKevin Wolf struct timeval t1, t2; 602*797ac58cSKevin Wolf int Cflag = 0, qflag = 0, vflag = 0; 603*797ac58cSKevin Wolf int c, cnt; 604*797ac58cSKevin Wolf char *buf; 605*797ac58cSKevin Wolf int64_t offset; 606*797ac58cSKevin Wolf /* Some compilers get confused and warn if this is not initialized. */ 607*797ac58cSKevin Wolf int total = 0; 608*797ac58cSKevin Wolf int nr_iov; 609*797ac58cSKevin Wolf QEMUIOVector qiov; 610*797ac58cSKevin Wolf int pattern = 0; 611*797ac58cSKevin Wolf int Pflag = 0; 612*797ac58cSKevin Wolf 613*797ac58cSKevin Wolf while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 614*797ac58cSKevin Wolf switch (c) { 615*797ac58cSKevin Wolf case 'C': 616*797ac58cSKevin Wolf Cflag = 1; 617*797ac58cSKevin Wolf break; 618*797ac58cSKevin Wolf case 'P': 619*797ac58cSKevin Wolf Pflag = 1; 620*797ac58cSKevin Wolf pattern = parse_pattern(optarg); 621*797ac58cSKevin Wolf if (pattern < 0) { 622*797ac58cSKevin Wolf return 0; 623*797ac58cSKevin Wolf } 624*797ac58cSKevin Wolf break; 625*797ac58cSKevin Wolf case 'q': 626*797ac58cSKevin Wolf qflag = 1; 627*797ac58cSKevin Wolf break; 628*797ac58cSKevin Wolf case 'v': 629*797ac58cSKevin Wolf vflag = 1; 630*797ac58cSKevin Wolf break; 631*797ac58cSKevin Wolf default: 632*797ac58cSKevin Wolf return command_usage(&readv_cmd); 633*797ac58cSKevin Wolf } 634*797ac58cSKevin Wolf } 635*797ac58cSKevin Wolf 636*797ac58cSKevin Wolf if (optind > argc - 2) { 637*797ac58cSKevin Wolf return command_usage(&readv_cmd); 638*797ac58cSKevin Wolf } 639*797ac58cSKevin Wolf 640*797ac58cSKevin Wolf 641*797ac58cSKevin Wolf offset = cvtnum(argv[optind]); 642*797ac58cSKevin Wolf if (offset < 0) { 643*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 644*797ac58cSKevin Wolf return 0; 645*797ac58cSKevin Wolf } 646*797ac58cSKevin Wolf optind++; 647*797ac58cSKevin Wolf 648*797ac58cSKevin Wolf if (offset & 0x1ff) { 649*797ac58cSKevin Wolf printf("offset %" PRId64 " is not sector aligned\n", 650*797ac58cSKevin Wolf offset); 651*797ac58cSKevin Wolf return 0; 652*797ac58cSKevin Wolf } 653*797ac58cSKevin Wolf 654*797ac58cSKevin Wolf nr_iov = argc - optind; 655*797ac58cSKevin Wolf buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, 0xab); 656*797ac58cSKevin Wolf if (buf == NULL) { 657*797ac58cSKevin Wolf return 0; 658*797ac58cSKevin Wolf } 659*797ac58cSKevin Wolf 660*797ac58cSKevin Wolf gettimeofday(&t1, NULL); 661*797ac58cSKevin Wolf cnt = do_aio_readv(bs, &qiov, offset, &total); 662*797ac58cSKevin Wolf gettimeofday(&t2, NULL); 663*797ac58cSKevin Wolf 664*797ac58cSKevin Wolf if (cnt < 0) { 665*797ac58cSKevin Wolf printf("readv failed: %s\n", strerror(-cnt)); 666*797ac58cSKevin Wolf goto out; 667*797ac58cSKevin Wolf } 668*797ac58cSKevin Wolf 669*797ac58cSKevin Wolf if (Pflag) { 670*797ac58cSKevin Wolf void *cmp_buf = g_malloc(qiov.size); 671*797ac58cSKevin Wolf memset(cmp_buf, pattern, qiov.size); 672*797ac58cSKevin Wolf if (memcmp(buf, cmp_buf, qiov.size)) { 673*797ac58cSKevin Wolf printf("Pattern verification failed at offset %" 674*797ac58cSKevin Wolf PRId64 ", %zd bytes\n", offset, qiov.size); 675*797ac58cSKevin Wolf } 676*797ac58cSKevin Wolf g_free(cmp_buf); 677*797ac58cSKevin Wolf } 678*797ac58cSKevin Wolf 679*797ac58cSKevin Wolf if (qflag) { 680*797ac58cSKevin Wolf goto out; 681*797ac58cSKevin Wolf } 682*797ac58cSKevin Wolf 683*797ac58cSKevin Wolf if (vflag) { 684*797ac58cSKevin Wolf dump_buffer(buf, offset, qiov.size); 685*797ac58cSKevin Wolf } 686*797ac58cSKevin Wolf 687*797ac58cSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 688*797ac58cSKevin Wolf t2 = tsub(t2, t1); 689*797ac58cSKevin Wolf print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); 690*797ac58cSKevin Wolf 691*797ac58cSKevin Wolf out: 692*797ac58cSKevin Wolf qemu_iovec_destroy(&qiov); 693*797ac58cSKevin Wolf qemu_io_free(buf); 694*797ac58cSKevin Wolf return 0; 695*797ac58cSKevin Wolf } 696*797ac58cSKevin Wolf 697*797ac58cSKevin Wolf static void write_help(void) 698*797ac58cSKevin Wolf { 699*797ac58cSKevin Wolf printf( 700*797ac58cSKevin Wolf "\n" 701*797ac58cSKevin Wolf " writes a range of bytes from the given offset\n" 702*797ac58cSKevin Wolf "\n" 703*797ac58cSKevin Wolf " Example:\n" 704*797ac58cSKevin Wolf " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n" 705*797ac58cSKevin Wolf "\n" 706*797ac58cSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n" 707*797ac58cSKevin Wolf " filled with a set pattern (0xcdcdcdcd).\n" 708*797ac58cSKevin Wolf " -b, -- write to the VM state rather than the virtual disk\n" 709*797ac58cSKevin Wolf " -c, -- write compressed data with bdrv_write_compressed\n" 710*797ac58cSKevin Wolf " -p, -- use bdrv_pwrite to write the file\n" 711*797ac58cSKevin Wolf " -P, -- use different pattern to fill file\n" 712*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 713*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 714*797ac58cSKevin Wolf " -z, -- write zeroes using bdrv_co_write_zeroes\n" 715*797ac58cSKevin Wolf "\n"); 716*797ac58cSKevin Wolf } 717*797ac58cSKevin Wolf 718*797ac58cSKevin Wolf static int write_f(BlockDriverState *bs, int argc, char **argv); 719*797ac58cSKevin Wolf 720*797ac58cSKevin Wolf static const cmdinfo_t write_cmd = { 721*797ac58cSKevin Wolf .name = "write", 722*797ac58cSKevin Wolf .altname = "w", 723*797ac58cSKevin Wolf .cfunc = write_f, 724*797ac58cSKevin Wolf .argmin = 2, 725*797ac58cSKevin Wolf .argmax = -1, 726*797ac58cSKevin Wolf .args = "[-bcCpqz] [-P pattern ] off len", 727*797ac58cSKevin Wolf .oneline = "writes a number of bytes at a specified offset", 728*797ac58cSKevin Wolf .help = write_help, 729*797ac58cSKevin Wolf }; 730*797ac58cSKevin Wolf 731*797ac58cSKevin Wolf static int write_f(BlockDriverState *bs, int argc, char **argv) 732*797ac58cSKevin Wolf { 733*797ac58cSKevin Wolf struct timeval t1, t2; 734*797ac58cSKevin Wolf int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0; 735*797ac58cSKevin Wolf int cflag = 0; 736*797ac58cSKevin Wolf int c, cnt; 737*797ac58cSKevin Wolf char *buf = NULL; 738*797ac58cSKevin Wolf int64_t offset; 739*797ac58cSKevin Wolf int count; 740*797ac58cSKevin Wolf /* Some compilers get confused and warn if this is not initialized. */ 741*797ac58cSKevin Wolf int total = 0; 742*797ac58cSKevin Wolf int pattern = 0xcd; 743*797ac58cSKevin Wolf 744*797ac58cSKevin Wolf while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) { 745*797ac58cSKevin Wolf switch (c) { 746*797ac58cSKevin Wolf case 'b': 747*797ac58cSKevin Wolf bflag = 1; 748*797ac58cSKevin Wolf break; 749*797ac58cSKevin Wolf case 'c': 750*797ac58cSKevin Wolf cflag = 1; 751*797ac58cSKevin Wolf break; 752*797ac58cSKevin Wolf case 'C': 753*797ac58cSKevin Wolf Cflag = 1; 754*797ac58cSKevin Wolf break; 755*797ac58cSKevin Wolf case 'p': 756*797ac58cSKevin Wolf pflag = 1; 757*797ac58cSKevin Wolf break; 758*797ac58cSKevin Wolf case 'P': 759*797ac58cSKevin Wolf Pflag = 1; 760*797ac58cSKevin Wolf pattern = parse_pattern(optarg); 761*797ac58cSKevin Wolf if (pattern < 0) { 762*797ac58cSKevin Wolf return 0; 763*797ac58cSKevin Wolf } 764*797ac58cSKevin Wolf break; 765*797ac58cSKevin Wolf case 'q': 766*797ac58cSKevin Wolf qflag = 1; 767*797ac58cSKevin Wolf break; 768*797ac58cSKevin Wolf case 'z': 769*797ac58cSKevin Wolf zflag = 1; 770*797ac58cSKevin Wolf break; 771*797ac58cSKevin Wolf default: 772*797ac58cSKevin Wolf return command_usage(&write_cmd); 773*797ac58cSKevin Wolf } 774*797ac58cSKevin Wolf } 775*797ac58cSKevin Wolf 776*797ac58cSKevin Wolf if (optind != argc - 2) { 777*797ac58cSKevin Wolf return command_usage(&write_cmd); 778*797ac58cSKevin Wolf } 779*797ac58cSKevin Wolf 780*797ac58cSKevin Wolf if (bflag + pflag + zflag > 1) { 781*797ac58cSKevin Wolf printf("-b, -p, or -z cannot be specified at the same time\n"); 782*797ac58cSKevin Wolf return 0; 783*797ac58cSKevin Wolf } 784*797ac58cSKevin Wolf 785*797ac58cSKevin Wolf if (zflag && Pflag) { 786*797ac58cSKevin Wolf printf("-z and -P cannot be specified at the same time\n"); 787*797ac58cSKevin Wolf return 0; 788*797ac58cSKevin Wolf } 789*797ac58cSKevin Wolf 790*797ac58cSKevin Wolf offset = cvtnum(argv[optind]); 791*797ac58cSKevin Wolf if (offset < 0) { 792*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 793*797ac58cSKevin Wolf return 0; 794*797ac58cSKevin Wolf } 795*797ac58cSKevin Wolf 796*797ac58cSKevin Wolf optind++; 797*797ac58cSKevin Wolf count = cvtnum(argv[optind]); 798*797ac58cSKevin Wolf if (count < 0) { 799*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 800*797ac58cSKevin Wolf return 0; 801*797ac58cSKevin Wolf } 802*797ac58cSKevin Wolf 803*797ac58cSKevin Wolf if (!pflag) { 804*797ac58cSKevin Wolf if (offset & 0x1ff) { 805*797ac58cSKevin Wolf printf("offset %" PRId64 " is not sector aligned\n", 806*797ac58cSKevin Wolf offset); 807*797ac58cSKevin Wolf return 0; 808*797ac58cSKevin Wolf } 809*797ac58cSKevin Wolf 810*797ac58cSKevin Wolf if (count & 0x1ff) { 811*797ac58cSKevin Wolf printf("count %d is not sector aligned\n", 812*797ac58cSKevin Wolf count); 813*797ac58cSKevin Wolf return 0; 814*797ac58cSKevin Wolf } 815*797ac58cSKevin Wolf } 816*797ac58cSKevin Wolf 817*797ac58cSKevin Wolf if (!zflag) { 818*797ac58cSKevin Wolf buf = qemu_io_alloc(bs, count, pattern); 819*797ac58cSKevin Wolf } 820*797ac58cSKevin Wolf 821*797ac58cSKevin Wolf gettimeofday(&t1, NULL); 822*797ac58cSKevin Wolf if (pflag) { 823*797ac58cSKevin Wolf cnt = do_pwrite(bs, buf, offset, count, &total); 824*797ac58cSKevin Wolf } else if (bflag) { 825*797ac58cSKevin Wolf cnt = do_save_vmstate(bs, buf, offset, count, &total); 826*797ac58cSKevin Wolf } else if (zflag) { 827*797ac58cSKevin Wolf cnt = do_co_write_zeroes(bs, offset, count, &total); 828*797ac58cSKevin Wolf } else if (cflag) { 829*797ac58cSKevin Wolf cnt = do_write_compressed(bs, buf, offset, count, &total); 830*797ac58cSKevin Wolf } else { 831*797ac58cSKevin Wolf cnt = do_write(bs, buf, offset, count, &total); 832*797ac58cSKevin Wolf } 833*797ac58cSKevin Wolf gettimeofday(&t2, NULL); 834*797ac58cSKevin Wolf 835*797ac58cSKevin Wolf if (cnt < 0) { 836*797ac58cSKevin Wolf printf("write failed: %s\n", strerror(-cnt)); 837*797ac58cSKevin Wolf goto out; 838*797ac58cSKevin Wolf } 839*797ac58cSKevin Wolf 840*797ac58cSKevin Wolf if (qflag) { 841*797ac58cSKevin Wolf goto out; 842*797ac58cSKevin Wolf } 843*797ac58cSKevin Wolf 844*797ac58cSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 845*797ac58cSKevin Wolf t2 = tsub(t2, t1); 846*797ac58cSKevin Wolf print_report("wrote", &t2, offset, count, total, cnt, Cflag); 847*797ac58cSKevin Wolf 848*797ac58cSKevin Wolf out: 849*797ac58cSKevin Wolf if (!zflag) { 850*797ac58cSKevin Wolf qemu_io_free(buf); 851*797ac58cSKevin Wolf } 852*797ac58cSKevin Wolf 853*797ac58cSKevin Wolf return 0; 854*797ac58cSKevin Wolf } 855*797ac58cSKevin Wolf 856*797ac58cSKevin Wolf static void 857*797ac58cSKevin Wolf writev_help(void) 858*797ac58cSKevin Wolf { 859*797ac58cSKevin Wolf printf( 860*797ac58cSKevin Wolf "\n" 861*797ac58cSKevin Wolf " writes a range of bytes from the given offset source from multiple buffers\n" 862*797ac58cSKevin Wolf "\n" 863*797ac58cSKevin Wolf " Example:\n" 864*797ac58cSKevin Wolf " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 865*797ac58cSKevin Wolf "\n" 866*797ac58cSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n" 867*797ac58cSKevin Wolf " filled with a set pattern (0xcdcdcdcd).\n" 868*797ac58cSKevin Wolf " -P, -- use different pattern to fill file\n" 869*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 870*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 871*797ac58cSKevin Wolf "\n"); 872*797ac58cSKevin Wolf } 873*797ac58cSKevin Wolf 874*797ac58cSKevin Wolf static int writev_f(BlockDriverState *bs, int argc, char **argv); 875*797ac58cSKevin Wolf 876*797ac58cSKevin Wolf static const cmdinfo_t writev_cmd = { 877*797ac58cSKevin Wolf .name = "writev", 878*797ac58cSKevin Wolf .cfunc = writev_f, 879*797ac58cSKevin Wolf .argmin = 2, 880*797ac58cSKevin Wolf .argmax = -1, 881*797ac58cSKevin Wolf .args = "[-Cq] [-P pattern ] off len [len..]", 882*797ac58cSKevin Wolf .oneline = "writes a number of bytes at a specified offset", 883*797ac58cSKevin Wolf .help = writev_help, 884*797ac58cSKevin Wolf }; 885*797ac58cSKevin Wolf 886*797ac58cSKevin Wolf static int writev_f(BlockDriverState *bs, int argc, char **argv) 887*797ac58cSKevin Wolf { 888*797ac58cSKevin Wolf struct timeval t1, t2; 889*797ac58cSKevin Wolf int Cflag = 0, qflag = 0; 890*797ac58cSKevin Wolf int c, cnt; 891*797ac58cSKevin Wolf char *buf; 892*797ac58cSKevin Wolf int64_t offset; 893*797ac58cSKevin Wolf /* Some compilers get confused and warn if this is not initialized. */ 894*797ac58cSKevin Wolf int total = 0; 895*797ac58cSKevin Wolf int nr_iov; 896*797ac58cSKevin Wolf int pattern = 0xcd; 897*797ac58cSKevin Wolf QEMUIOVector qiov; 898*797ac58cSKevin Wolf 899*797ac58cSKevin Wolf while ((c = getopt(argc, argv, "CqP:")) != EOF) { 900*797ac58cSKevin Wolf switch (c) { 901*797ac58cSKevin Wolf case 'C': 902*797ac58cSKevin Wolf Cflag = 1; 903*797ac58cSKevin Wolf break; 904*797ac58cSKevin Wolf case 'q': 905*797ac58cSKevin Wolf qflag = 1; 906*797ac58cSKevin Wolf break; 907*797ac58cSKevin Wolf case 'P': 908*797ac58cSKevin Wolf pattern = parse_pattern(optarg); 909*797ac58cSKevin Wolf if (pattern < 0) { 910*797ac58cSKevin Wolf return 0; 911*797ac58cSKevin Wolf } 912*797ac58cSKevin Wolf break; 913*797ac58cSKevin Wolf default: 914*797ac58cSKevin Wolf return command_usage(&writev_cmd); 915*797ac58cSKevin Wolf } 916*797ac58cSKevin Wolf } 917*797ac58cSKevin Wolf 918*797ac58cSKevin Wolf if (optind > argc - 2) { 919*797ac58cSKevin Wolf return command_usage(&writev_cmd); 920*797ac58cSKevin Wolf } 921*797ac58cSKevin Wolf 922*797ac58cSKevin Wolf offset = cvtnum(argv[optind]); 923*797ac58cSKevin Wolf if (offset < 0) { 924*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 925*797ac58cSKevin Wolf return 0; 926*797ac58cSKevin Wolf } 927*797ac58cSKevin Wolf optind++; 928*797ac58cSKevin Wolf 929*797ac58cSKevin Wolf if (offset & 0x1ff) { 930*797ac58cSKevin Wolf printf("offset %" PRId64 " is not sector aligned\n", 931*797ac58cSKevin Wolf offset); 932*797ac58cSKevin Wolf return 0; 933*797ac58cSKevin Wolf } 934*797ac58cSKevin Wolf 935*797ac58cSKevin Wolf nr_iov = argc - optind; 936*797ac58cSKevin Wolf buf = create_iovec(bs, &qiov, &argv[optind], nr_iov, pattern); 937*797ac58cSKevin Wolf if (buf == NULL) { 938*797ac58cSKevin Wolf return 0; 939*797ac58cSKevin Wolf } 940*797ac58cSKevin Wolf 941*797ac58cSKevin Wolf gettimeofday(&t1, NULL); 942*797ac58cSKevin Wolf cnt = do_aio_writev(bs, &qiov, offset, &total); 943*797ac58cSKevin Wolf gettimeofday(&t2, NULL); 944*797ac58cSKevin Wolf 945*797ac58cSKevin Wolf if (cnt < 0) { 946*797ac58cSKevin Wolf printf("writev failed: %s\n", strerror(-cnt)); 947*797ac58cSKevin Wolf goto out; 948*797ac58cSKevin Wolf } 949*797ac58cSKevin Wolf 950*797ac58cSKevin Wolf if (qflag) { 951*797ac58cSKevin Wolf goto out; 952*797ac58cSKevin Wolf } 953*797ac58cSKevin Wolf 954*797ac58cSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 955*797ac58cSKevin Wolf t2 = tsub(t2, t1); 956*797ac58cSKevin Wolf print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); 957*797ac58cSKevin Wolf out: 958*797ac58cSKevin Wolf qemu_iovec_destroy(&qiov); 959*797ac58cSKevin Wolf qemu_io_free(buf); 960*797ac58cSKevin Wolf return 0; 961*797ac58cSKevin Wolf } 962*797ac58cSKevin Wolf 963*797ac58cSKevin Wolf static void multiwrite_help(void) 964*797ac58cSKevin Wolf { 965*797ac58cSKevin Wolf printf( 966*797ac58cSKevin Wolf "\n" 967*797ac58cSKevin Wolf " writes a range of bytes from the given offset source from multiple buffers,\n" 968*797ac58cSKevin Wolf " in a batch of requests that may be merged by qemu\n" 969*797ac58cSKevin Wolf "\n" 970*797ac58cSKevin Wolf " Example:\n" 971*797ac58cSKevin Wolf " 'multiwrite 512 1k 1k ; 4k 1k'\n" 972*797ac58cSKevin Wolf " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n" 973*797ac58cSKevin Wolf "\n" 974*797ac58cSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n" 975*797ac58cSKevin Wolf " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n" 976*797ac58cSKevin Wolf " by one for each request contained in the multiwrite command.\n" 977*797ac58cSKevin Wolf " -P, -- use different pattern to fill file\n" 978*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 979*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 980*797ac58cSKevin Wolf "\n"); 981*797ac58cSKevin Wolf } 982*797ac58cSKevin Wolf 983*797ac58cSKevin Wolf static int multiwrite_f(BlockDriverState *bs, int argc, char **argv); 984*797ac58cSKevin Wolf 985*797ac58cSKevin Wolf static const cmdinfo_t multiwrite_cmd = { 986*797ac58cSKevin Wolf .name = "multiwrite", 987*797ac58cSKevin Wolf .cfunc = multiwrite_f, 988*797ac58cSKevin Wolf .argmin = 2, 989*797ac58cSKevin Wolf .argmax = -1, 990*797ac58cSKevin Wolf .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]", 991*797ac58cSKevin Wolf .oneline = "issues multiple write requests at once", 992*797ac58cSKevin Wolf .help = multiwrite_help, 993*797ac58cSKevin Wolf }; 994*797ac58cSKevin Wolf 995*797ac58cSKevin Wolf static int multiwrite_f(BlockDriverState *bs, int argc, char **argv) 996*797ac58cSKevin Wolf { 997*797ac58cSKevin Wolf struct timeval t1, t2; 998*797ac58cSKevin Wolf int Cflag = 0, qflag = 0; 999*797ac58cSKevin Wolf int c, cnt; 1000*797ac58cSKevin Wolf char **buf; 1001*797ac58cSKevin Wolf int64_t offset, first_offset = 0; 1002*797ac58cSKevin Wolf /* Some compilers get confused and warn if this is not initialized. */ 1003*797ac58cSKevin Wolf int total = 0; 1004*797ac58cSKevin Wolf int nr_iov; 1005*797ac58cSKevin Wolf int nr_reqs; 1006*797ac58cSKevin Wolf int pattern = 0xcd; 1007*797ac58cSKevin Wolf QEMUIOVector *qiovs; 1008*797ac58cSKevin Wolf int i; 1009*797ac58cSKevin Wolf BlockRequest *reqs; 1010*797ac58cSKevin Wolf 1011*797ac58cSKevin Wolf while ((c = getopt(argc, argv, "CqP:")) != EOF) { 1012*797ac58cSKevin Wolf switch (c) { 1013*797ac58cSKevin Wolf case 'C': 1014*797ac58cSKevin Wolf Cflag = 1; 1015*797ac58cSKevin Wolf break; 1016*797ac58cSKevin Wolf case 'q': 1017*797ac58cSKevin Wolf qflag = 1; 1018*797ac58cSKevin Wolf break; 1019*797ac58cSKevin Wolf case 'P': 1020*797ac58cSKevin Wolf pattern = parse_pattern(optarg); 1021*797ac58cSKevin Wolf if (pattern < 0) { 1022*797ac58cSKevin Wolf return 0; 1023*797ac58cSKevin Wolf } 1024*797ac58cSKevin Wolf break; 1025*797ac58cSKevin Wolf default: 1026*797ac58cSKevin Wolf return command_usage(&writev_cmd); 1027*797ac58cSKevin Wolf } 1028*797ac58cSKevin Wolf } 1029*797ac58cSKevin Wolf 1030*797ac58cSKevin Wolf if (optind > argc - 2) { 1031*797ac58cSKevin Wolf return command_usage(&writev_cmd); 1032*797ac58cSKevin Wolf } 1033*797ac58cSKevin Wolf 1034*797ac58cSKevin Wolf nr_reqs = 1; 1035*797ac58cSKevin Wolf for (i = optind; i < argc; i++) { 1036*797ac58cSKevin Wolf if (!strcmp(argv[i], ";")) { 1037*797ac58cSKevin Wolf nr_reqs++; 1038*797ac58cSKevin Wolf } 1039*797ac58cSKevin Wolf } 1040*797ac58cSKevin Wolf 1041*797ac58cSKevin Wolf reqs = g_malloc0(nr_reqs * sizeof(*reqs)); 1042*797ac58cSKevin Wolf buf = g_malloc0(nr_reqs * sizeof(*buf)); 1043*797ac58cSKevin Wolf qiovs = g_malloc(nr_reqs * sizeof(*qiovs)); 1044*797ac58cSKevin Wolf 1045*797ac58cSKevin Wolf for (i = 0; i < nr_reqs && optind < argc; i++) { 1046*797ac58cSKevin Wolf int j; 1047*797ac58cSKevin Wolf 1048*797ac58cSKevin Wolf /* Read the offset of the request */ 1049*797ac58cSKevin Wolf offset = cvtnum(argv[optind]); 1050*797ac58cSKevin Wolf if (offset < 0) { 1051*797ac58cSKevin Wolf printf("non-numeric offset argument -- %s\n", argv[optind]); 1052*797ac58cSKevin Wolf goto out; 1053*797ac58cSKevin Wolf } 1054*797ac58cSKevin Wolf optind++; 1055*797ac58cSKevin Wolf 1056*797ac58cSKevin Wolf if (offset & 0x1ff) { 1057*797ac58cSKevin Wolf printf("offset %lld is not sector aligned\n", 1058*797ac58cSKevin Wolf (long long)offset); 1059*797ac58cSKevin Wolf goto out; 1060*797ac58cSKevin Wolf } 1061*797ac58cSKevin Wolf 1062*797ac58cSKevin Wolf if (i == 0) { 1063*797ac58cSKevin Wolf first_offset = offset; 1064*797ac58cSKevin Wolf } 1065*797ac58cSKevin Wolf 1066*797ac58cSKevin Wolf /* Read lengths for qiov entries */ 1067*797ac58cSKevin Wolf for (j = optind; j < argc; j++) { 1068*797ac58cSKevin Wolf if (!strcmp(argv[j], ";")) { 1069*797ac58cSKevin Wolf break; 1070*797ac58cSKevin Wolf } 1071*797ac58cSKevin Wolf } 1072*797ac58cSKevin Wolf 1073*797ac58cSKevin Wolf nr_iov = j - optind; 1074*797ac58cSKevin Wolf 1075*797ac58cSKevin Wolf /* Build request */ 1076*797ac58cSKevin Wolf buf[i] = create_iovec(bs, &qiovs[i], &argv[optind], nr_iov, pattern); 1077*797ac58cSKevin Wolf if (buf[i] == NULL) { 1078*797ac58cSKevin Wolf goto out; 1079*797ac58cSKevin Wolf } 1080*797ac58cSKevin Wolf 1081*797ac58cSKevin Wolf reqs[i].qiov = &qiovs[i]; 1082*797ac58cSKevin Wolf reqs[i].sector = offset >> 9; 1083*797ac58cSKevin Wolf reqs[i].nb_sectors = reqs[i].qiov->size >> 9; 1084*797ac58cSKevin Wolf 1085*797ac58cSKevin Wolf optind = j + 1; 1086*797ac58cSKevin Wolf 1087*797ac58cSKevin Wolf pattern++; 1088*797ac58cSKevin Wolf } 1089*797ac58cSKevin Wolf 1090*797ac58cSKevin Wolf /* If there were empty requests at the end, ignore them */ 1091*797ac58cSKevin Wolf nr_reqs = i; 1092*797ac58cSKevin Wolf 1093*797ac58cSKevin Wolf gettimeofday(&t1, NULL); 1094*797ac58cSKevin Wolf cnt = do_aio_multiwrite(bs, reqs, nr_reqs, &total); 1095*797ac58cSKevin Wolf gettimeofday(&t2, NULL); 1096*797ac58cSKevin Wolf 1097*797ac58cSKevin Wolf if (cnt < 0) { 1098*797ac58cSKevin Wolf printf("aio_multiwrite failed: %s\n", strerror(-cnt)); 1099*797ac58cSKevin Wolf goto out; 1100*797ac58cSKevin Wolf } 1101*797ac58cSKevin Wolf 1102*797ac58cSKevin Wolf if (qflag) { 1103*797ac58cSKevin Wolf goto out; 1104*797ac58cSKevin Wolf } 1105*797ac58cSKevin Wolf 1106*797ac58cSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 1107*797ac58cSKevin Wolf t2 = tsub(t2, t1); 1108*797ac58cSKevin Wolf print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); 1109*797ac58cSKevin Wolf out: 1110*797ac58cSKevin Wolf for (i = 0; i < nr_reqs; i++) { 1111*797ac58cSKevin Wolf qemu_io_free(buf[i]); 1112*797ac58cSKevin Wolf if (reqs[i].qiov != NULL) { 1113*797ac58cSKevin Wolf qemu_iovec_destroy(&qiovs[i]); 1114*797ac58cSKevin Wolf } 1115*797ac58cSKevin Wolf } 1116*797ac58cSKevin Wolf g_free(buf); 1117*797ac58cSKevin Wolf g_free(reqs); 1118*797ac58cSKevin Wolf g_free(qiovs); 1119*797ac58cSKevin Wolf return 0; 1120*797ac58cSKevin Wolf } 1121*797ac58cSKevin Wolf 1122*797ac58cSKevin Wolf struct aio_ctx { 1123*797ac58cSKevin Wolf QEMUIOVector qiov; 1124*797ac58cSKevin Wolf int64_t offset; 1125*797ac58cSKevin Wolf char *buf; 1126*797ac58cSKevin Wolf int qflag; 1127*797ac58cSKevin Wolf int vflag; 1128*797ac58cSKevin Wolf int Cflag; 1129*797ac58cSKevin Wolf int Pflag; 1130*797ac58cSKevin Wolf int pattern; 1131*797ac58cSKevin Wolf struct timeval t1; 1132*797ac58cSKevin Wolf }; 1133*797ac58cSKevin Wolf 1134*797ac58cSKevin Wolf static void aio_write_done(void *opaque, int ret) 1135*797ac58cSKevin Wolf { 1136*797ac58cSKevin Wolf struct aio_ctx *ctx = opaque; 1137*797ac58cSKevin Wolf struct timeval t2; 1138*797ac58cSKevin Wolf 1139*797ac58cSKevin Wolf gettimeofday(&t2, NULL); 1140*797ac58cSKevin Wolf 1141*797ac58cSKevin Wolf 1142*797ac58cSKevin Wolf if (ret < 0) { 1143*797ac58cSKevin Wolf printf("aio_write failed: %s\n", strerror(-ret)); 1144*797ac58cSKevin Wolf goto out; 1145*797ac58cSKevin Wolf } 1146*797ac58cSKevin Wolf 1147*797ac58cSKevin Wolf if (ctx->qflag) { 1148*797ac58cSKevin Wolf goto out; 1149*797ac58cSKevin Wolf } 1150*797ac58cSKevin Wolf 1151*797ac58cSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 1152*797ac58cSKevin Wolf t2 = tsub(t2, ctx->t1); 1153*797ac58cSKevin Wolf print_report("wrote", &t2, ctx->offset, ctx->qiov.size, 1154*797ac58cSKevin Wolf ctx->qiov.size, 1, ctx->Cflag); 1155*797ac58cSKevin Wolf out: 1156*797ac58cSKevin Wolf qemu_io_free(ctx->buf); 1157*797ac58cSKevin Wolf qemu_iovec_destroy(&ctx->qiov); 1158*797ac58cSKevin Wolf g_free(ctx); 1159*797ac58cSKevin Wolf } 1160*797ac58cSKevin Wolf 1161*797ac58cSKevin Wolf static void aio_read_done(void *opaque, int ret) 1162*797ac58cSKevin Wolf { 1163*797ac58cSKevin Wolf struct aio_ctx *ctx = opaque; 1164*797ac58cSKevin Wolf struct timeval t2; 1165*797ac58cSKevin Wolf 1166*797ac58cSKevin Wolf gettimeofday(&t2, NULL); 1167*797ac58cSKevin Wolf 1168*797ac58cSKevin Wolf if (ret < 0) { 1169*797ac58cSKevin Wolf printf("readv failed: %s\n", strerror(-ret)); 1170*797ac58cSKevin Wolf goto out; 1171*797ac58cSKevin Wolf } 1172*797ac58cSKevin Wolf 1173*797ac58cSKevin Wolf if (ctx->Pflag) { 1174*797ac58cSKevin Wolf void *cmp_buf = g_malloc(ctx->qiov.size); 1175*797ac58cSKevin Wolf 1176*797ac58cSKevin Wolf memset(cmp_buf, ctx->pattern, ctx->qiov.size); 1177*797ac58cSKevin Wolf if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { 1178*797ac58cSKevin Wolf printf("Pattern verification failed at offset %" 1179*797ac58cSKevin Wolf PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size); 1180*797ac58cSKevin Wolf } 1181*797ac58cSKevin Wolf g_free(cmp_buf); 1182*797ac58cSKevin Wolf } 1183*797ac58cSKevin Wolf 1184*797ac58cSKevin Wolf if (ctx->qflag) { 1185*797ac58cSKevin Wolf goto out; 1186*797ac58cSKevin Wolf } 1187*797ac58cSKevin Wolf 1188*797ac58cSKevin Wolf if (ctx->vflag) { 1189*797ac58cSKevin Wolf dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); 1190*797ac58cSKevin Wolf } 1191*797ac58cSKevin Wolf 1192*797ac58cSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 1193*797ac58cSKevin Wolf t2 = tsub(t2, ctx->t1); 1194*797ac58cSKevin Wolf print_report("read", &t2, ctx->offset, ctx->qiov.size, 1195*797ac58cSKevin Wolf ctx->qiov.size, 1, ctx->Cflag); 1196*797ac58cSKevin Wolf out: 1197*797ac58cSKevin Wolf qemu_io_free(ctx->buf); 1198*797ac58cSKevin Wolf qemu_iovec_destroy(&ctx->qiov); 1199*797ac58cSKevin Wolf g_free(ctx); 1200*797ac58cSKevin Wolf } 1201*797ac58cSKevin Wolf 1202*797ac58cSKevin Wolf static void aio_read_help(void) 1203*797ac58cSKevin Wolf { 1204*797ac58cSKevin Wolf printf( 1205*797ac58cSKevin Wolf "\n" 1206*797ac58cSKevin Wolf " asynchronously reads a range of bytes from the given offset\n" 1207*797ac58cSKevin Wolf "\n" 1208*797ac58cSKevin Wolf " Example:\n" 1209*797ac58cSKevin Wolf " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n" 1210*797ac58cSKevin Wolf "\n" 1211*797ac58cSKevin Wolf " Reads a segment of the currently open file, optionally dumping it to the\n" 1212*797ac58cSKevin Wolf " standard output stream (with -v option) for subsequent inspection.\n" 1213*797ac58cSKevin Wolf " The read is performed asynchronously and the aio_flush command must be\n" 1214*797ac58cSKevin Wolf " used to ensure all outstanding aio requests have been completed.\n" 1215*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 1216*797ac58cSKevin Wolf " -P, -- use a pattern to verify read data\n" 1217*797ac58cSKevin Wolf " -v, -- dump buffer to standard output\n" 1218*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 1219*797ac58cSKevin Wolf "\n"); 1220*797ac58cSKevin Wolf } 1221*797ac58cSKevin Wolf 1222*797ac58cSKevin Wolf static int aio_read_f(BlockDriverState *bs, int argc, char **argv); 1223*797ac58cSKevin Wolf 1224*797ac58cSKevin Wolf static const cmdinfo_t aio_read_cmd = { 1225*797ac58cSKevin Wolf .name = "aio_read", 1226*797ac58cSKevin Wolf .cfunc = aio_read_f, 1227*797ac58cSKevin Wolf .argmin = 2, 1228*797ac58cSKevin Wolf .argmax = -1, 1229*797ac58cSKevin Wolf .args = "[-Cqv] [-P pattern ] off len [len..]", 1230*797ac58cSKevin Wolf .oneline = "asynchronously reads a number of bytes", 1231*797ac58cSKevin Wolf .help = aio_read_help, 1232*797ac58cSKevin Wolf }; 1233*797ac58cSKevin Wolf 1234*797ac58cSKevin Wolf static int aio_read_f(BlockDriverState *bs, int argc, char **argv) 1235*797ac58cSKevin Wolf { 1236*797ac58cSKevin Wolf int nr_iov, c; 1237*797ac58cSKevin Wolf struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1238*797ac58cSKevin Wolf 1239*797ac58cSKevin Wolf while ((c = getopt(argc, argv, "CP:qv")) != EOF) { 1240*797ac58cSKevin Wolf switch (c) { 1241*797ac58cSKevin Wolf case 'C': 1242*797ac58cSKevin Wolf ctx->Cflag = 1; 1243*797ac58cSKevin Wolf break; 1244*797ac58cSKevin Wolf case 'P': 1245*797ac58cSKevin Wolf ctx->Pflag = 1; 1246*797ac58cSKevin Wolf ctx->pattern = parse_pattern(optarg); 1247*797ac58cSKevin Wolf if (ctx->pattern < 0) { 1248*797ac58cSKevin Wolf g_free(ctx); 1249*797ac58cSKevin Wolf return 0; 1250*797ac58cSKevin Wolf } 1251*797ac58cSKevin Wolf break; 1252*797ac58cSKevin Wolf case 'q': 1253*797ac58cSKevin Wolf ctx->qflag = 1; 1254*797ac58cSKevin Wolf break; 1255*797ac58cSKevin Wolf case 'v': 1256*797ac58cSKevin Wolf ctx->vflag = 1; 1257*797ac58cSKevin Wolf break; 1258*797ac58cSKevin Wolf default: 1259*797ac58cSKevin Wolf g_free(ctx); 1260*797ac58cSKevin Wolf return command_usage(&aio_read_cmd); 1261*797ac58cSKevin Wolf } 1262*797ac58cSKevin Wolf } 1263*797ac58cSKevin Wolf 1264*797ac58cSKevin Wolf if (optind > argc - 2) { 1265*797ac58cSKevin Wolf g_free(ctx); 1266*797ac58cSKevin Wolf return command_usage(&aio_read_cmd); 1267*797ac58cSKevin Wolf } 1268*797ac58cSKevin Wolf 1269*797ac58cSKevin Wolf ctx->offset = cvtnum(argv[optind]); 1270*797ac58cSKevin Wolf if (ctx->offset < 0) { 1271*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 1272*797ac58cSKevin Wolf g_free(ctx); 1273*797ac58cSKevin Wolf return 0; 1274*797ac58cSKevin Wolf } 1275*797ac58cSKevin Wolf optind++; 1276*797ac58cSKevin Wolf 1277*797ac58cSKevin Wolf if (ctx->offset & 0x1ff) { 1278*797ac58cSKevin Wolf printf("offset %" PRId64 " is not sector aligned\n", 1279*797ac58cSKevin Wolf ctx->offset); 1280*797ac58cSKevin Wolf g_free(ctx); 1281*797ac58cSKevin Wolf return 0; 1282*797ac58cSKevin Wolf } 1283*797ac58cSKevin Wolf 1284*797ac58cSKevin Wolf nr_iov = argc - optind; 1285*797ac58cSKevin Wolf ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, 0xab); 1286*797ac58cSKevin Wolf if (ctx->buf == NULL) { 1287*797ac58cSKevin Wolf g_free(ctx); 1288*797ac58cSKevin Wolf return 0; 1289*797ac58cSKevin Wolf } 1290*797ac58cSKevin Wolf 1291*797ac58cSKevin Wolf gettimeofday(&ctx->t1, NULL); 1292*797ac58cSKevin Wolf bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, 1293*797ac58cSKevin Wolf ctx->qiov.size >> 9, aio_read_done, ctx); 1294*797ac58cSKevin Wolf return 0; 1295*797ac58cSKevin Wolf } 1296*797ac58cSKevin Wolf 1297*797ac58cSKevin Wolf static void aio_write_help(void) 1298*797ac58cSKevin Wolf { 1299*797ac58cSKevin Wolf printf( 1300*797ac58cSKevin Wolf "\n" 1301*797ac58cSKevin Wolf " asynchronously writes a range of bytes from the given offset source\n" 1302*797ac58cSKevin Wolf " from multiple buffers\n" 1303*797ac58cSKevin Wolf "\n" 1304*797ac58cSKevin Wolf " Example:\n" 1305*797ac58cSKevin Wolf " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n" 1306*797ac58cSKevin Wolf "\n" 1307*797ac58cSKevin Wolf " Writes into a segment of the currently open file, using a buffer\n" 1308*797ac58cSKevin Wolf " filled with a set pattern (0xcdcdcdcd).\n" 1309*797ac58cSKevin Wolf " The write is performed asynchronously and the aio_flush command must be\n" 1310*797ac58cSKevin Wolf " used to ensure all outstanding aio requests have been completed.\n" 1311*797ac58cSKevin Wolf " -P, -- use different pattern to fill file\n" 1312*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 1313*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 1314*797ac58cSKevin Wolf "\n"); 1315*797ac58cSKevin Wolf } 1316*797ac58cSKevin Wolf 1317*797ac58cSKevin Wolf static int aio_write_f(BlockDriverState *bs, int argc, char **argv); 1318*797ac58cSKevin Wolf 1319*797ac58cSKevin Wolf static const cmdinfo_t aio_write_cmd = { 1320*797ac58cSKevin Wolf .name = "aio_write", 1321*797ac58cSKevin Wolf .cfunc = aio_write_f, 1322*797ac58cSKevin Wolf .argmin = 2, 1323*797ac58cSKevin Wolf .argmax = -1, 1324*797ac58cSKevin Wolf .args = "[-Cq] [-P pattern ] off len [len..]", 1325*797ac58cSKevin Wolf .oneline = "asynchronously writes a number of bytes", 1326*797ac58cSKevin Wolf .help = aio_write_help, 1327*797ac58cSKevin Wolf }; 1328*797ac58cSKevin Wolf 1329*797ac58cSKevin Wolf static int aio_write_f(BlockDriverState *bs, int argc, char **argv) 1330*797ac58cSKevin Wolf { 1331*797ac58cSKevin Wolf int nr_iov, c; 1332*797ac58cSKevin Wolf int pattern = 0xcd; 1333*797ac58cSKevin Wolf struct aio_ctx *ctx = g_new0(struct aio_ctx, 1); 1334*797ac58cSKevin Wolf 1335*797ac58cSKevin Wolf while ((c = getopt(argc, argv, "CqP:")) != EOF) { 1336*797ac58cSKevin Wolf switch (c) { 1337*797ac58cSKevin Wolf case 'C': 1338*797ac58cSKevin Wolf ctx->Cflag = 1; 1339*797ac58cSKevin Wolf break; 1340*797ac58cSKevin Wolf case 'q': 1341*797ac58cSKevin Wolf ctx->qflag = 1; 1342*797ac58cSKevin Wolf break; 1343*797ac58cSKevin Wolf case 'P': 1344*797ac58cSKevin Wolf pattern = parse_pattern(optarg); 1345*797ac58cSKevin Wolf if (pattern < 0) { 1346*797ac58cSKevin Wolf g_free(ctx); 1347*797ac58cSKevin Wolf return 0; 1348*797ac58cSKevin Wolf } 1349*797ac58cSKevin Wolf break; 1350*797ac58cSKevin Wolf default: 1351*797ac58cSKevin Wolf g_free(ctx); 1352*797ac58cSKevin Wolf return command_usage(&aio_write_cmd); 1353*797ac58cSKevin Wolf } 1354*797ac58cSKevin Wolf } 1355*797ac58cSKevin Wolf 1356*797ac58cSKevin Wolf if (optind > argc - 2) { 1357*797ac58cSKevin Wolf g_free(ctx); 1358*797ac58cSKevin Wolf return command_usage(&aio_write_cmd); 1359*797ac58cSKevin Wolf } 1360*797ac58cSKevin Wolf 1361*797ac58cSKevin Wolf ctx->offset = cvtnum(argv[optind]); 1362*797ac58cSKevin Wolf if (ctx->offset < 0) { 1363*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 1364*797ac58cSKevin Wolf g_free(ctx); 1365*797ac58cSKevin Wolf return 0; 1366*797ac58cSKevin Wolf } 1367*797ac58cSKevin Wolf optind++; 1368*797ac58cSKevin Wolf 1369*797ac58cSKevin Wolf if (ctx->offset & 0x1ff) { 1370*797ac58cSKevin Wolf printf("offset %" PRId64 " is not sector aligned\n", 1371*797ac58cSKevin Wolf ctx->offset); 1372*797ac58cSKevin Wolf g_free(ctx); 1373*797ac58cSKevin Wolf return 0; 1374*797ac58cSKevin Wolf } 1375*797ac58cSKevin Wolf 1376*797ac58cSKevin Wolf nr_iov = argc - optind; 1377*797ac58cSKevin Wolf ctx->buf = create_iovec(bs, &ctx->qiov, &argv[optind], nr_iov, pattern); 1378*797ac58cSKevin Wolf if (ctx->buf == NULL) { 1379*797ac58cSKevin Wolf g_free(ctx); 1380*797ac58cSKevin Wolf return 0; 1381*797ac58cSKevin Wolf } 1382*797ac58cSKevin Wolf 1383*797ac58cSKevin Wolf gettimeofday(&ctx->t1, NULL); 1384*797ac58cSKevin Wolf bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, 1385*797ac58cSKevin Wolf ctx->qiov.size >> 9, aio_write_done, ctx); 1386*797ac58cSKevin Wolf return 0; 1387*797ac58cSKevin Wolf } 1388*797ac58cSKevin Wolf 1389*797ac58cSKevin Wolf static int aio_flush_f(BlockDriverState *bs, int argc, char **argv) 1390*797ac58cSKevin Wolf { 1391*797ac58cSKevin Wolf bdrv_drain_all(); 1392*797ac58cSKevin Wolf return 0; 1393*797ac58cSKevin Wolf } 1394*797ac58cSKevin Wolf 1395*797ac58cSKevin Wolf static const cmdinfo_t aio_flush_cmd = { 1396*797ac58cSKevin Wolf .name = "aio_flush", 1397*797ac58cSKevin Wolf .cfunc = aio_flush_f, 1398*797ac58cSKevin Wolf .oneline = "completes all outstanding aio requests" 1399*797ac58cSKevin Wolf }; 1400*797ac58cSKevin Wolf 1401*797ac58cSKevin Wolf static int flush_f(BlockDriverState *bs, int argc, char **argv) 1402*797ac58cSKevin Wolf { 1403*797ac58cSKevin Wolf bdrv_flush(bs); 1404*797ac58cSKevin Wolf return 0; 1405*797ac58cSKevin Wolf } 1406*797ac58cSKevin Wolf 1407*797ac58cSKevin Wolf static const cmdinfo_t flush_cmd = { 1408*797ac58cSKevin Wolf .name = "flush", 1409*797ac58cSKevin Wolf .altname = "f", 1410*797ac58cSKevin Wolf .cfunc = flush_f, 1411*797ac58cSKevin Wolf .oneline = "flush all in-core file state to disk", 1412*797ac58cSKevin Wolf }; 1413*797ac58cSKevin Wolf 1414*797ac58cSKevin Wolf static int truncate_f(BlockDriverState *bs, int argc, char **argv) 1415*797ac58cSKevin Wolf { 1416*797ac58cSKevin Wolf int64_t offset; 1417*797ac58cSKevin Wolf int ret; 1418*797ac58cSKevin Wolf 1419*797ac58cSKevin Wolf offset = cvtnum(argv[1]); 1420*797ac58cSKevin Wolf if (offset < 0) { 1421*797ac58cSKevin Wolf printf("non-numeric truncate argument -- %s\n", argv[1]); 1422*797ac58cSKevin Wolf return 0; 1423*797ac58cSKevin Wolf } 1424*797ac58cSKevin Wolf 1425*797ac58cSKevin Wolf ret = bdrv_truncate(bs, offset); 1426*797ac58cSKevin Wolf if (ret < 0) { 1427*797ac58cSKevin Wolf printf("truncate: %s\n", strerror(-ret)); 1428*797ac58cSKevin Wolf return 0; 1429*797ac58cSKevin Wolf } 1430*797ac58cSKevin Wolf 1431*797ac58cSKevin Wolf return 0; 1432*797ac58cSKevin Wolf } 1433*797ac58cSKevin Wolf 1434*797ac58cSKevin Wolf static const cmdinfo_t truncate_cmd = { 1435*797ac58cSKevin Wolf .name = "truncate", 1436*797ac58cSKevin Wolf .altname = "t", 1437*797ac58cSKevin Wolf .cfunc = truncate_f, 1438*797ac58cSKevin Wolf .argmin = 1, 1439*797ac58cSKevin Wolf .argmax = 1, 1440*797ac58cSKevin Wolf .args = "off", 1441*797ac58cSKevin Wolf .oneline = "truncates the current file at the given offset", 1442*797ac58cSKevin Wolf }; 1443*797ac58cSKevin Wolf 1444*797ac58cSKevin Wolf static int length_f(BlockDriverState *bs, int argc, char **argv) 1445*797ac58cSKevin Wolf { 1446*797ac58cSKevin Wolf int64_t size; 1447*797ac58cSKevin Wolf char s1[64]; 1448*797ac58cSKevin Wolf 1449*797ac58cSKevin Wolf size = bdrv_getlength(bs); 1450*797ac58cSKevin Wolf if (size < 0) { 1451*797ac58cSKevin Wolf printf("getlength: %s\n", strerror(-size)); 1452*797ac58cSKevin Wolf return 0; 1453*797ac58cSKevin Wolf } 1454*797ac58cSKevin Wolf 1455*797ac58cSKevin Wolf cvtstr(size, s1, sizeof(s1)); 1456*797ac58cSKevin Wolf printf("%s\n", s1); 1457*797ac58cSKevin Wolf return 0; 1458*797ac58cSKevin Wolf } 1459*797ac58cSKevin Wolf 1460*797ac58cSKevin Wolf 1461*797ac58cSKevin Wolf static const cmdinfo_t length_cmd = { 1462*797ac58cSKevin Wolf .name = "length", 1463*797ac58cSKevin Wolf .altname = "l", 1464*797ac58cSKevin Wolf .cfunc = length_f, 1465*797ac58cSKevin Wolf .oneline = "gets the length of the current file", 1466*797ac58cSKevin Wolf }; 1467*797ac58cSKevin Wolf 1468*797ac58cSKevin Wolf 1469*797ac58cSKevin Wolf static int info_f(BlockDriverState *bs, int argc, char **argv) 1470*797ac58cSKevin Wolf { 1471*797ac58cSKevin Wolf BlockDriverInfo bdi; 1472*797ac58cSKevin Wolf char s1[64], s2[64]; 1473*797ac58cSKevin Wolf int ret; 1474*797ac58cSKevin Wolf 1475*797ac58cSKevin Wolf if (bs->drv && bs->drv->format_name) { 1476*797ac58cSKevin Wolf printf("format name: %s\n", bs->drv->format_name); 1477*797ac58cSKevin Wolf } 1478*797ac58cSKevin Wolf if (bs->drv && bs->drv->protocol_name) { 1479*797ac58cSKevin Wolf printf("format name: %s\n", bs->drv->protocol_name); 1480*797ac58cSKevin Wolf } 1481*797ac58cSKevin Wolf 1482*797ac58cSKevin Wolf ret = bdrv_get_info(bs, &bdi); 1483*797ac58cSKevin Wolf if (ret) { 1484*797ac58cSKevin Wolf return 0; 1485*797ac58cSKevin Wolf } 1486*797ac58cSKevin Wolf 1487*797ac58cSKevin Wolf cvtstr(bdi.cluster_size, s1, sizeof(s1)); 1488*797ac58cSKevin Wolf cvtstr(bdi.vm_state_offset, s2, sizeof(s2)); 1489*797ac58cSKevin Wolf 1490*797ac58cSKevin Wolf printf("cluster size: %s\n", s1); 1491*797ac58cSKevin Wolf printf("vm state offset: %s\n", s2); 1492*797ac58cSKevin Wolf 1493*797ac58cSKevin Wolf return 0; 1494*797ac58cSKevin Wolf } 1495*797ac58cSKevin Wolf 1496*797ac58cSKevin Wolf 1497*797ac58cSKevin Wolf 1498*797ac58cSKevin Wolf static const cmdinfo_t info_cmd = { 1499*797ac58cSKevin Wolf .name = "info", 1500*797ac58cSKevin Wolf .altname = "i", 1501*797ac58cSKevin Wolf .cfunc = info_f, 1502*797ac58cSKevin Wolf .oneline = "prints information about the current file", 1503*797ac58cSKevin Wolf }; 1504*797ac58cSKevin Wolf 1505*797ac58cSKevin Wolf static void discard_help(void) 1506*797ac58cSKevin Wolf { 1507*797ac58cSKevin Wolf printf( 1508*797ac58cSKevin Wolf "\n" 1509*797ac58cSKevin Wolf " discards a range of bytes from the given offset\n" 1510*797ac58cSKevin Wolf "\n" 1511*797ac58cSKevin Wolf " Example:\n" 1512*797ac58cSKevin Wolf " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n" 1513*797ac58cSKevin Wolf "\n" 1514*797ac58cSKevin Wolf " Discards a segment of the currently open file.\n" 1515*797ac58cSKevin Wolf " -C, -- report statistics in a machine parsable format\n" 1516*797ac58cSKevin Wolf " -q, -- quiet mode, do not show I/O statistics\n" 1517*797ac58cSKevin Wolf "\n"); 1518*797ac58cSKevin Wolf } 1519*797ac58cSKevin Wolf 1520*797ac58cSKevin Wolf static int discard_f(BlockDriverState *bs, int argc, char **argv); 1521*797ac58cSKevin Wolf 1522*797ac58cSKevin Wolf static const cmdinfo_t discard_cmd = { 1523*797ac58cSKevin Wolf .name = "discard", 1524*797ac58cSKevin Wolf .altname = "d", 1525*797ac58cSKevin Wolf .cfunc = discard_f, 1526*797ac58cSKevin Wolf .argmin = 2, 1527*797ac58cSKevin Wolf .argmax = -1, 1528*797ac58cSKevin Wolf .args = "[-Cq] off len", 1529*797ac58cSKevin Wolf .oneline = "discards a number of bytes at a specified offset", 1530*797ac58cSKevin Wolf .help = discard_help, 1531*797ac58cSKevin Wolf }; 1532*797ac58cSKevin Wolf 1533*797ac58cSKevin Wolf static int discard_f(BlockDriverState *bs, int argc, char **argv) 1534*797ac58cSKevin Wolf { 1535*797ac58cSKevin Wolf struct timeval t1, t2; 1536*797ac58cSKevin Wolf int Cflag = 0, qflag = 0; 1537*797ac58cSKevin Wolf int c, ret; 1538*797ac58cSKevin Wolf int64_t offset; 1539*797ac58cSKevin Wolf int count; 1540*797ac58cSKevin Wolf 1541*797ac58cSKevin Wolf while ((c = getopt(argc, argv, "Cq")) != EOF) { 1542*797ac58cSKevin Wolf switch (c) { 1543*797ac58cSKevin Wolf case 'C': 1544*797ac58cSKevin Wolf Cflag = 1; 1545*797ac58cSKevin Wolf break; 1546*797ac58cSKevin Wolf case 'q': 1547*797ac58cSKevin Wolf qflag = 1; 1548*797ac58cSKevin Wolf break; 1549*797ac58cSKevin Wolf default: 1550*797ac58cSKevin Wolf return command_usage(&discard_cmd); 1551*797ac58cSKevin Wolf } 1552*797ac58cSKevin Wolf } 1553*797ac58cSKevin Wolf 1554*797ac58cSKevin Wolf if (optind != argc - 2) { 1555*797ac58cSKevin Wolf return command_usage(&discard_cmd); 1556*797ac58cSKevin Wolf } 1557*797ac58cSKevin Wolf 1558*797ac58cSKevin Wolf offset = cvtnum(argv[optind]); 1559*797ac58cSKevin Wolf if (offset < 0) { 1560*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 1561*797ac58cSKevin Wolf return 0; 1562*797ac58cSKevin Wolf } 1563*797ac58cSKevin Wolf 1564*797ac58cSKevin Wolf optind++; 1565*797ac58cSKevin Wolf count = cvtnum(argv[optind]); 1566*797ac58cSKevin Wolf if (count < 0) { 1567*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[optind]); 1568*797ac58cSKevin Wolf return 0; 1569*797ac58cSKevin Wolf } 1570*797ac58cSKevin Wolf 1571*797ac58cSKevin Wolf gettimeofday(&t1, NULL); 1572*797ac58cSKevin Wolf ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, 1573*797ac58cSKevin Wolf count >> BDRV_SECTOR_BITS); 1574*797ac58cSKevin Wolf gettimeofday(&t2, NULL); 1575*797ac58cSKevin Wolf 1576*797ac58cSKevin Wolf if (ret < 0) { 1577*797ac58cSKevin Wolf printf("discard failed: %s\n", strerror(-ret)); 1578*797ac58cSKevin Wolf goto out; 1579*797ac58cSKevin Wolf } 1580*797ac58cSKevin Wolf 1581*797ac58cSKevin Wolf /* Finally, report back -- -C gives a parsable format */ 1582*797ac58cSKevin Wolf if (!qflag) { 1583*797ac58cSKevin Wolf t2 = tsub(t2, t1); 1584*797ac58cSKevin Wolf print_report("discard", &t2, offset, count, count, 1, Cflag); 1585*797ac58cSKevin Wolf } 1586*797ac58cSKevin Wolf 1587*797ac58cSKevin Wolf out: 1588*797ac58cSKevin Wolf return 0; 1589*797ac58cSKevin Wolf } 1590*797ac58cSKevin Wolf 1591*797ac58cSKevin Wolf static int alloc_f(BlockDriverState *bs, int argc, char **argv) 1592*797ac58cSKevin Wolf { 1593*797ac58cSKevin Wolf int64_t offset, sector_num; 1594*797ac58cSKevin Wolf int nb_sectors, remaining; 1595*797ac58cSKevin Wolf char s1[64]; 1596*797ac58cSKevin Wolf int num, sum_alloc; 1597*797ac58cSKevin Wolf int ret; 1598*797ac58cSKevin Wolf 1599*797ac58cSKevin Wolf offset = cvtnum(argv[1]); 1600*797ac58cSKevin Wolf if (offset < 0) { 1601*797ac58cSKevin Wolf printf("non-numeric offset argument -- %s\n", argv[1]); 1602*797ac58cSKevin Wolf return 0; 1603*797ac58cSKevin Wolf } else if (offset & 0x1ff) { 1604*797ac58cSKevin Wolf printf("offset %" PRId64 " is not sector aligned\n", 1605*797ac58cSKevin Wolf offset); 1606*797ac58cSKevin Wolf return 0; 1607*797ac58cSKevin Wolf } 1608*797ac58cSKevin Wolf 1609*797ac58cSKevin Wolf if (argc == 3) { 1610*797ac58cSKevin Wolf nb_sectors = cvtnum(argv[2]); 1611*797ac58cSKevin Wolf if (nb_sectors < 0) { 1612*797ac58cSKevin Wolf printf("non-numeric length argument -- %s\n", argv[2]); 1613*797ac58cSKevin Wolf return 0; 1614*797ac58cSKevin Wolf } 1615*797ac58cSKevin Wolf } else { 1616*797ac58cSKevin Wolf nb_sectors = 1; 1617*797ac58cSKevin Wolf } 1618*797ac58cSKevin Wolf 1619*797ac58cSKevin Wolf remaining = nb_sectors; 1620*797ac58cSKevin Wolf sum_alloc = 0; 1621*797ac58cSKevin Wolf sector_num = offset >> 9; 1622*797ac58cSKevin Wolf while (remaining) { 1623*797ac58cSKevin Wolf ret = bdrv_is_allocated(bs, sector_num, remaining, &num); 1624*797ac58cSKevin Wolf sector_num += num; 1625*797ac58cSKevin Wolf remaining -= num; 1626*797ac58cSKevin Wolf if (ret) { 1627*797ac58cSKevin Wolf sum_alloc += num; 1628*797ac58cSKevin Wolf } 1629*797ac58cSKevin Wolf if (num == 0) { 1630*797ac58cSKevin Wolf nb_sectors -= remaining; 1631*797ac58cSKevin Wolf remaining = 0; 1632*797ac58cSKevin Wolf } 1633*797ac58cSKevin Wolf } 1634*797ac58cSKevin Wolf 1635*797ac58cSKevin Wolf cvtstr(offset, s1, sizeof(s1)); 1636*797ac58cSKevin Wolf 1637*797ac58cSKevin Wolf printf("%d/%d sectors allocated at offset %s\n", 1638*797ac58cSKevin Wolf sum_alloc, nb_sectors, s1); 1639*797ac58cSKevin Wolf return 0; 1640*797ac58cSKevin Wolf } 1641*797ac58cSKevin Wolf 1642*797ac58cSKevin Wolf static const cmdinfo_t alloc_cmd = { 1643*797ac58cSKevin Wolf .name = "alloc", 1644*797ac58cSKevin Wolf .altname = "a", 1645*797ac58cSKevin Wolf .argmin = 1, 1646*797ac58cSKevin Wolf .argmax = 2, 1647*797ac58cSKevin Wolf .cfunc = alloc_f, 1648*797ac58cSKevin Wolf .args = "off [sectors]", 1649*797ac58cSKevin Wolf .oneline = "checks if a sector is present in the file", 1650*797ac58cSKevin Wolf }; 1651*797ac58cSKevin Wolf 1652*797ac58cSKevin Wolf 1653*797ac58cSKevin Wolf static int map_is_allocated(BlockDriverState *bs, int64_t sector_num, 1654*797ac58cSKevin Wolf int64_t nb_sectors, int64_t *pnum) 1655*797ac58cSKevin Wolf { 1656*797ac58cSKevin Wolf int num, num_checked; 1657*797ac58cSKevin Wolf int ret, firstret; 1658*797ac58cSKevin Wolf 1659*797ac58cSKevin Wolf num_checked = MIN(nb_sectors, INT_MAX); 1660*797ac58cSKevin Wolf ret = bdrv_is_allocated(bs, sector_num, num_checked, &num); 1661*797ac58cSKevin Wolf if (ret < 0) { 1662*797ac58cSKevin Wolf return ret; 1663*797ac58cSKevin Wolf } 1664*797ac58cSKevin Wolf 1665*797ac58cSKevin Wolf firstret = ret; 1666*797ac58cSKevin Wolf *pnum = num; 1667*797ac58cSKevin Wolf 1668*797ac58cSKevin Wolf while (nb_sectors > 0 && ret == firstret) { 1669*797ac58cSKevin Wolf sector_num += num; 1670*797ac58cSKevin Wolf nb_sectors -= num; 1671*797ac58cSKevin Wolf 1672*797ac58cSKevin Wolf num_checked = MIN(nb_sectors, INT_MAX); 1673*797ac58cSKevin Wolf ret = bdrv_is_allocated(bs, sector_num, num_checked, &num); 1674*797ac58cSKevin Wolf if (ret == firstret) { 1675*797ac58cSKevin Wolf *pnum += num; 1676*797ac58cSKevin Wolf } else { 1677*797ac58cSKevin Wolf break; 1678*797ac58cSKevin Wolf } 1679*797ac58cSKevin Wolf } 1680*797ac58cSKevin Wolf 1681*797ac58cSKevin Wolf return firstret; 1682*797ac58cSKevin Wolf } 1683*797ac58cSKevin Wolf 1684*797ac58cSKevin Wolf static int map_f(BlockDriverState *bs, int argc, char **argv) 1685*797ac58cSKevin Wolf { 1686*797ac58cSKevin Wolf int64_t offset; 1687*797ac58cSKevin Wolf int64_t nb_sectors; 1688*797ac58cSKevin Wolf char s1[64]; 1689*797ac58cSKevin Wolf int64_t num; 1690*797ac58cSKevin Wolf int ret; 1691*797ac58cSKevin Wolf const char *retstr; 1692*797ac58cSKevin Wolf 1693*797ac58cSKevin Wolf offset = 0; 1694*797ac58cSKevin Wolf nb_sectors = bs->total_sectors; 1695*797ac58cSKevin Wolf 1696*797ac58cSKevin Wolf do { 1697*797ac58cSKevin Wolf ret = map_is_allocated(bs, offset, nb_sectors, &num); 1698*797ac58cSKevin Wolf if (ret < 0) { 1699*797ac58cSKevin Wolf error_report("Failed to get allocation status: %s", strerror(-ret)); 1700*797ac58cSKevin Wolf return 0; 1701*797ac58cSKevin Wolf } 1702*797ac58cSKevin Wolf 1703*797ac58cSKevin Wolf retstr = ret ? " allocated" : "not allocated"; 1704*797ac58cSKevin Wolf cvtstr(offset << 9ULL, s1, sizeof(s1)); 1705*797ac58cSKevin Wolf printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s " 1706*797ac58cSKevin Wolf "at offset %s (%d)\n", 1707*797ac58cSKevin Wolf offset << 9ULL, num, nb_sectors, retstr, s1, ret); 1708*797ac58cSKevin Wolf 1709*797ac58cSKevin Wolf offset += num; 1710*797ac58cSKevin Wolf nb_sectors -= num; 1711*797ac58cSKevin Wolf } while (offset < bs->total_sectors); 1712*797ac58cSKevin Wolf 1713*797ac58cSKevin Wolf return 0; 1714*797ac58cSKevin Wolf } 1715*797ac58cSKevin Wolf 1716*797ac58cSKevin Wolf static const cmdinfo_t map_cmd = { 1717*797ac58cSKevin Wolf .name = "map", 1718*797ac58cSKevin Wolf .argmin = 0, 1719*797ac58cSKevin Wolf .argmax = 0, 1720*797ac58cSKevin Wolf .cfunc = map_f, 1721*797ac58cSKevin Wolf .args = "", 1722*797ac58cSKevin Wolf .oneline = "prints the allocated areas of a file", 1723*797ac58cSKevin Wolf }; 1724*797ac58cSKevin Wolf 1725*797ac58cSKevin Wolf static int break_f(BlockDriverState *bs, int argc, char **argv) 1726*797ac58cSKevin Wolf { 1727*797ac58cSKevin Wolf int ret; 1728*797ac58cSKevin Wolf 1729*797ac58cSKevin Wolf ret = bdrv_debug_breakpoint(bs, argv[1], argv[2]); 1730*797ac58cSKevin Wolf if (ret < 0) { 1731*797ac58cSKevin Wolf printf("Could not set breakpoint: %s\n", strerror(-ret)); 1732*797ac58cSKevin Wolf } 1733*797ac58cSKevin Wolf 1734*797ac58cSKevin Wolf return 0; 1735*797ac58cSKevin Wolf } 1736*797ac58cSKevin Wolf 1737*797ac58cSKevin Wolf static const cmdinfo_t break_cmd = { 1738*797ac58cSKevin Wolf .name = "break", 1739*797ac58cSKevin Wolf .argmin = 2, 1740*797ac58cSKevin Wolf .argmax = 2, 1741*797ac58cSKevin Wolf .cfunc = break_f, 1742*797ac58cSKevin Wolf .args = "event tag", 1743*797ac58cSKevin Wolf .oneline = "sets a breakpoint on event and tags the stopped " 1744*797ac58cSKevin Wolf "request as tag", 1745*797ac58cSKevin Wolf }; 1746*797ac58cSKevin Wolf 1747*797ac58cSKevin Wolf static int resume_f(BlockDriverState *bs, int argc, char **argv) 1748*797ac58cSKevin Wolf { 1749*797ac58cSKevin Wolf int ret; 1750*797ac58cSKevin Wolf 1751*797ac58cSKevin Wolf ret = bdrv_debug_resume(bs, argv[1]); 1752*797ac58cSKevin Wolf if (ret < 0) { 1753*797ac58cSKevin Wolf printf("Could not resume request: %s\n", strerror(-ret)); 1754*797ac58cSKevin Wolf } 1755*797ac58cSKevin Wolf 1756*797ac58cSKevin Wolf return 0; 1757*797ac58cSKevin Wolf } 1758*797ac58cSKevin Wolf 1759*797ac58cSKevin Wolf static const cmdinfo_t resume_cmd = { 1760*797ac58cSKevin Wolf .name = "resume", 1761*797ac58cSKevin Wolf .argmin = 1, 1762*797ac58cSKevin Wolf .argmax = 1, 1763*797ac58cSKevin Wolf .cfunc = resume_f, 1764*797ac58cSKevin Wolf .args = "tag", 1765*797ac58cSKevin Wolf .oneline = "resumes the request tagged as tag", 1766*797ac58cSKevin Wolf }; 1767*797ac58cSKevin Wolf 1768*797ac58cSKevin Wolf static int wait_break_f(BlockDriverState *bs, int argc, char **argv) 1769*797ac58cSKevin Wolf { 1770*797ac58cSKevin Wolf while (!bdrv_debug_is_suspended(bs, argv[1])) { 1771*797ac58cSKevin Wolf qemu_aio_wait(); 1772*797ac58cSKevin Wolf } 1773*797ac58cSKevin Wolf 1774*797ac58cSKevin Wolf return 0; 1775*797ac58cSKevin Wolf } 1776*797ac58cSKevin Wolf 1777*797ac58cSKevin Wolf static const cmdinfo_t wait_break_cmd = { 1778*797ac58cSKevin Wolf .name = "wait_break", 1779*797ac58cSKevin Wolf .argmin = 1, 1780*797ac58cSKevin Wolf .argmax = 1, 1781*797ac58cSKevin Wolf .cfunc = wait_break_f, 1782*797ac58cSKevin Wolf .args = "tag", 1783*797ac58cSKevin Wolf .oneline = "waits for the suspension of a request", 1784*797ac58cSKevin Wolf }; 1785*797ac58cSKevin Wolf 1786*797ac58cSKevin Wolf static int abort_f(BlockDriverState *bs, int argc, char **argv) 1787*797ac58cSKevin Wolf { 1788*797ac58cSKevin Wolf abort(); 1789*797ac58cSKevin Wolf } 1790*797ac58cSKevin Wolf 1791*797ac58cSKevin Wolf static const cmdinfo_t abort_cmd = { 1792*797ac58cSKevin Wolf .name = "abort", 1793*797ac58cSKevin Wolf .cfunc = abort_f, 1794*797ac58cSKevin Wolf .flags = CMD_NOFILE_OK, 1795*797ac58cSKevin Wolf .oneline = "simulate a program crash using abort(3)", 1796*797ac58cSKevin Wolf }; 1797*797ac58cSKevin Wolf 1798*797ac58cSKevin Wolf static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct) 1799*797ac58cSKevin Wolf { 1800*797ac58cSKevin Wolf if (ct->flags & CMD_FLAG_GLOBAL) { 1801*797ac58cSKevin Wolf return 1; 1802*797ac58cSKevin Wolf } 1803*797ac58cSKevin Wolf if (!(ct->flags & CMD_NOFILE_OK) && !bs) { 1804*797ac58cSKevin Wolf fprintf(stderr, "no file open, try 'help open'\n"); 1805*797ac58cSKevin Wolf return 0; 1806*797ac58cSKevin Wolf } 1807*797ac58cSKevin Wolf return 1; 1808*797ac58cSKevin Wolf } 1809*797ac58cSKevin Wolf 1810*797ac58cSKevin Wolf static void __attribute((constructor)) init_qemuio_commands(void) 1811*797ac58cSKevin Wolf { 1812*797ac58cSKevin Wolf /* initialize commands */ 1813*797ac58cSKevin Wolf help_init(); 1814*797ac58cSKevin Wolf add_command(&read_cmd); 1815*797ac58cSKevin Wolf add_command(&readv_cmd); 1816*797ac58cSKevin Wolf add_command(&write_cmd); 1817*797ac58cSKevin Wolf add_command(&writev_cmd); 1818*797ac58cSKevin Wolf add_command(&multiwrite_cmd); 1819*797ac58cSKevin Wolf add_command(&aio_read_cmd); 1820*797ac58cSKevin Wolf add_command(&aio_write_cmd); 1821*797ac58cSKevin Wolf add_command(&aio_flush_cmd); 1822*797ac58cSKevin Wolf add_command(&flush_cmd); 1823*797ac58cSKevin Wolf add_command(&truncate_cmd); 1824*797ac58cSKevin Wolf add_command(&length_cmd); 1825*797ac58cSKevin Wolf add_command(&info_cmd); 1826*797ac58cSKevin Wolf add_command(&discard_cmd); 1827*797ac58cSKevin Wolf add_command(&alloc_cmd); 1828*797ac58cSKevin Wolf add_command(&map_cmd); 1829*797ac58cSKevin Wolf add_command(&break_cmd); 1830*797ac58cSKevin Wolf add_command(&resume_cmd); 1831*797ac58cSKevin Wolf add_command(&wait_break_cmd); 1832*797ac58cSKevin Wolf add_command(&abort_cmd); 1833*797ac58cSKevin Wolf 1834*797ac58cSKevin Wolf add_check_command(init_check_command); 1835*797ac58cSKevin Wolf } 1836