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

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

unix.superglobalmegacorp.com