Annotation of qemu/qemu-io.c, revision 1.1.1.7

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

unix.superglobalmegacorp.com