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

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"
                     18: #include "block_int.h"
                     19: #include "cmd.h"
                     20: 
                     21: #define VERSION        "0.0.1"
                     22: 
                     23: #define CMD_NOFILE_OK  0x01
                     24: 
                     25: char *progname;
                     26: static BlockDriverState *bs;
                     27: 
                     28: static int misalign;
                     29: 
                     30: /*
                     31:  * Memory allocation helpers.
                     32:  *
                     33:  * Make sure memory is aligned by default, or purposefully misaligned if
                     34:  * that is specified on the command line.
                     35:  */
                     36: 
                     37: #define MISALIGN_OFFSET                16
                     38: static void *qemu_io_alloc(size_t len, int pattern)
                     39: {
                     40:        void *buf;
                     41: 
                     42:        if (misalign)
                     43:                len += MISALIGN_OFFSET;
                     44:        buf = qemu_memalign(512, len);
                     45:        memset(buf, pattern, len);
                     46:        if (misalign)
                     47:                buf += MISALIGN_OFFSET;
                     48:        return buf;
                     49: }
                     50: 
                     51: static void qemu_io_free(void *p)
                     52: {
                     53:        if (misalign)
                     54:                p -= MISALIGN_OFFSET;
                     55:        qemu_vfree(p);
                     56: }
                     57: 
                     58: static void
                     59: dump_buffer(const void *buffer, int64_t offset, int len)
                     60: {
                     61:        int i, j;
                     62:        const uint8_t *p;
                     63: 
                     64:        for (i = 0, p = buffer; i < len; i += 16) {
                     65:                const uint8_t *s = p;
                     66: 
                     67:                printf("%08llx:  ", (unsigned long long)offset + i);
                     68:                for (j = 0; j < 16 && i + j < len; j++, p++)
                     69:                        printf("%02x ", *p);
                     70:                printf(" ");
                     71:                for (j = 0; j < 16 && i + j < len; j++, s++) {
                     72:                        if (isalnum(*s))
                     73:                                printf("%c", *s);
                     74:                        else
                     75:                                printf(".");
                     76:                }
                     77:                printf("\n");
                     78:        }
                     79: }
                     80: 
                     81: static void
                     82: print_report(const char *op, struct timeval *t, int64_t offset,
                     83:                int count, int total, int cnt, int Cflag)
                     84: {
                     85:        char s1[64], s2[64], ts[64];
                     86: 
                     87:        timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
                     88:        if (!Cflag) {
                     89:                cvtstr((double)total, s1, sizeof(s1));
                     90:                cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
                     91:                printf("%s %d/%d bytes at offset %lld\n",
                     92:                        op, total, count, (long long)offset);
                     93:                printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
                     94:                        s1, cnt, ts, s2, tdiv((double)cnt, *t));
                     95:        } else {/* bytes,ops,time,bytes/sec,ops/sec */
                     96:                printf("%d,%d,%s,%.3f,%.3f\n",
                     97:                        total, cnt, ts,
                     98:                        tdiv((double)total, *t),
                     99:                        tdiv((double)cnt, *t));
                    100:        }
                    101: }
                    102: 
                    103: /*
                    104:  * Parse multiple length statements for vectored I/O, and construct an I/O
                    105:  * vector matching it.
                    106:  */
                    107: static void *
                    108: create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
                    109: {
                    110:        size_t *sizes = calloc(nr_iov, sizeof(size_t));
                    111:        size_t count = 0;
                    112:        void *buf, *p;
                    113:        int i;
                    114: 
                    115:        for (i = 0; i < nr_iov; i++) {
                    116:                char *arg = argv[i];
                    117:                long long len;
                    118: 
                    119:                len = cvtnum(arg);
                    120:                if (len < 0) {
                    121:                        printf("non-numeric length argument -- %s\n", arg);
                    122:                        return NULL;
                    123:                }
                    124: 
                    125:                /* should be SIZE_T_MAX, but that doesn't exist */
                    126:                if (len > UINT_MAX) {
                    127:                        printf("too large length argument -- %s\n", arg);
                    128:                        return NULL;
                    129:                }
                    130: 
                    131:                if (len & 0x1ff) {
                    132:                        printf("length argument %lld is not sector aligned\n",
                    133:                                len);
                    134:                        return NULL;
                    135:                }
                    136: 
                    137:                sizes[i] = len;
                    138:                count += len;
                    139:        }
                    140: 
                    141:        qemu_iovec_init(qiov, nr_iov);
                    142: 
                    143:        buf = p = qemu_io_alloc(count, pattern);
                    144: 
                    145:        for (i = 0; i < nr_iov; i++) {
                    146:                qemu_iovec_add(qiov, p, sizes[i]);
                    147:                p += sizes[i];
                    148:        }
                    149: 
                    150:        free(sizes);
                    151:        return buf;
                    152: }
                    153: 
                    154: static int do_read(char *buf, int64_t offset, int count, int *total)
                    155: {
                    156:        int ret;
                    157: 
                    158:        ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
                    159:        if (ret < 0)
                    160:                return ret;
                    161:        *total = count;
                    162:        return 1;
                    163: }
                    164: 
                    165: static int do_write(char *buf, int64_t offset, int count, int *total)
                    166: {
                    167:        int ret;
                    168: 
                    169:        ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
                    170:        if (ret < 0)
                    171:                return ret;
                    172:        *total = count;
                    173:        return 1;
                    174: }
                    175: 
                    176: static int do_pread(char *buf, int64_t offset, int count, int *total)
                    177: {
                    178:        *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
                    179:        if (*total < 0)
                    180:                return *total;
                    181:        return 1;
                    182: }
                    183: 
                    184: static int do_pwrite(char *buf, int64_t offset, int count, int *total)
                    185: {
                    186:        *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
                    187:        if (*total < 0)
                    188:                return *total;
                    189:        return 1;
                    190: }
                    191: 
                    192: static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
                    193: {
                    194:        *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
                    195:        if (*total < 0)
                    196:                return *total;
                    197:        return 1;
                    198: }
                    199: 
                    200: static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
                    201: {
                    202:        *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
                    203:        if (*total < 0)
                    204:                return *total;
                    205:        return 1;
                    206: }
                    207: 
                    208: #define NOT_DONE 0x7fffffff
                    209: static void aio_rw_done(void *opaque, int ret)
                    210: {
                    211:        *(int *)opaque = ret;
                    212: }
                    213: 
                    214: static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
                    215: {
                    216:        BlockDriverAIOCB *acb;
                    217:        int async_ret = NOT_DONE;
                    218: 
                    219:        acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
                    220:                             aio_rw_done, &async_ret);
                    221:        if (!acb)
                    222:                return -EIO;
                    223: 
                    224:        while (async_ret == NOT_DONE)
                    225:                qemu_aio_wait();
                    226: 
                    227:        *total = qiov->size;
                    228:        return async_ret < 0 ? async_ret : 1;
                    229: }
                    230: 
                    231: static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
                    232: {
                    233:        BlockDriverAIOCB *acb;
                    234:        int async_ret = NOT_DONE;
                    235: 
                    236:        acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
                    237:                              aio_rw_done, &async_ret);
                    238:        if (!acb)
                    239:                return -EIO;
                    240: 
                    241:        while (async_ret == NOT_DONE)
                    242:                qemu_aio_wait();
                    243: 
                    244:        *total = qiov->size;
                    245:        return async_ret < 0 ? async_ret : 1;
                    246: }
                    247: 
                    248: 
                    249: static const cmdinfo_t read_cmd;
                    250: 
                    251: static void
                    252: read_help(void)
                    253: {
                    254:        printf(
                    255: "\n"
                    256: " reads a range of bytes from the given offset\n"
                    257: "\n"
                    258: " Example:\n"
                    259: " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
                    260: "\n"
                    261: " Reads a segment of the currently open file, optionally dumping it to the\n"
                    262: " standard output stream (with -v option) for subsequent inspection.\n"
                    263: " -b, -- read from the VM state rather than the virtual disk\n"
                    264: " -C, -- report statistics in a machine parsable format\n"
                    265: " -l, -- length for pattern verification (only with -P)\n"
                    266: " -p, -- use bdrv_pread to read the file\n"
                    267: " -P, -- use a pattern to verify read data\n"
                    268: " -q, -- quite mode, do not show I/O statistics\n"
                    269: " -s, -- start offset for pattern verification (only with -P)\n"
                    270: " -v, -- dump buffer to standard output\n"
                    271: "\n");
                    272: }
                    273: 
                    274: static int
                    275: read_f(int argc, char **argv)
                    276: {
                    277:        struct timeval t1, t2;
                    278:        int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
                    279:        int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
                    280:        int c, cnt;
                    281:        char *buf;
                    282:        int64_t offset;
                    283:        int count;
                    284:         /* Some compilers get confused and warn if this is not initialized.  */
                    285:         int total = 0;
                    286:        int pattern = 0, pattern_offset = 0, pattern_count = 0;
                    287: 
                    288:        while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
                    289:                switch (c) {
                    290:                case 'b':
                    291:                        bflag = 1;
                    292:                        break;
                    293:                case 'C':
                    294:                        Cflag = 1;
                    295:                        break;
                    296:                case 'l':
                    297:                        lflag = 1;
                    298:                        pattern_count = cvtnum(optarg);
                    299:                        if (pattern_count < 0) {
                    300:                                printf("non-numeric length argument -- %s\n", optarg);
                    301:                                return 0;
                    302:                        }
                    303:                        break;
                    304:                case 'p':
                    305:                        pflag = 1;
                    306:                        break;
                    307:                case 'P':
                    308:                        Pflag = 1;
                    309:                        pattern = atoi(optarg);
                    310:                        break;
                    311:                case 'q':
                    312:                        qflag = 1;
                    313:                        break;
                    314:                case 's':
                    315:                        sflag = 1;
                    316:                        pattern_offset = cvtnum(optarg);
                    317:                        if (pattern_offset < 0) {
                    318:                                printf("non-numeric length argument -- %s\n", optarg);
                    319:                                return 0;
                    320:                        }
                    321:                        break;
                    322:                case 'v':
                    323:                        vflag = 1;
                    324:                        break;
                    325:                default:
                    326:                        return command_usage(&read_cmd);
                    327:                }
                    328:        }
                    329: 
                    330:        if (optind != argc - 2)
                    331:                return command_usage(&read_cmd);
                    332: 
                    333:        if (bflag && pflag) {
                    334:                printf("-b and -p cannot be specified at the same time\n");
                    335:                return 0;
                    336:        }
                    337: 
                    338:        offset = cvtnum(argv[optind]);
                    339:        if (offset < 0) {
                    340:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    341:                return 0;
                    342:        }
                    343: 
                    344:        optind++;
                    345:        count = cvtnum(argv[optind]);
                    346:        if (count < 0) {
                    347:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    348:                return 0;
                    349:        }
                    350: 
                    351:     if (!Pflag && (lflag || sflag)) {
                    352:         return command_usage(&read_cmd);
                    353:     }
                    354: 
                    355:     if (!lflag) {
                    356:         pattern_count = count - pattern_offset;
                    357:     }
                    358: 
                    359:     if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
                    360:         printf("pattern verfication range exceeds end of read data\n");
                    361:         return 0;
                    362:     }
                    363: 
                    364:        if (!pflag)
                    365:                if (offset & 0x1ff) {
                    366:                        printf("offset %lld is not sector aligned\n",
                    367:                                (long long)offset);
                    368:                        return 0;
                    369: 
                    370:                if (count & 0x1ff) {
                    371:                        printf("count %d is not sector aligned\n",
                    372:                                count);
                    373:                        return 0;
                    374:                }
                    375:        }
                    376: 
                    377:        buf = qemu_io_alloc(count, 0xab);
                    378: 
                    379:        gettimeofday(&t1, NULL);
                    380:        if (pflag)
                    381:                cnt = do_pread(buf, offset, count, &total);
                    382:        else if (bflag)
                    383:                cnt = do_load_vmstate(buf, offset, count, &total);
                    384:        else
                    385:                cnt = do_read(buf, offset, count, &total);
                    386:        gettimeofday(&t2, NULL);
                    387: 
                    388:        if (cnt < 0) {
                    389:                printf("read failed: %s\n", strerror(-cnt));
                    390:                goto out;
                    391:        }
                    392: 
                    393:        if (Pflag) {
                    394:                void* cmp_buf = malloc(pattern_count);
                    395:                memset(cmp_buf, pattern, pattern_count);
                    396:                if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
                    397:                        printf("Pattern verification failed at offset %lld, "
                    398:                                "%d bytes\n",
                    399:                                (long long) offset + pattern_offset, pattern_count);
                    400:                }
                    401:                free(cmp_buf);
                    402:        }
                    403: 
                    404:        if (qflag)
                    405:                goto out;
                    406: 
                    407:         if (vflag)
                    408:                dump_buffer(buf, offset, count);
                    409: 
                    410:        /* Finally, report back -- -C gives a parsable format */
                    411:        t2 = tsub(t2, t1);
                    412:        print_report("read", &t2, offset, count, total, cnt, Cflag);
                    413: 
                    414: out:
                    415:        qemu_io_free(buf);
                    416: 
                    417:        return 0;
                    418: }
                    419: 
                    420: static const cmdinfo_t read_cmd = {
                    421:        .name           = "read",
                    422:        .altname        = "r",
                    423:        .cfunc          = read_f,
                    424:        .argmin         = 2,
                    425:        .argmax         = -1,
                    426:        .args           = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
                    427:        .oneline        = "reads a number of bytes at a specified offset",
                    428:        .help           = read_help,
                    429: };
                    430: 
                    431: static const cmdinfo_t readv_cmd;
                    432: 
                    433: static void
                    434: readv_help(void)
                    435: {
                    436:        printf(
                    437: "\n"
                    438: " reads a range of bytes from the given offset into multiple buffers\n"
                    439: "\n"
                    440: " Example:\n"
                    441: " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
                    442: "\n"
                    443: " Reads a segment of the currently open file, optionally dumping it to the\n"
                    444: " standard output stream (with -v option) for subsequent inspection.\n"
                    445: " Uses multiple iovec buffers if more than one byte range is specified.\n"
                    446: " -C, -- report statistics in a machine parsable format\n"
                    447: " -P, -- use a pattern to verify read data\n"
                    448: " -v, -- dump buffer to standard output\n"
                    449: " -q, -- quite mode, do not show I/O statistics\n"
                    450: "\n");
                    451: }
                    452: 
                    453: static int
                    454: readv_f(int argc, char **argv)
                    455: {
                    456:        struct timeval t1, t2;
                    457:        int Cflag = 0, qflag = 0, vflag = 0;
                    458:        int c, cnt;
                    459:        char *buf;
                    460:        int64_t offset;
                    461:        int total;
                    462:        int nr_iov;
                    463:        QEMUIOVector qiov;
                    464:        int pattern = 0;
                    465:        int Pflag = 0;
                    466: 
                    467:        while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
                    468:                switch (c) {
                    469:                case 'C':
                    470:                        Cflag = 1;
                    471:                        break;
                    472:                case 'P':
                    473:                        Pflag = 1;
                    474:                        pattern = atoi(optarg);
                    475:                        break;
                    476:                case 'q':
                    477:                        qflag = 1;
                    478:                        break;
                    479:                case 'v':
                    480:                        vflag = 1;
                    481:                        break;
                    482:                default:
                    483:                        return command_usage(&readv_cmd);
                    484:                }
                    485:        }
                    486: 
                    487:        if (optind > argc - 2)
                    488:                return command_usage(&readv_cmd);
                    489: 
                    490: 
                    491:        offset = cvtnum(argv[optind]);
                    492:        if (offset < 0) {
                    493:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    494:                return 0;
                    495:        }
                    496:        optind++;
                    497: 
                    498:        if (offset & 0x1ff) {
                    499:                printf("offset %lld is not sector aligned\n",
                    500:                        (long long)offset);
                    501:                return 0;
                    502:        }
                    503: 
                    504:        nr_iov = argc - optind;
                    505:        buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
                    506: 
                    507:        gettimeofday(&t1, NULL);
                    508:        cnt = do_aio_readv(&qiov, offset, &total);
                    509:        gettimeofday(&t2, NULL);
                    510: 
                    511:        if (cnt < 0) {
                    512:                printf("readv failed: %s\n", strerror(-cnt));
                    513:                goto out;
                    514:        }
                    515: 
                    516:        if (Pflag) {
                    517:                void* cmp_buf = malloc(qiov.size);
                    518:                memset(cmp_buf, pattern, qiov.size);
                    519:                if (memcmp(buf, cmp_buf, qiov.size)) {
                    520:                        printf("Pattern verification failed at offset %lld, "
                    521:                                "%zd bytes\n",
                    522:                                (long long) offset, qiov.size);
                    523:                }
                    524:                free(cmp_buf);
                    525:        }
                    526: 
                    527:        if (qflag)
                    528:                goto out;
                    529: 
                    530:         if (vflag)
                    531:                dump_buffer(buf, offset, qiov.size);
                    532: 
                    533:        /* Finally, report back -- -C gives a parsable format */
                    534:        t2 = tsub(t2, t1);
                    535:        print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
                    536: 
                    537: out:
                    538:        qemu_io_free(buf);
                    539:        return 0;
                    540: }
                    541: 
                    542: static const cmdinfo_t readv_cmd = {
                    543:        .name           = "readv",
                    544:        .cfunc          = readv_f,
                    545:        .argmin         = 2,
                    546:        .argmax         = -1,
                    547:        .args           = "[-Cqv] [-P pattern ] off len [len..]",
                    548:        .oneline        = "reads a number of bytes at a specified offset",
                    549:        .help           = readv_help,
                    550: };
                    551: 
                    552: static const cmdinfo_t write_cmd;
                    553: 
                    554: static void
                    555: write_help(void)
                    556: {
                    557:        printf(
                    558: "\n"
                    559: " writes a range of bytes from the given offset\n"
                    560: "\n"
                    561: " Example:\n"
                    562: " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
                    563: "\n"
                    564: " Writes into a segment of the currently open file, using a buffer\n"
                    565: " filled with a set pattern (0xcdcdcdcd).\n"
                    566: " -b, -- write to the VM state rather than the virtual disk\n"
                    567: " -p, -- use bdrv_pwrite to write the file\n"
                    568: " -P, -- use different pattern to fill file\n"
                    569: " -C, -- report statistics in a machine parsable format\n"
                    570: " -q, -- quite mode, do not show I/O statistics\n"
                    571: "\n");
                    572: }
                    573: 
                    574: static int
                    575: write_f(int argc, char **argv)
                    576: {
                    577:        struct timeval t1, t2;
                    578:        int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
                    579:        int c, cnt;
                    580:        char *buf;
                    581:        int64_t offset;
                    582:        int count;
                    583:         /* Some compilers get confused and warn if this is not initialized.  */
                    584:         int total = 0;
                    585:        int pattern = 0xcd;
                    586: 
                    587:        while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
                    588:                switch (c) {
                    589:                case 'b':
                    590:                        bflag = 1;
                    591:                        break;
                    592:                case 'C':
                    593:                        Cflag = 1;
                    594:                        break;
                    595:                case 'p':
                    596:                        pflag = 1;
                    597:                        break;
                    598:                case 'P':
                    599:                        pattern = atoi(optarg);
                    600:                        break;
                    601:                case 'q':
                    602:                        qflag = 1;
                    603:                        break;
                    604:                default:
                    605:                        return command_usage(&write_cmd);
                    606:                }
                    607:        }
                    608: 
                    609:        if (optind != argc - 2)
                    610:                return command_usage(&write_cmd);
                    611: 
                    612:        if (bflag && pflag) {
                    613:                printf("-b and -p cannot be specified at the same time\n");
                    614:                return 0;
                    615:        }
                    616: 
                    617:        offset = cvtnum(argv[optind]);
                    618:        if (offset < 0) {
                    619:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    620:                return 0;
                    621:        }
                    622: 
                    623:        optind++;
                    624:        count = cvtnum(argv[optind]);
                    625:        if (count < 0) {
                    626:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    627:                return 0;
                    628:        }
                    629: 
                    630:        if (!pflag) {
                    631:                if (offset & 0x1ff) {
                    632:                        printf("offset %lld is not sector aligned\n",
                    633:                                (long long)offset);
                    634:                        return 0;
                    635:                }
                    636: 
                    637:                if (count & 0x1ff) {
                    638:                        printf("count %d is not sector aligned\n",
                    639:                                count);
                    640:                        return 0;
                    641:                }
                    642:        }
                    643: 
                    644:        buf = qemu_io_alloc(count, pattern);
                    645: 
                    646:        gettimeofday(&t1, NULL);
                    647:        if (pflag)
                    648:                cnt = do_pwrite(buf, offset, count, &total);
                    649:        else if (bflag)
                    650:                cnt = do_save_vmstate(buf, offset, count, &total);
                    651:        else
                    652:                cnt = do_write(buf, offset, count, &total);
                    653:        gettimeofday(&t2, NULL);
                    654: 
                    655:        if (cnt < 0) {
                    656:                printf("write failed: %s\n", strerror(-cnt));
                    657:                goto out;
                    658:        }
                    659: 
                    660:        if (qflag)
                    661:                goto out;
                    662: 
                    663:        /* Finally, report back -- -C gives a parsable format */
                    664:        t2 = tsub(t2, t1);
                    665:        print_report("wrote", &t2, offset, count, total, cnt, Cflag);
                    666: 
                    667: out:
                    668:        qemu_io_free(buf);
                    669: 
                    670:        return 0;
                    671: }
                    672: 
                    673: static const cmdinfo_t write_cmd = {
                    674:        .name           = "write",
                    675:        .altname        = "w",
                    676:        .cfunc          = write_f,
                    677:        .argmin         = 2,
                    678:        .argmax         = -1,
                    679:        .args           = "[-abCpq] [-P pattern ] off len",
                    680:        .oneline        = "writes a number of bytes at a specified offset",
                    681:        .help           = write_help,
                    682: };
                    683: 
                    684: static const cmdinfo_t writev_cmd;
                    685: 
                    686: static void
                    687: writev_help(void)
                    688: {
                    689:        printf(
                    690: "\n"
                    691: " writes a range of bytes from the given offset source from multiple buffers\n"
                    692: "\n"
                    693: " Example:\n"
                    694: " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
                    695: "\n"
                    696: " Writes into a segment of the currently open file, using a buffer\n"
                    697: " filled with a set pattern (0xcdcdcdcd).\n"
                    698: " -P, -- use different pattern to fill file\n"
                    699: " -C, -- report statistics in a machine parsable format\n"
                    700: " -q, -- quite mode, do not show I/O statistics\n"
                    701: "\n");
                    702: }
                    703: 
                    704: static int
                    705: writev_f(int argc, char **argv)
                    706: {
                    707:        struct timeval t1, t2;
                    708:        int Cflag = 0, qflag = 0;
                    709:        int c, cnt;
                    710:        char *buf;
                    711:        int64_t offset;
                    712:        int total;
                    713:        int nr_iov;
                    714:        int pattern = 0xcd;
                    715:        QEMUIOVector qiov;
                    716: 
                    717:        while ((c = getopt(argc, argv, "CqP:")) != EOF) {
                    718:                switch (c) {
                    719:                case 'C':
                    720:                        Cflag = 1;
                    721:                        break;
                    722:                case 'q':
                    723:                        qflag = 1;
                    724:                        break;
                    725:                case 'P':
                    726:                        pattern = atoi(optarg);
                    727:                        break;
                    728:                default:
                    729:                        return command_usage(&writev_cmd);
                    730:                }
                    731:        }
                    732: 
                    733:        if (optind > argc - 2)
                    734:                return command_usage(&writev_cmd);
                    735: 
                    736:        offset = cvtnum(argv[optind]);
                    737:        if (offset < 0) {
                    738:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    739:                return 0;
                    740:        }
                    741:        optind++;
                    742: 
                    743:        if (offset & 0x1ff) {
                    744:                printf("offset %lld is not sector aligned\n",
                    745:                        (long long)offset);
                    746:                return 0;
                    747:        }
                    748: 
                    749:        nr_iov = argc - optind;
                    750:        buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
                    751: 
                    752:        gettimeofday(&t1, NULL);
                    753:        cnt = do_aio_writev(&qiov, offset, &total);
                    754:        gettimeofday(&t2, NULL);
                    755: 
                    756:        if (cnt < 0) {
                    757:                printf("writev failed: %s\n", strerror(-cnt));
                    758:                goto out;
                    759:        }
                    760: 
                    761:        if (qflag)
                    762:                goto out;
                    763: 
                    764:        /* Finally, report back -- -C gives a parsable format */
                    765:        t2 = tsub(t2, t1);
                    766:        print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
                    767: out:
                    768:        qemu_io_free(buf);
                    769:        return 0;
                    770: }
                    771: 
                    772: static const cmdinfo_t writev_cmd = {
                    773:        .name           = "writev",
                    774:        .cfunc          = writev_f,
                    775:        .argmin         = 2,
                    776:        .argmax         = -1,
                    777:        .args           = "[-Cq] [-P pattern ] off len [len..]",
                    778:        .oneline        = "writes a number of bytes at a specified offset",
                    779:        .help           = writev_help,
                    780: };
                    781: 
                    782: struct aio_ctx {
                    783:        QEMUIOVector qiov;
                    784:        int64_t offset;
                    785:        char *buf;
                    786:        int qflag;
                    787:        int vflag;
                    788:        int Cflag;
                    789:        int Pflag;
                    790:        int pattern;
                    791:        struct timeval t1;
                    792: };
                    793: 
                    794: static void
                    795: aio_write_done(void *opaque, int ret)
                    796: {
                    797:        struct aio_ctx *ctx = opaque;
                    798:        struct timeval t2;
                    799: 
                    800:        gettimeofday(&t2, NULL);
                    801: 
                    802: 
                    803:        if (ret < 0) {
                    804:                printf("aio_write failed: %s\n", strerror(-ret));
                    805:                goto out;
                    806:        }
                    807: 
                    808:        if (ctx->qflag) {
                    809:                goto out;
                    810:        }
                    811: 
                    812:        /* Finally, report back -- -C gives a parsable format */
                    813:        t2 = tsub(t2, ctx->t1);
                    814:        print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
                    815:                     ctx->qiov.size, 1, ctx->Cflag);
                    816: out:
                    817:        qemu_io_free(ctx->buf);
                    818:        free(ctx);
                    819: }
                    820: 
                    821: static const cmdinfo_t aio_read_cmd;
                    822: 
                    823: static void
                    824: aio_read_done(void *opaque, int ret)
                    825: {
                    826:        struct aio_ctx *ctx = opaque;
                    827:        struct timeval t2;
                    828: 
                    829:        gettimeofday(&t2, NULL);
                    830: 
                    831:        if (ret < 0) {
                    832:                printf("readv failed: %s\n", strerror(-ret));
                    833:                goto out;
                    834:        }
                    835: 
                    836:        if (ctx->Pflag) {
                    837:                void *cmp_buf = malloc(ctx->qiov.size);
                    838: 
                    839:                memset(cmp_buf, ctx->pattern, ctx->qiov.size);
                    840:                if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
                    841:                        printf("Pattern verification failed at offset %lld, "
                    842:                                "%zd bytes\n",
                    843:                                (long long) ctx->offset, ctx->qiov.size);
                    844:                }
                    845:                free(cmp_buf);
                    846:        }
                    847: 
                    848:        if (ctx->qflag) {
                    849:                goto out;
                    850:        }
                    851: 
                    852:        if (ctx->vflag) {
                    853:                dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
                    854:        }
                    855: 
                    856:        /* Finally, report back -- -C gives a parsable format */
                    857:        t2 = tsub(t2, ctx->t1);
                    858:        print_report("read", &t2, ctx->offset, ctx->qiov.size,
                    859:                     ctx->qiov.size, 1, ctx->Cflag);
                    860: out:
                    861:        qemu_io_free(ctx->buf);
                    862:        free(ctx);
                    863: }
                    864: 
                    865: static void
                    866: aio_read_help(void)
                    867: {
                    868:        printf(
                    869: "\n"
                    870: " asynchronously reads a range of bytes from the given offset\n"
                    871: "\n"
                    872: " Example:\n"
                    873: " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
                    874: "\n"
                    875: " Reads a segment of the currently open file, optionally dumping it to the\n"
                    876: " standard output stream (with -v option) for subsequent inspection.\n"
                    877: " The read is performed asynchronously and should the aio_flush command \n"
                    878: " should be used to ensure all outstanding aio requests have been completed\n"
                    879: " -C, -- report statistics in a machine parsable format\n"
                    880: " -P, -- use a pattern to verify read data\n"
                    881: " -v, -- dump buffer to standard output\n"
                    882: " -q, -- quite mode, do not show I/O statistics\n"
                    883: "\n");
                    884: }
                    885: 
                    886: static int
                    887: aio_read_f(int argc, char **argv)
                    888: {
                    889:        int nr_iov, c;
                    890:        struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
                    891:        BlockDriverAIOCB *acb;
                    892: 
                    893:        while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
                    894:                switch (c) {
                    895:                case 'C':
                    896:                        ctx->Cflag = 1;
                    897:                        break;
                    898:                case 'P':
                    899:                        ctx->Pflag = 1;
                    900:                        ctx->pattern = atoi(optarg);
                    901:                        break;
                    902:                case 'q':
                    903:                        ctx->qflag = 1;
                    904:                        break;
                    905:                case 'v':
                    906:                        ctx->vflag = 1;
                    907:                        break;
                    908:                default:
                    909:                        free(ctx);
                    910:                        return command_usage(&aio_read_cmd);
                    911:                }
                    912:        }
                    913: 
                    914:        if (optind > argc - 2) {
                    915:                free(ctx);
                    916:                return command_usage(&aio_read_cmd);
                    917:        }
                    918: 
                    919:        ctx->offset = cvtnum(argv[optind]);
                    920:        if (ctx->offset < 0) {
                    921:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    922:                free(ctx);
                    923:                return 0;
                    924:        }
                    925:        optind++;
                    926: 
                    927:        if (ctx->offset & 0x1ff) {
                    928:                printf("offset %lld is not sector aligned\n",
                    929:                        (long long)ctx->offset);
                    930:                free(ctx);
                    931:                return 0;
                    932:        }
                    933: 
                    934:        nr_iov = argc - optind;
                    935:        ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
                    936: 
                    937:        gettimeofday(&ctx->t1, NULL);
                    938:        acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
                    939:                              ctx->qiov.size >> 9, aio_read_done, ctx);
                    940:        if (!acb) {
                    941:                free(ctx->buf);
                    942:                free(ctx);
                    943:                return -EIO;
                    944:        }
                    945: 
                    946:        return 0;
                    947: }
                    948: 
                    949: static const cmdinfo_t aio_read_cmd = {
                    950:        .name           = "aio_read",
                    951:        .cfunc          = aio_read_f,
                    952:        .argmin         = 2,
                    953:        .argmax         = -1,
                    954:        .args           = "[-Cqv] [-P pattern ] off len [len..]",
                    955:        .oneline        = "asynchronously reads a number of bytes",
                    956:        .help           = aio_read_help,
                    957: };
                    958: 
                    959: static const cmdinfo_t aio_write_cmd;
                    960: 
                    961: static void
                    962: aio_write_help(void)
                    963: {
                    964:        printf(
                    965: "\n"
                    966: " asynchronously writes a range of bytes from the given offset source \n"
                    967: " from multiple buffers\n"
                    968: "\n"
                    969: " Example:\n"
                    970: " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
                    971: "\n"
                    972: " Writes into a segment of the currently open file, using a buffer\n"
                    973: " filled with a set pattern (0xcdcdcdcd).\n"
                    974: " The write is performed asynchronously and should the aio_flush command \n"
                    975: " should be used to ensure all outstanding aio requests have been completed\n"
                    976: " -P, -- use different pattern to fill file\n"
                    977: " -C, -- report statistics in a machine parsable format\n"
                    978: " -q, -- quite mode, do not show I/O statistics\n"
                    979: "\n");
                    980: }
                    981: 
                    982: 
                    983: static int
                    984: aio_write_f(int argc, char **argv)
                    985: {
                    986:        int nr_iov, c;
                    987:        int pattern = 0xcd;
                    988:        struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
                    989:        BlockDriverAIOCB *acb;
                    990: 
                    991:        while ((c = getopt(argc, argv, "CqP:")) != EOF) {
                    992:                switch (c) {
                    993:                case 'C':
                    994:                        ctx->Cflag = 1;
                    995:                        break;
                    996:                case 'q':
                    997:                        ctx->qflag = 1;
                    998:                        break;
                    999:                case 'P':
                   1000:                        pattern = atoi(optarg);
                   1001:                        break;
                   1002:                default:
                   1003:                        free(ctx);
                   1004:                        return command_usage(&aio_write_cmd);
                   1005:                }
                   1006:        }
                   1007: 
                   1008:        if (optind > argc - 2) {
                   1009:                free(ctx);
                   1010:                return command_usage(&aio_write_cmd);
                   1011:        }
                   1012: 
                   1013:        ctx->offset = cvtnum(argv[optind]);
                   1014:        if (ctx->offset < 0) {
                   1015:                printf("non-numeric length argument -- %s\n", argv[optind]);
                   1016:                free(ctx);
                   1017:                return 0;
                   1018:        }
                   1019:        optind++;
                   1020: 
                   1021:        if (ctx->offset & 0x1ff) {
                   1022:                printf("offset %lld is not sector aligned\n",
                   1023:                        (long long)ctx->offset);
                   1024:                free(ctx);
                   1025:                return 0;
                   1026:        }
                   1027: 
                   1028:        nr_iov = argc - optind;
                   1029:        ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
                   1030: 
                   1031:        gettimeofday(&ctx->t1, NULL);
                   1032:        acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
                   1033:                              ctx->qiov.size >> 9, aio_write_done, ctx);
                   1034:        if (!acb) {
                   1035:                free(ctx->buf);
                   1036:                free(ctx);
                   1037:                return -EIO;
                   1038:        }
                   1039: 
                   1040:        return 0;
                   1041: }
                   1042: 
                   1043: static const cmdinfo_t aio_write_cmd = {
                   1044:        .name           = "aio_write",
                   1045:        .cfunc          = aio_write_f,
                   1046:        .argmin         = 2,
                   1047:        .argmax         = -1,
                   1048:        .args           = "[-Cq] [-P pattern ] off len [len..]",
                   1049:        .oneline        = "asynchronously writes a number of bytes",
                   1050:        .help           = aio_write_help,
                   1051: };
                   1052: 
                   1053: static int
                   1054: aio_flush_f(int argc, char **argv)
                   1055: {
                   1056:        qemu_aio_flush();
                   1057:        return 0;
                   1058: }
                   1059: 
                   1060: static const cmdinfo_t aio_flush_cmd = {
                   1061:        .name           = "aio_flush",
                   1062:        .cfunc          = aio_flush_f,
                   1063:        .oneline        = "completes all outstanding aio requets"
                   1064: };
                   1065: 
                   1066: static int
                   1067: flush_f(int argc, char **argv)
                   1068: {
                   1069:        bdrv_flush(bs);
                   1070:        return 0;
                   1071: }
                   1072: 
                   1073: static const cmdinfo_t flush_cmd = {
                   1074:        .name           = "flush",
                   1075:        .altname        = "f",
                   1076:        .cfunc          = flush_f,
                   1077:        .oneline        = "flush all in-core file state to disk",
                   1078: };
                   1079: 
                   1080: static int
                   1081: truncate_f(int argc, char **argv)
                   1082: {
                   1083:        int64_t offset;
                   1084:        int ret;
                   1085: 
                   1086:        offset = cvtnum(argv[1]);
                   1087:        if (offset < 0) {
                   1088:                printf("non-numeric truncate argument -- %s\n", argv[1]);
                   1089:                return 0;
                   1090:        }
                   1091: 
                   1092:        ret = bdrv_truncate(bs, offset);
                   1093:        if (ret < 0) {
                   1094:                printf("truncate: %s", strerror(ret));
                   1095:                return 0;
                   1096:        }
                   1097: 
                   1098:        return 0;
                   1099: }
                   1100: 
                   1101: static const cmdinfo_t truncate_cmd = {
                   1102:        .name           = "truncate",
                   1103:        .altname        = "t",
                   1104:        .cfunc          = truncate_f,
                   1105:        .argmin         = 1,
                   1106:        .argmax         = 1,
                   1107:        .args           = "off",
                   1108:        .oneline        = "truncates the current file at the given offset",
                   1109: };
                   1110: 
                   1111: static int
                   1112: length_f(int argc, char **argv)
                   1113: {
                   1114:         int64_t size;
                   1115:        char s1[64];
                   1116: 
                   1117:        size = bdrv_getlength(bs);
                   1118:        if (size < 0) {
                   1119:                printf("getlength: %s", strerror(size));
                   1120:                return 0;
                   1121:        }
                   1122: 
                   1123:        cvtstr(size, s1, sizeof(s1));
                   1124:        printf("%s\n", s1);
                   1125:        return 0;
                   1126: }
                   1127: 
                   1128: 
                   1129: static const cmdinfo_t length_cmd = {
                   1130:        .name           = "length",
                   1131:        .altname        = "l",
                   1132:        .cfunc          = length_f,
                   1133:        .oneline        = "gets the length of the current file",
                   1134: };
                   1135: 
                   1136: 
                   1137: static int
                   1138: info_f(int argc, char **argv)
                   1139: {
                   1140:        BlockDriverInfo bdi;
                   1141:        char s1[64], s2[64];
                   1142:        int ret;
                   1143: 
                   1144:        if (bs->drv && bs->drv->format_name)
                   1145:                printf("format name: %s\n", bs->drv->format_name);
                   1146:        if (bs->drv && bs->drv->protocol_name)
                   1147:                printf("format name: %s\n", bs->drv->protocol_name);
                   1148: 
                   1149:        ret = bdrv_get_info(bs, &bdi);
                   1150:        if (ret)
                   1151:                return 0;
                   1152: 
                   1153:        cvtstr(bdi.cluster_size, s1, sizeof(s1));
                   1154:        cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
                   1155: 
                   1156:        printf("cluster size: %s\n", s1);
                   1157:        printf("vm state offset: %s\n", s2);
                   1158: 
                   1159:        return 0;
                   1160: }
                   1161: 
                   1162: 
                   1163: 
                   1164: static const cmdinfo_t info_cmd = {
                   1165:        .name           = "info",
                   1166:        .altname        = "i",
                   1167:        .cfunc          = info_f,
                   1168:        .oneline        = "prints information about the current file",
                   1169: };
                   1170: 
                   1171: static int
                   1172: alloc_f(int argc, char **argv)
                   1173: {
                   1174:        int64_t offset;
                   1175:        int nb_sectors;
                   1176:        char s1[64];
                   1177:        int num;
                   1178:        int ret;
                   1179:        const char *retstr;
                   1180: 
                   1181:        offset = cvtnum(argv[1]);
                   1182:        if (offset & 0x1ff) {
                   1183:                printf("offset %lld is not sector aligned\n",
                   1184:                        (long long)offset);
                   1185:                return 0;
                   1186:        }
                   1187: 
                   1188:        if (argc == 3)
                   1189:                nb_sectors = cvtnum(argv[2]);
                   1190:        else
                   1191:                nb_sectors = 1;
                   1192: 
                   1193:        ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
                   1194: 
                   1195:        cvtstr(offset, s1, sizeof(s1));
                   1196: 
                   1197:        retstr = ret ? "allocated" : "not allocated";
                   1198:        if (nb_sectors == 1)
                   1199:                printf("sector %s at offset %s\n", retstr, s1);
                   1200:        else
                   1201:                printf("%d/%d sectors %s at offset %s\n",
                   1202:                        num, nb_sectors, retstr, s1);
                   1203:        return 0;
                   1204: }
                   1205: 
                   1206: static const cmdinfo_t alloc_cmd = {
                   1207:        .name           = "alloc",
                   1208:        .altname        = "a",
                   1209:        .argmin         = 1,
                   1210:        .argmax         = 2,
                   1211:        .cfunc          = alloc_f,
                   1212:        .args           = "off [sectors]",
                   1213:        .oneline        = "checks if a sector is present in the file",
                   1214: };
                   1215: 
                   1216: static int
                   1217: close_f(int argc, char **argv)
                   1218: {
                   1219:        bdrv_close(bs);
                   1220:        bs = NULL;
                   1221:        return 0;
                   1222: }
                   1223: 
                   1224: static const cmdinfo_t close_cmd = {
                   1225:        .name           = "close",
                   1226:        .altname        = "c",
                   1227:        .cfunc          = close_f,
                   1228:        .oneline        = "close the current open file",
                   1229: };
                   1230: 
                   1231: static int openfile(char *name, int flags, int growable)
                   1232: {
                   1233:        if (bs) {
                   1234:                fprintf(stderr, "file open already, try 'help close'\n");
                   1235:                return 1;
                   1236:        }
                   1237: 
                   1238:        bs = bdrv_new("hda");
                   1239:        if (!bs)
                   1240:                return 1;
                   1241: 
                   1242:        if (growable) {
                   1243:                flags |= BDRV_O_FILE;
                   1244:        }
                   1245: 
                   1246:        if (bdrv_open(bs, name, flags) == -1) {
                   1247:                fprintf(stderr, "%s: can't open device %s\n", progname, name);
                   1248:                bs = NULL;
                   1249:                return 1;
                   1250:        }
                   1251: 
                   1252:        if (growable) {
                   1253:                bs->growable = 1;
                   1254:        }
                   1255:        return 0;
                   1256: }
                   1257: 
                   1258: static void
                   1259: open_help(void)
                   1260: {
                   1261:        printf(
                   1262: "\n"
                   1263: " opens a new file in the requested mode\n"
                   1264: "\n"
                   1265: " Example:\n"
                   1266: " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
                   1267: "\n"
                   1268: " Opens a file for subsequent use by all of the other qemu-io commands.\n"
                   1269: " -C, -- create new file if it doesn't exist\n"
                   1270: " -r, -- open file read-only\n"
                   1271: " -s, -- use snapshot file\n"
                   1272: " -n, -- disable host cache\n"
                   1273: " -g, -- allow file to grow (only applies to protocols)"
                   1274: "\n");
                   1275: }
                   1276: 
                   1277: static const cmdinfo_t open_cmd;
                   1278: 
                   1279: static int
                   1280: open_f(int argc, char **argv)
                   1281: {
                   1282:        int flags = 0;
                   1283:        int readonly = 0;
                   1284:        int growable = 0;
                   1285:        int c;
                   1286: 
                   1287:        while ((c = getopt(argc, argv, "snCrg")) != EOF) {
                   1288:                switch (c) {
                   1289:                case 's':
                   1290:                        flags |= BDRV_O_SNAPSHOT;
                   1291:                        break;
                   1292:                case 'n':
                   1293:                        flags |= BDRV_O_NOCACHE;
                   1294:                        break;
                   1295:                case 'C':
                   1296:                        flags |= BDRV_O_CREAT;
                   1297:                        break;
                   1298:                case 'r':
                   1299:                        readonly = 1;
                   1300:                        break;
                   1301:                case 'g':
                   1302:                        growable = 1;
                   1303:                        break;
                   1304:                default:
                   1305:                        return command_usage(&open_cmd);
                   1306:                }
                   1307:        }
                   1308: 
                   1309:        if (readonly)
                   1310:                flags |= BDRV_O_RDONLY;
                   1311:        else
                   1312:                flags |= BDRV_O_RDWR;
                   1313: 
                   1314:        if (optind != argc - 1)
                   1315:                return command_usage(&open_cmd);
                   1316: 
                   1317:        return openfile(argv[optind], flags, growable);
                   1318: }
                   1319: 
                   1320: static const cmdinfo_t open_cmd = {
                   1321:        .name           = "open",
                   1322:        .altname        = "o",
                   1323:        .cfunc          = open_f,
                   1324:        .argmin         = 1,
                   1325:        .argmax         = -1,
                   1326:        .flags          = CMD_NOFILE_OK,
                   1327:        .args           = "[-Crsn] [path]",
                   1328:        .oneline        = "open the file specified by path",
                   1329:        .help           = open_help,
                   1330: };
                   1331: 
                   1332: static int
                   1333: init_args_command(
                   1334:         int     index)
                   1335: {
                   1336:        /* only one device allowed so far */
                   1337:        if (index >= 1)
                   1338:                return 0;
                   1339:        return ++index;
                   1340: }
                   1341: 
                   1342: static int
                   1343: init_check_command(
                   1344:        const cmdinfo_t *ct)
                   1345: {
                   1346:        if (ct->flags & CMD_FLAG_GLOBAL)
                   1347:                return 1;
                   1348:        if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
                   1349:                fprintf(stderr, "no file open, try 'help open'\n");
                   1350:                return 0;
                   1351:        }
                   1352:        return 1;
                   1353: }
                   1354: 
                   1355: static void usage(const char *name)
                   1356: {
                   1357:        printf(
                   1358: "Usage: %s [-h] [-V] [-Crsnm] [-c cmd] ... [file]\n"
                   1359: "QEMU Disk exerciser\n"
                   1360: "\n"
                   1361: "  -C, --create         create new file if it doesn't exist\n"
                   1362: "  -c, --cmd            command to execute\n"
                   1363: "  -r, --read-only      export read-only\n"
                   1364: "  -s, --snapshot       use snapshot file\n"
                   1365: "  -n, --nocache        disable host cache\n"
                   1366: "  -g, --growable       allow file to grow (only applies to protocols)\n"
                   1367: "  -m, --misalign       misalign allocations for O_DIRECT\n"
                   1368: "  -h, --help           display this help and exit\n"
                   1369: "  -V, --version        output version information and exit\n"
                   1370: "\n",
                   1371:        name);
                   1372: }
                   1373: 
                   1374: 
                   1375: int main(int argc, char **argv)
                   1376: {
                   1377:        int readonly = 0;
                   1378:        int growable = 0;
                   1379:        const char *sopt = "hVc:Crsnmg";
                   1380:        struct option lopt[] = {
                   1381:                { "help", 0, NULL, 'h' },
                   1382:                { "version", 0, NULL, 'V' },
                   1383:                { "offset", 1, NULL, 'o' },
                   1384:                { "cmd", 1, NULL, 'c' },
                   1385:                { "create", 0, NULL, 'C' },
                   1386:                { "read-only", 0, NULL, 'r' },
                   1387:                { "snapshot", 0, NULL, 's' },
                   1388:                { "nocache", 0, NULL, 'n' },
                   1389:                { "misalign", 0, NULL, 'm' },
                   1390:                { "growable", 0, NULL, 'g' },
                   1391:                { NULL, 0, NULL, 0 }
                   1392:        };
                   1393:        int c;
                   1394:        int opt_index = 0;
                   1395:        int flags = 0;
                   1396: 
                   1397:        progname = basename(argv[0]);
                   1398: 
                   1399:        while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
                   1400:                switch (c) {
                   1401:                case 's':
                   1402:                        flags |= BDRV_O_SNAPSHOT;
                   1403:                        break;
                   1404:                case 'n':
                   1405:                        flags |= BDRV_O_NOCACHE;
                   1406:                        break;
                   1407:                case 'c':
                   1408:                        add_user_command(optarg);
                   1409:                        break;
                   1410:                case 'C':
                   1411:                        flags |= BDRV_O_CREAT;
                   1412:                        break;
                   1413:                case 'r':
                   1414:                        readonly = 1;
                   1415:                        break;
                   1416:                case 'm':
                   1417:                        misalign = 1;
                   1418:                        break;
                   1419:                case 'g':
                   1420:                        growable = 1;
                   1421:                        break;
                   1422:                case 'V':
                   1423:                        printf("%s version %s\n", progname, VERSION);
                   1424:                        exit(0);
                   1425:                case 'h':
                   1426:                        usage(progname);
                   1427:                        exit(0);
                   1428:                default:
                   1429:                        usage(progname);
                   1430:                        exit(1);
                   1431:                }
                   1432:        }
                   1433: 
                   1434:        if ((argc - optind) > 1) {
                   1435:                usage(progname);
                   1436:                exit(1);
                   1437:        }
                   1438: 
                   1439:        bdrv_init();
                   1440: 
                   1441:        /* initialize commands */
                   1442:        quit_init();
                   1443:        help_init();
                   1444:        add_command(&open_cmd);
                   1445:        add_command(&close_cmd);
                   1446:        add_command(&read_cmd);
                   1447:        add_command(&readv_cmd);
                   1448:        add_command(&write_cmd);
                   1449:        add_command(&writev_cmd);
                   1450:        add_command(&aio_read_cmd);
                   1451:        add_command(&aio_write_cmd);
                   1452:        add_command(&aio_flush_cmd);
                   1453:        add_command(&flush_cmd);
                   1454:        add_command(&truncate_cmd);
                   1455:        add_command(&length_cmd);
                   1456:        add_command(&info_cmd);
                   1457:        add_command(&alloc_cmd);
                   1458: 
                   1459:        add_args_command(init_args_command);
                   1460:        add_check_command(init_check_command);
                   1461: 
                   1462:        /* open the device */
                   1463:        if (readonly)
                   1464:                flags |= BDRV_O_RDONLY;
                   1465:        else
                   1466:                flags |= BDRV_O_RDWR;
                   1467: 
                   1468:        if ((argc - optind) == 1)
                   1469:                openfile(argv[optind], flags, growable);
                   1470:        command_loop();
                   1471: 
                   1472:        /*
                   1473:         * Make sure all outstanding requests get flushed the program exits.
                   1474:         */
                   1475:        qemu_aio_flush();
                   1476: 
                   1477:        if (bs)
                   1478:                bdrv_close(bs);
                   1479:        return 0;
                   1480: }

unix.superglobalmegacorp.com