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

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: 
1.1.1.3 ! root       87:                 printf("%08" PRIx64 ":  ", offset + i);
1.1       root       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));
1.1.1.3 ! root      111:                 printf("%s %d/%d bytes at offset %" PRId64 "\n",
        !           112:                        op, total, count, offset);
1.1       root      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];
1.1.1.3 ! root      138:                 uint64_t len;
1.1       root      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) {
1.1.1.3 ! root      153:                         printf("length argument %" PRId64
        !           154:                                " is not sector aligned\n", 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: 
1.1.1.3 ! root      270: struct multiwrite_async_ret {
        !           271:        int num_done;
        !           272:        int error;
        !           273: };
        !           274: 
        !           275: static void multiwrite_cb(void *opaque, int ret)
        !           276: {
        !           277:        struct multiwrite_async_ret *async_ret = opaque;
        !           278: 
        !           279:        async_ret->num_done++;
        !           280:        if (ret < 0) {
        !           281:                async_ret->error = ret;
        !           282:        }
        !           283: }
        !           284: 
        !           285: static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
        !           286: {
        !           287:        int i, ret;
        !           288:        struct multiwrite_async_ret async_ret = {
        !           289:                .num_done = 0,
        !           290:                .error = 0,
        !           291:        };
        !           292: 
        !           293:        *total = 0;
        !           294:        for (i = 0; i < num_reqs; i++) {
        !           295:                reqs[i].cb = multiwrite_cb;
        !           296:                reqs[i].opaque = &async_ret;
        !           297:                *total += reqs[i].qiov->size;
        !           298:        }
        !           299: 
        !           300:        ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
        !           301:        if (ret < 0) {
        !           302:                return ret;
        !           303:        }
        !           304: 
        !           305:        while (async_ret.num_done < num_reqs) {
        !           306:                qemu_aio_wait();
        !           307:        }
        !           308: 
        !           309:        return async_ret.error < 0 ? async_ret.error : 1;
        !           310: }
1.1       root      311: 
                    312: static void
                    313: read_help(void)
                    314: {
                    315:        printf(
                    316: "\n"
                    317: " reads a range of bytes from the given offset\n"
                    318: "\n"
                    319: " Example:\n"
                    320: " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
                    321: "\n"
                    322: " Reads a segment of the currently open file, optionally dumping it to the\n"
                    323: " standard output stream (with -v option) for subsequent inspection.\n"
                    324: " -b, -- read from the VM state rather than the virtual disk\n"
                    325: " -C, -- report statistics in a machine parsable format\n"
                    326: " -l, -- length for pattern verification (only with -P)\n"
                    327: " -p, -- use bdrv_pread to read the file\n"
                    328: " -P, -- use a pattern to verify read data\n"
                    329: " -q, -- quite mode, do not show I/O statistics\n"
                    330: " -s, -- start offset for pattern verification (only with -P)\n"
                    331: " -v, -- dump buffer to standard output\n"
                    332: "\n");
                    333: }
                    334: 
1.1.1.2   root      335: static int read_f(int argc, char **argv);
                    336: 
                    337: static const cmdinfo_t read_cmd = {
                    338:        .name           = "read",
                    339:        .altname        = "r",
                    340:        .cfunc          = read_f,
                    341:        .argmin         = 2,
                    342:        .argmax         = -1,
                    343:        .args           = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
                    344:        .oneline        = "reads a number of bytes at a specified offset",
                    345:        .help           = read_help,
                    346: };
                    347: 
1.1       root      348: static int
                    349: read_f(int argc, char **argv)
                    350: {
                    351:        struct timeval t1, t2;
                    352:        int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
                    353:        int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
                    354:        int c, cnt;
                    355:        char *buf;
                    356:        int64_t offset;
                    357:        int count;
                    358:         /* Some compilers get confused and warn if this is not initialized.  */
                    359:         int total = 0;
                    360:        int pattern = 0, pattern_offset = 0, pattern_count = 0;
                    361: 
                    362:        while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
                    363:                switch (c) {
                    364:                case 'b':
                    365:                        bflag = 1;
                    366:                        break;
                    367:                case 'C':
                    368:                        Cflag = 1;
                    369:                        break;
                    370:                case 'l':
                    371:                        lflag = 1;
                    372:                        pattern_count = cvtnum(optarg);
                    373:                        if (pattern_count < 0) {
                    374:                                printf("non-numeric length argument -- %s\n", optarg);
                    375:                                return 0;
                    376:                        }
                    377:                        break;
                    378:                case 'p':
                    379:                        pflag = 1;
                    380:                        break;
                    381:                case 'P':
                    382:                        Pflag = 1;
1.1.1.2   root      383:                        pattern = parse_pattern(optarg);
                    384:                        if (pattern < 0)
                    385:                                return 0;
1.1       root      386:                        break;
                    387:                case 'q':
                    388:                        qflag = 1;
                    389:                        break;
                    390:                case 's':
                    391:                        sflag = 1;
                    392:                        pattern_offset = cvtnum(optarg);
                    393:                        if (pattern_offset < 0) {
                    394:                                printf("non-numeric length argument -- %s\n", optarg);
                    395:                                return 0;
                    396:                        }
                    397:                        break;
                    398:                case 'v':
                    399:                        vflag = 1;
                    400:                        break;
                    401:                default:
                    402:                        return command_usage(&read_cmd);
                    403:                }
                    404:        }
                    405: 
                    406:        if (optind != argc - 2)
                    407:                return command_usage(&read_cmd);
                    408: 
                    409:        if (bflag && pflag) {
                    410:                printf("-b and -p cannot be specified at the same time\n");
                    411:                return 0;
                    412:        }
                    413: 
                    414:        offset = cvtnum(argv[optind]);
                    415:        if (offset < 0) {
                    416:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    417:                return 0;
                    418:        }
                    419: 
                    420:        optind++;
                    421:        count = cvtnum(argv[optind]);
                    422:        if (count < 0) {
                    423:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    424:                return 0;
                    425:        }
                    426: 
                    427:     if (!Pflag && (lflag || sflag)) {
                    428:         return command_usage(&read_cmd);
                    429:     }
                    430: 
                    431:     if (!lflag) {
                    432:         pattern_count = count - pattern_offset;
                    433:     }
                    434: 
                    435:     if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
                    436:         printf("pattern verfication range exceeds end of read data\n");
                    437:         return 0;
                    438:     }
                    439: 
                    440:        if (!pflag)
                    441:                if (offset & 0x1ff) {
1.1.1.3 ! root      442:                         printf("offset %" PRId64 " is not sector aligned\n",
        !           443:                                offset);
1.1       root      444:                        return 0;
                    445: 
                    446:                if (count & 0x1ff) {
                    447:                        printf("count %d is not sector aligned\n",
                    448:                                count);
                    449:                        return 0;
                    450:                }
                    451:        }
                    452: 
                    453:        buf = qemu_io_alloc(count, 0xab);
                    454: 
                    455:        gettimeofday(&t1, NULL);
                    456:        if (pflag)
                    457:                cnt = do_pread(buf, offset, count, &total);
                    458:        else if (bflag)
                    459:                cnt = do_load_vmstate(buf, offset, count, &total);
                    460:        else
                    461:                cnt = do_read(buf, offset, count, &total);
                    462:        gettimeofday(&t2, NULL);
                    463: 
                    464:        if (cnt < 0) {
                    465:                printf("read failed: %s\n", strerror(-cnt));
                    466:                goto out;
                    467:        }
                    468: 
                    469:        if (Pflag) {
                    470:                void* cmp_buf = malloc(pattern_count);
                    471:                memset(cmp_buf, pattern, pattern_count);
                    472:                if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
1.1.1.3 ! root      473:                        printf("Pattern verification failed at offset %"
        !           474:                                PRId64 ", %d bytes\n",
        !           475:                                offset + pattern_offset, pattern_count);
1.1       root      476:                }
                    477:                free(cmp_buf);
                    478:        }
                    479: 
                    480:        if (qflag)
                    481:                goto out;
                    482: 
                    483:         if (vflag)
                    484:                dump_buffer(buf, offset, count);
                    485: 
                    486:        /* Finally, report back -- -C gives a parsable format */
                    487:        t2 = tsub(t2, t1);
                    488:        print_report("read", &t2, offset, count, total, cnt, Cflag);
                    489: 
                    490: out:
                    491:        qemu_io_free(buf);
                    492: 
                    493:        return 0;
                    494: }
                    495: 
                    496: static void
                    497: readv_help(void)
                    498: {
                    499:        printf(
                    500: "\n"
                    501: " reads a range of bytes from the given offset into multiple buffers\n"
                    502: "\n"
                    503: " Example:\n"
                    504: " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
                    505: "\n"
                    506: " Reads a segment of the currently open file, optionally dumping it to the\n"
                    507: " standard output stream (with -v option) for subsequent inspection.\n"
                    508: " Uses multiple iovec buffers if more than one byte range is specified.\n"
                    509: " -C, -- report statistics in a machine parsable format\n"
                    510: " -P, -- use a pattern to verify read data\n"
                    511: " -v, -- dump buffer to standard output\n"
                    512: " -q, -- quite mode, do not show I/O statistics\n"
                    513: "\n");
                    514: }
                    515: 
1.1.1.2   root      516: static int readv_f(int argc, char **argv);
                    517: 
                    518: static const cmdinfo_t readv_cmd = {
                    519:        .name           = "readv",
                    520:        .cfunc          = readv_f,
                    521:        .argmin         = 2,
                    522:        .argmax         = -1,
                    523:        .args           = "[-Cqv] [-P pattern ] off len [len..]",
                    524:        .oneline        = "reads a number of bytes at a specified offset",
                    525:        .help           = readv_help,
                    526: };
                    527: 
1.1       root      528: static int
                    529: readv_f(int argc, char **argv)
                    530: {
                    531:        struct timeval t1, t2;
                    532:        int Cflag = 0, qflag = 0, vflag = 0;
                    533:        int c, cnt;
                    534:        char *buf;
                    535:        int64_t offset;
1.1.1.3 ! root      536:         /* Some compilers get confused and warn if this is not initialized.  */
        !           537:         int total = 0;
1.1       root      538:        int nr_iov;
                    539:        QEMUIOVector qiov;
                    540:        int pattern = 0;
                    541:        int Pflag = 0;
                    542: 
                    543:        while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
                    544:                switch (c) {
                    545:                case 'C':
                    546:                        Cflag = 1;
                    547:                        break;
                    548:                case 'P':
                    549:                        Pflag = 1;
1.1.1.2   root      550:                        pattern = parse_pattern(optarg);
                    551:                        if (pattern < 0)
                    552:                                return 0;
1.1       root      553:                        break;
                    554:                case 'q':
                    555:                        qflag = 1;
                    556:                        break;
                    557:                case 'v':
                    558:                        vflag = 1;
                    559:                        break;
                    560:                default:
                    561:                        return command_usage(&readv_cmd);
                    562:                }
                    563:        }
                    564: 
                    565:        if (optind > argc - 2)
                    566:                return command_usage(&readv_cmd);
                    567: 
                    568: 
                    569:        offset = cvtnum(argv[optind]);
                    570:        if (offset < 0) {
                    571:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    572:                return 0;
                    573:        }
                    574:        optind++;
                    575: 
                    576:        if (offset & 0x1ff) {
1.1.1.3 ! root      577:                 printf("offset %" PRId64 " is not sector aligned\n",
        !           578:                        offset);
1.1       root      579:                return 0;
                    580:        }
                    581: 
                    582:        nr_iov = argc - optind;
                    583:        buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
                    584: 
                    585:        gettimeofday(&t1, NULL);
                    586:        cnt = do_aio_readv(&qiov, offset, &total);
                    587:        gettimeofday(&t2, NULL);
                    588: 
                    589:        if (cnt < 0) {
                    590:                printf("readv failed: %s\n", strerror(-cnt));
                    591:                goto out;
                    592:        }
                    593: 
                    594:        if (Pflag) {
                    595:                void* cmp_buf = malloc(qiov.size);
                    596:                memset(cmp_buf, pattern, qiov.size);
                    597:                if (memcmp(buf, cmp_buf, qiov.size)) {
1.1.1.3 ! root      598:                        printf("Pattern verification failed at offset %"
        !           599:                                PRId64 ", %zd bytes\n",
        !           600:                                offset, qiov.size);
1.1       root      601:                }
                    602:                free(cmp_buf);
                    603:        }
                    604: 
                    605:        if (qflag)
                    606:                goto out;
                    607: 
                    608:         if (vflag)
                    609:                dump_buffer(buf, offset, qiov.size);
                    610: 
                    611:        /* Finally, report back -- -C gives a parsable format */
                    612:        t2 = tsub(t2, t1);
                    613:        print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
                    614: 
                    615: out:
                    616:        qemu_io_free(buf);
                    617:        return 0;
                    618: }
                    619: 
                    620: static void
                    621: write_help(void)
                    622: {
                    623:        printf(
                    624: "\n"
                    625: " writes a range of bytes from the given offset\n"
                    626: "\n"
                    627: " Example:\n"
                    628: " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
                    629: "\n"
                    630: " Writes into a segment of the currently open file, using a buffer\n"
                    631: " filled with a set pattern (0xcdcdcdcd).\n"
                    632: " -b, -- write to the VM state rather than the virtual disk\n"
                    633: " -p, -- use bdrv_pwrite to write the file\n"
                    634: " -P, -- use different pattern to fill file\n"
                    635: " -C, -- report statistics in a machine parsable format\n"
                    636: " -q, -- quite mode, do not show I/O statistics\n"
                    637: "\n");
                    638: }
                    639: 
1.1.1.2   root      640: static int write_f(int argc, char **argv);
                    641: 
                    642: static const cmdinfo_t write_cmd = {
                    643:        .name           = "write",
                    644:        .altname        = "w",
                    645:        .cfunc          = write_f,
                    646:        .argmin         = 2,
                    647:        .argmax         = -1,
                    648:        .args           = "[-abCpq] [-P pattern ] off len",
                    649:        .oneline        = "writes a number of bytes at a specified offset",
                    650:        .help           = write_help,
                    651: };
                    652: 
1.1       root      653: static int
                    654: write_f(int argc, char **argv)
                    655: {
                    656:        struct timeval t1, t2;
                    657:        int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
                    658:        int c, cnt;
                    659:        char *buf;
                    660:        int64_t offset;
                    661:        int count;
                    662:         /* Some compilers get confused and warn if this is not initialized.  */
                    663:         int total = 0;
                    664:        int pattern = 0xcd;
                    665: 
                    666:        while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
                    667:                switch (c) {
                    668:                case 'b':
                    669:                        bflag = 1;
                    670:                        break;
                    671:                case 'C':
                    672:                        Cflag = 1;
                    673:                        break;
                    674:                case 'p':
                    675:                        pflag = 1;
                    676:                        break;
                    677:                case 'P':
1.1.1.2   root      678:                        pattern = parse_pattern(optarg);
                    679:                        if (pattern < 0)
                    680:                                return 0;
1.1       root      681:                        break;
                    682:                case 'q':
                    683:                        qflag = 1;
                    684:                        break;
                    685:                default:
                    686:                        return command_usage(&write_cmd);
                    687:                }
                    688:        }
                    689: 
                    690:        if (optind != argc - 2)
                    691:                return command_usage(&write_cmd);
                    692: 
                    693:        if (bflag && pflag) {
                    694:                printf("-b and -p cannot be specified at the same time\n");
                    695:                return 0;
                    696:        }
                    697: 
                    698:        offset = cvtnum(argv[optind]);
                    699:        if (offset < 0) {
                    700:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    701:                return 0;
                    702:        }
                    703: 
                    704:        optind++;
                    705:        count = cvtnum(argv[optind]);
                    706:        if (count < 0) {
                    707:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    708:                return 0;
                    709:        }
                    710: 
                    711:        if (!pflag) {
                    712:                if (offset & 0x1ff) {
1.1.1.3 ! root      713:                         printf("offset %" PRId64 " is not sector aligned\n",
        !           714:                                offset);
1.1       root      715:                        return 0;
                    716:                }
                    717: 
                    718:                if (count & 0x1ff) {
                    719:                        printf("count %d is not sector aligned\n",
                    720:                                count);
                    721:                        return 0;
                    722:                }
                    723:        }
                    724: 
                    725:        buf = qemu_io_alloc(count, pattern);
                    726: 
                    727:        gettimeofday(&t1, NULL);
                    728:        if (pflag)
                    729:                cnt = do_pwrite(buf, offset, count, &total);
                    730:        else if (bflag)
                    731:                cnt = do_save_vmstate(buf, offset, count, &total);
                    732:        else
                    733:                cnt = do_write(buf, offset, count, &total);
                    734:        gettimeofday(&t2, NULL);
                    735: 
                    736:        if (cnt < 0) {
                    737:                printf("write failed: %s\n", strerror(-cnt));
                    738:                goto out;
                    739:        }
                    740: 
                    741:        if (qflag)
                    742:                goto out;
                    743: 
                    744:        /* Finally, report back -- -C gives a parsable format */
                    745:        t2 = tsub(t2, t1);
                    746:        print_report("wrote", &t2, offset, count, total, cnt, Cflag);
                    747: 
                    748: out:
                    749:        qemu_io_free(buf);
                    750: 
                    751:        return 0;
                    752: }
                    753: 
                    754: static void
                    755: writev_help(void)
                    756: {
                    757:        printf(
                    758: "\n"
                    759: " writes a range of bytes from the given offset source from multiple buffers\n"
                    760: "\n"
                    761: " Example:\n"
                    762: " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
                    763: "\n"
                    764: " Writes into a segment of the currently open file, using a buffer\n"
                    765: " filled with a set pattern (0xcdcdcdcd).\n"
                    766: " -P, -- use different pattern to fill file\n"
                    767: " -C, -- report statistics in a machine parsable format\n"
                    768: " -q, -- quite mode, do not show I/O statistics\n"
                    769: "\n");
                    770: }
                    771: 
1.1.1.2   root      772: static int writev_f(int argc, char **argv);
                    773: 
                    774: static const cmdinfo_t writev_cmd = {
                    775:        .name           = "writev",
                    776:        .cfunc          = writev_f,
                    777:        .argmin         = 2,
                    778:        .argmax         = -1,
                    779:        .args           = "[-Cq] [-P pattern ] off len [len..]",
                    780:        .oneline        = "writes a number of bytes at a specified offset",
                    781:        .help           = writev_help,
                    782: };
                    783: 
1.1       root      784: static int
                    785: writev_f(int argc, char **argv)
                    786: {
                    787:        struct timeval t1, t2;
                    788:        int Cflag = 0, qflag = 0;
                    789:        int c, cnt;
                    790:        char *buf;
                    791:        int64_t offset;
1.1.1.3 ! root      792:         /* Some compilers get confused and warn if this is not initialized.  */
        !           793:         int total = 0;
1.1       root      794:        int nr_iov;
                    795:        int pattern = 0xcd;
                    796:        QEMUIOVector qiov;
                    797: 
                    798:        while ((c = getopt(argc, argv, "CqP:")) != EOF) {
                    799:                switch (c) {
                    800:                case 'C':
                    801:                        Cflag = 1;
                    802:                        break;
                    803:                case 'q':
                    804:                        qflag = 1;
                    805:                        break;
                    806:                case 'P':
1.1.1.2   root      807:                        pattern = parse_pattern(optarg);
                    808:                        if (pattern < 0)
                    809:                                return 0;
1.1       root      810:                        break;
                    811:                default:
                    812:                        return command_usage(&writev_cmd);
                    813:                }
                    814:        }
                    815: 
                    816:        if (optind > argc - 2)
                    817:                return command_usage(&writev_cmd);
                    818: 
                    819:        offset = cvtnum(argv[optind]);
                    820:        if (offset < 0) {
                    821:                printf("non-numeric length argument -- %s\n", argv[optind]);
                    822:                return 0;
                    823:        }
                    824:        optind++;
                    825: 
                    826:        if (offset & 0x1ff) {
1.1.1.3 ! root      827:                 printf("offset %" PRId64 " is not sector aligned\n",
        !           828:                        offset);
1.1       root      829:                return 0;
                    830:        }
                    831: 
                    832:        nr_iov = argc - optind;
                    833:        buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
                    834: 
                    835:        gettimeofday(&t1, NULL);
                    836:        cnt = do_aio_writev(&qiov, offset, &total);
                    837:        gettimeofday(&t2, NULL);
                    838: 
                    839:        if (cnt < 0) {
                    840:                printf("writev failed: %s\n", strerror(-cnt));
                    841:                goto out;
                    842:        }
                    843: 
                    844:        if (qflag)
                    845:                goto out;
                    846: 
                    847:        /* Finally, report back -- -C gives a parsable format */
                    848:        t2 = tsub(t2, t1);
                    849:        print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
                    850: out:
                    851:        qemu_io_free(buf);
                    852:        return 0;
                    853: }
                    854: 
1.1.1.3 ! root      855: static void
        !           856: multiwrite_help(void)
        !           857: {
        !           858:        printf(
        !           859: "\n"
        !           860: " writes a range of bytes from the given offset source from multiple buffers,\n"
        !           861: " in a batch of requests that may be merged by qemu\n"
        !           862: "\n"
        !           863: " Example:\n"
        !           864: " 'multiwrite 512 1k 1k ; 4k 1k' \n"
        !           865: "  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
        !           866: "\n"
        !           867: " Writes into a segment of the currently open file, using a buffer\n"
        !           868: " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
        !           869: " by one for each request contained in the multiwrite command.\n"
        !           870: " -P, -- use different pattern to fill file\n"
        !           871: " -C, -- report statistics in a machine parsable format\n"
        !           872: " -q, -- quiet mode, do not show I/O statistics\n"
        !           873: "\n");
        !           874: }
        !           875: 
        !           876: static int multiwrite_f(int argc, char **argv);
        !           877: 
        !           878: static const cmdinfo_t multiwrite_cmd = {
        !           879:        .name           = "multiwrite",
        !           880:        .cfunc          = multiwrite_f,
        !           881:        .argmin         = 2,
        !           882:        .argmax         = -1,
        !           883:        .args           = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
        !           884:        .oneline        = "issues multiple write requests at once",
        !           885:        .help           = multiwrite_help,
        !           886: };
        !           887: 
        !           888: static int
        !           889: multiwrite_f(int argc, char **argv)
        !           890: {
        !           891:        struct timeval t1, t2;
        !           892:        int Cflag = 0, qflag = 0;
        !           893:        int c, cnt;
        !           894:        char **buf;
        !           895:        int64_t offset, first_offset = 0;
        !           896:        /* Some compilers get confused and warn if this is not initialized.  */
        !           897:        int total = 0;
        !           898:        int nr_iov;
        !           899:        int nr_reqs;
        !           900:        int pattern = 0xcd;
        !           901:        QEMUIOVector *qiovs;
        !           902:        int i;
        !           903:        BlockRequest *reqs;
        !           904: 
        !           905:        while ((c = getopt(argc, argv, "CqP:")) != EOF) {
        !           906:                switch (c) {
        !           907:                case 'C':
        !           908:                        Cflag = 1;
        !           909:                        break;
        !           910:                case 'q':
        !           911:                        qflag = 1;
        !           912:                        break;
        !           913:                case 'P':
        !           914:                        pattern = parse_pattern(optarg);
        !           915:                        if (pattern < 0)
        !           916:                                return 0;
        !           917:                        break;
        !           918:                default:
        !           919:                        return command_usage(&writev_cmd);
        !           920:                }
        !           921:        }
        !           922: 
        !           923:        if (optind > argc - 2)
        !           924:                return command_usage(&writev_cmd);
        !           925: 
        !           926:        nr_reqs = 1;
        !           927:        for (i = optind; i < argc; i++) {
        !           928:                if (!strcmp(argv[i], ";")) {
        !           929:                        nr_reqs++;
        !           930:                }
        !           931:        }
        !           932: 
        !           933:        reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
        !           934:        buf = qemu_malloc(nr_reqs * sizeof(*buf));
        !           935:        qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));
        !           936: 
        !           937:        for (i = 0; i < nr_reqs; i++) {
        !           938:                int j;
        !           939: 
        !           940:                /* Read the offset of the request */
        !           941:                offset = cvtnum(argv[optind]);
        !           942:                if (offset < 0) {
        !           943:                        printf("non-numeric offset argument -- %s\n", argv[optind]);
        !           944:                        return 0;
        !           945:                }
        !           946:                optind++;
        !           947: 
        !           948:                if (offset & 0x1ff) {
        !           949:                        printf("offset %lld is not sector aligned\n",
        !           950:                                (long long)offset);
        !           951:                        return 0;
        !           952:                }
        !           953: 
        !           954:         if (i == 0) {
        !           955:             first_offset = offset;
        !           956:         }
        !           957: 
        !           958:                /* Read lengths for qiov entries */
        !           959:                for (j = optind; j < argc; j++) {
        !           960:                        if (!strcmp(argv[j], ";")) {
        !           961:                                break;
        !           962:                        }
        !           963:                }
        !           964: 
        !           965:                nr_iov = j - optind;
        !           966: 
        !           967:                /* Build request */
        !           968:                reqs[i].qiov = &qiovs[i];
        !           969:                buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern);
        !           970:                reqs[i].sector = offset >> 9;
        !           971:                reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
        !           972: 
        !           973:                optind = j + 1;
        !           974: 
        !           975:                offset += reqs[i].qiov->size;
        !           976:                pattern++;
        !           977:        }
        !           978: 
        !           979:        gettimeofday(&t1, NULL);
        !           980:        cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
        !           981:        gettimeofday(&t2, NULL);
        !           982: 
        !           983:        if (cnt < 0) {
        !           984:                printf("aio_multiwrite failed: %s\n", strerror(-cnt));
        !           985:                goto out;
        !           986:        }
        !           987: 
        !           988:        if (qflag)
        !           989:                goto out;
        !           990: 
        !           991:        /* Finally, report back -- -C gives a parsable format */
        !           992:        t2 = tsub(t2, t1);
        !           993:        print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
        !           994: out:
        !           995:        for (i = 0; i < nr_reqs; i++) {
        !           996:                qemu_io_free(buf[i]);
        !           997:                qemu_iovec_destroy(&qiovs[i]);
        !           998:        }
        !           999:        qemu_free(buf);
        !          1000:        qemu_free(reqs);
        !          1001:        qemu_free(qiovs);
        !          1002:        return 0;
        !          1003: }
        !          1004: 
1.1       root     1005: struct aio_ctx {
                   1006:        QEMUIOVector qiov;
                   1007:        int64_t offset;
                   1008:        char *buf;
                   1009:        int qflag;
                   1010:        int vflag;
                   1011:        int Cflag;
                   1012:        int Pflag;
                   1013:        int pattern;
                   1014:        struct timeval t1;
                   1015: };
                   1016: 
                   1017: static void
                   1018: aio_write_done(void *opaque, int ret)
                   1019: {
                   1020:        struct aio_ctx *ctx = opaque;
                   1021:        struct timeval t2;
                   1022: 
                   1023:        gettimeofday(&t2, NULL);
                   1024: 
                   1025: 
                   1026:        if (ret < 0) {
                   1027:                printf("aio_write failed: %s\n", strerror(-ret));
                   1028:                goto out;
                   1029:        }
                   1030: 
                   1031:        if (ctx->qflag) {
                   1032:                goto out;
                   1033:        }
                   1034: 
                   1035:        /* Finally, report back -- -C gives a parsable format */
                   1036:        t2 = tsub(t2, ctx->t1);
                   1037:        print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
                   1038:                     ctx->qiov.size, 1, ctx->Cflag);
                   1039: out:
                   1040:        qemu_io_free(ctx->buf);
                   1041:        free(ctx);
                   1042: }
                   1043: 
                   1044: static void
                   1045: aio_read_done(void *opaque, int ret)
                   1046: {
                   1047:        struct aio_ctx *ctx = opaque;
                   1048:        struct timeval t2;
                   1049: 
                   1050:        gettimeofday(&t2, NULL);
                   1051: 
                   1052:        if (ret < 0) {
                   1053:                printf("readv failed: %s\n", strerror(-ret));
                   1054:                goto out;
                   1055:        }
                   1056: 
                   1057:        if (ctx->Pflag) {
                   1058:                void *cmp_buf = malloc(ctx->qiov.size);
                   1059: 
                   1060:                memset(cmp_buf, ctx->pattern, ctx->qiov.size);
                   1061:                if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1.1.1.3 ! root     1062:                        printf("Pattern verification failed at offset %"
        !          1063:                                PRId64 ", %zd bytes\n",
        !          1064:                                ctx->offset, ctx->qiov.size);
1.1       root     1065:                }
                   1066:                free(cmp_buf);
                   1067:        }
                   1068: 
                   1069:        if (ctx->qflag) {
                   1070:                goto out;
                   1071:        }
                   1072: 
                   1073:        if (ctx->vflag) {
                   1074:                dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
                   1075:        }
                   1076: 
                   1077:        /* Finally, report back -- -C gives a parsable format */
                   1078:        t2 = tsub(t2, ctx->t1);
                   1079:        print_report("read", &t2, ctx->offset, ctx->qiov.size,
                   1080:                     ctx->qiov.size, 1, ctx->Cflag);
                   1081: out:
                   1082:        qemu_io_free(ctx->buf);
                   1083:        free(ctx);
                   1084: }
                   1085: 
                   1086: static void
                   1087: aio_read_help(void)
                   1088: {
                   1089:        printf(
                   1090: "\n"
                   1091: " asynchronously reads a range of bytes from the given offset\n"
                   1092: "\n"
                   1093: " Example:\n"
                   1094: " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
                   1095: "\n"
                   1096: " Reads a segment of the currently open file, optionally dumping it to the\n"
                   1097: " standard output stream (with -v option) for subsequent inspection.\n"
1.1.1.3 ! root     1098: " The read is performed asynchronously and the aio_flush command must be\n"
        !          1099: " used to ensure all outstanding aio requests have been completed\n"
1.1       root     1100: " -C, -- report statistics in a machine parsable format\n"
                   1101: " -P, -- use a pattern to verify read data\n"
                   1102: " -v, -- dump buffer to standard output\n"
                   1103: " -q, -- quite mode, do not show I/O statistics\n"
                   1104: "\n");
                   1105: }
                   1106: 
1.1.1.2   root     1107: static int aio_read_f(int argc, char **argv);
                   1108: 
                   1109: static const cmdinfo_t aio_read_cmd = {
                   1110:        .name           = "aio_read",
                   1111:        .cfunc          = aio_read_f,
                   1112:        .argmin         = 2,
                   1113:        .argmax         = -1,
                   1114:        .args           = "[-Cqv] [-P pattern ] off len [len..]",
                   1115:        .oneline        = "asynchronously reads a number of bytes",
                   1116:        .help           = aio_read_help,
                   1117: };
                   1118: 
1.1       root     1119: static int
                   1120: aio_read_f(int argc, char **argv)
                   1121: {
                   1122:        int nr_iov, c;
                   1123:        struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
                   1124:        BlockDriverAIOCB *acb;
                   1125: 
                   1126:        while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
                   1127:                switch (c) {
                   1128:                case 'C':
                   1129:                        ctx->Cflag = 1;
                   1130:                        break;
                   1131:                case 'P':
                   1132:                        ctx->Pflag = 1;
1.1.1.2   root     1133:                        ctx->pattern = parse_pattern(optarg);
                   1134:                        if (ctx->pattern < 0)
                   1135:                                return 0;
1.1       root     1136:                        break;
                   1137:                case 'q':
                   1138:                        ctx->qflag = 1;
                   1139:                        break;
                   1140:                case 'v':
                   1141:                        ctx->vflag = 1;
                   1142:                        break;
                   1143:                default:
                   1144:                        free(ctx);
                   1145:                        return command_usage(&aio_read_cmd);
                   1146:                }
                   1147:        }
                   1148: 
                   1149:        if (optind > argc - 2) {
                   1150:                free(ctx);
                   1151:                return command_usage(&aio_read_cmd);
                   1152:        }
                   1153: 
                   1154:        ctx->offset = cvtnum(argv[optind]);
                   1155:        if (ctx->offset < 0) {
                   1156:                printf("non-numeric length argument -- %s\n", argv[optind]);
                   1157:                free(ctx);
                   1158:                return 0;
                   1159:        }
                   1160:        optind++;
                   1161: 
                   1162:        if (ctx->offset & 0x1ff) {
1.1.1.3 ! root     1163:                printf("offset %" PRId64 " is not sector aligned\n",
        !          1164:                        ctx->offset);
1.1       root     1165:                free(ctx);
                   1166:                return 0;
                   1167:        }
                   1168: 
                   1169:        nr_iov = argc - optind;
                   1170:        ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
                   1171: 
                   1172:        gettimeofday(&ctx->t1, NULL);
                   1173:        acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
                   1174:                              ctx->qiov.size >> 9, aio_read_done, ctx);
                   1175:        if (!acb) {
                   1176:                free(ctx->buf);
                   1177:                free(ctx);
                   1178:                return -EIO;
                   1179:        }
                   1180: 
                   1181:        return 0;
                   1182: }
                   1183: 
                   1184: static void
                   1185: aio_write_help(void)
                   1186: {
                   1187:        printf(
                   1188: "\n"
                   1189: " asynchronously writes a range of bytes from the given offset source \n"
                   1190: " from multiple buffers\n"
                   1191: "\n"
                   1192: " Example:\n"
                   1193: " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
                   1194: "\n"
                   1195: " Writes into a segment of the currently open file, using a buffer\n"
                   1196: " filled with a set pattern (0xcdcdcdcd).\n"
1.1.1.3 ! root     1197: " The write is performed asynchronously and the aio_flush command must be\n"
        !          1198: " used to ensure all outstanding aio requests have been completed\n"
1.1       root     1199: " -P, -- use different pattern to fill file\n"
                   1200: " -C, -- report statistics in a machine parsable format\n"
                   1201: " -q, -- quite mode, do not show I/O statistics\n"
                   1202: "\n");
                   1203: }
                   1204: 
1.1.1.2   root     1205: static int aio_write_f(int argc, char **argv);
                   1206: 
                   1207: static const cmdinfo_t aio_write_cmd = {
                   1208:        .name           = "aio_write",
                   1209:        .cfunc          = aio_write_f,
                   1210:        .argmin         = 2,
                   1211:        .argmax         = -1,
                   1212:        .args           = "[-Cq] [-P pattern ] off len [len..]",
                   1213:        .oneline        = "asynchronously writes a number of bytes",
                   1214:        .help           = aio_write_help,
                   1215: };
1.1       root     1216: 
                   1217: static int
                   1218: aio_write_f(int argc, char **argv)
                   1219: {
                   1220:        int nr_iov, c;
                   1221:        int pattern = 0xcd;
                   1222:        struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
                   1223:        BlockDriverAIOCB *acb;
                   1224: 
                   1225:        while ((c = getopt(argc, argv, "CqP:")) != EOF) {
                   1226:                switch (c) {
                   1227:                case 'C':
                   1228:                        ctx->Cflag = 1;
                   1229:                        break;
                   1230:                case 'q':
                   1231:                        ctx->qflag = 1;
                   1232:                        break;
                   1233:                case 'P':
1.1.1.2   root     1234:                        pattern = parse_pattern(optarg);
                   1235:                        if (pattern < 0)
                   1236:                                return 0;
1.1       root     1237:                        break;
                   1238:                default:
                   1239:                        free(ctx);
                   1240:                        return command_usage(&aio_write_cmd);
                   1241:                }
                   1242:        }
                   1243: 
                   1244:        if (optind > argc - 2) {
                   1245:                free(ctx);
                   1246:                return command_usage(&aio_write_cmd);
                   1247:        }
                   1248: 
                   1249:        ctx->offset = cvtnum(argv[optind]);
                   1250:        if (ctx->offset < 0) {
                   1251:                printf("non-numeric length argument -- %s\n", argv[optind]);
                   1252:                free(ctx);
                   1253:                return 0;
                   1254:        }
                   1255:        optind++;
                   1256: 
                   1257:        if (ctx->offset & 0x1ff) {
1.1.1.3 ! root     1258:                printf("offset %" PRId64 " is not sector aligned\n",
        !          1259:                        ctx->offset);
1.1       root     1260:                free(ctx);
                   1261:                return 0;
                   1262:        }
                   1263: 
                   1264:        nr_iov = argc - optind;
                   1265:        ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
                   1266: 
                   1267:        gettimeofday(&ctx->t1, NULL);
                   1268:        acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
                   1269:                              ctx->qiov.size >> 9, aio_write_done, ctx);
                   1270:        if (!acb) {
                   1271:                free(ctx->buf);
                   1272:                free(ctx);
                   1273:                return -EIO;
                   1274:        }
                   1275: 
                   1276:        return 0;
                   1277: }
                   1278: 
                   1279: static int
                   1280: aio_flush_f(int argc, char **argv)
                   1281: {
                   1282:        qemu_aio_flush();
                   1283:        return 0;
                   1284: }
                   1285: 
                   1286: static const cmdinfo_t aio_flush_cmd = {
                   1287:        .name           = "aio_flush",
                   1288:        .cfunc          = aio_flush_f,
1.1.1.3 ! root     1289:        .oneline        = "completes all outstanding aio requests"
1.1       root     1290: };
                   1291: 
                   1292: static int
                   1293: flush_f(int argc, char **argv)
                   1294: {
                   1295:        bdrv_flush(bs);
                   1296:        return 0;
                   1297: }
                   1298: 
                   1299: static const cmdinfo_t flush_cmd = {
                   1300:        .name           = "flush",
                   1301:        .altname        = "f",
                   1302:        .cfunc          = flush_f,
                   1303:        .oneline        = "flush all in-core file state to disk",
                   1304: };
                   1305: 
                   1306: static int
                   1307: truncate_f(int argc, char **argv)
                   1308: {
                   1309:        int64_t offset;
                   1310:        int ret;
                   1311: 
                   1312:        offset = cvtnum(argv[1]);
                   1313:        if (offset < 0) {
                   1314:                printf("non-numeric truncate argument -- %s\n", argv[1]);
                   1315:                return 0;
                   1316:        }
                   1317: 
                   1318:        ret = bdrv_truncate(bs, offset);
                   1319:        if (ret < 0) {
1.1.1.3 ! root     1320:                printf("truncate: %s\n", strerror(-ret));
1.1       root     1321:                return 0;
                   1322:        }
                   1323: 
                   1324:        return 0;
                   1325: }
                   1326: 
                   1327: static const cmdinfo_t truncate_cmd = {
                   1328:        .name           = "truncate",
                   1329:        .altname        = "t",
                   1330:        .cfunc          = truncate_f,
                   1331:        .argmin         = 1,
                   1332:        .argmax         = 1,
                   1333:        .args           = "off",
                   1334:        .oneline        = "truncates the current file at the given offset",
                   1335: };
                   1336: 
                   1337: static int
                   1338: length_f(int argc, char **argv)
                   1339: {
                   1340:         int64_t size;
                   1341:        char s1[64];
                   1342: 
                   1343:        size = bdrv_getlength(bs);
                   1344:        if (size < 0) {
1.1.1.3 ! root     1345:                printf("getlength: %s\n", strerror(-size));
1.1       root     1346:                return 0;
                   1347:        }
                   1348: 
                   1349:        cvtstr(size, s1, sizeof(s1));
                   1350:        printf("%s\n", s1);
                   1351:        return 0;
                   1352: }
                   1353: 
                   1354: 
                   1355: static const cmdinfo_t length_cmd = {
                   1356:        .name           = "length",
                   1357:        .altname        = "l",
                   1358:        .cfunc          = length_f,
                   1359:        .oneline        = "gets the length of the current file",
                   1360: };
                   1361: 
                   1362: 
                   1363: static int
                   1364: info_f(int argc, char **argv)
                   1365: {
                   1366:        BlockDriverInfo bdi;
                   1367:        char s1[64], s2[64];
                   1368:        int ret;
                   1369: 
                   1370:        if (bs->drv && bs->drv->format_name)
                   1371:                printf("format name: %s\n", bs->drv->format_name);
                   1372:        if (bs->drv && bs->drv->protocol_name)
                   1373:                printf("format name: %s\n", bs->drv->protocol_name);
                   1374: 
                   1375:        ret = bdrv_get_info(bs, &bdi);
                   1376:        if (ret)
                   1377:                return 0;
                   1378: 
                   1379:        cvtstr(bdi.cluster_size, s1, sizeof(s1));
                   1380:        cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
                   1381: 
                   1382:        printf("cluster size: %s\n", s1);
                   1383:        printf("vm state offset: %s\n", s2);
                   1384: 
                   1385:        return 0;
                   1386: }
                   1387: 
                   1388: 
                   1389: 
                   1390: static const cmdinfo_t info_cmd = {
                   1391:        .name           = "info",
                   1392:        .altname        = "i",
                   1393:        .cfunc          = info_f,
                   1394:        .oneline        = "prints information about the current file",
                   1395: };
                   1396: 
                   1397: static int
                   1398: alloc_f(int argc, char **argv)
                   1399: {
                   1400:        int64_t offset;
1.1.1.2   root     1401:        int nb_sectors, remaining;
1.1       root     1402:        char s1[64];
1.1.1.2   root     1403:        int num, sum_alloc;
1.1       root     1404:        int ret;
                   1405: 
                   1406:        offset = cvtnum(argv[1]);
                   1407:        if (offset & 0x1ff) {
1.1.1.3 ! root     1408:                 printf("offset %" PRId64 " is not sector aligned\n",
        !          1409:                        offset);
1.1       root     1410:                return 0;
                   1411:        }
                   1412: 
                   1413:        if (argc == 3)
                   1414:                nb_sectors = cvtnum(argv[2]);
                   1415:        else
                   1416:                nb_sectors = 1;
                   1417: 
1.1.1.2   root     1418:        remaining = nb_sectors;
                   1419:        sum_alloc = 0;
                   1420:        while (remaining) {
                   1421:                ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
                   1422:                remaining -= num;
                   1423:                if (ret) {
                   1424:                        sum_alloc += num;
                   1425:                }
                   1426:        }
1.1       root     1427: 
                   1428:        cvtstr(offset, s1, sizeof(s1));
                   1429: 
                   1430:        if (nb_sectors == 1)
1.1.1.2   root     1431:                printf("sector allocated at offset %s\n", s1);
1.1       root     1432:        else
1.1.1.2   root     1433:                printf("%d/%d sectors allocated at offset %s\n",
                   1434:                        sum_alloc, nb_sectors, s1);
1.1       root     1435:        return 0;
                   1436: }
                   1437: 
                   1438: static const cmdinfo_t alloc_cmd = {
                   1439:        .name           = "alloc",
                   1440:        .altname        = "a",
                   1441:        .argmin         = 1,
                   1442:        .argmax         = 2,
                   1443:        .cfunc          = alloc_f,
                   1444:        .args           = "off [sectors]",
                   1445:        .oneline        = "checks if a sector is present in the file",
                   1446: };
                   1447: 
                   1448: static int
                   1449: close_f(int argc, char **argv)
                   1450: {
                   1451:        bdrv_close(bs);
                   1452:        bs = NULL;
                   1453:        return 0;
                   1454: }
                   1455: 
                   1456: static const cmdinfo_t close_cmd = {
                   1457:        .name           = "close",
                   1458:        .altname        = "c",
                   1459:        .cfunc          = close_f,
                   1460:        .oneline        = "close the current open file",
                   1461: };
                   1462: 
                   1463: static int openfile(char *name, int flags, int growable)
                   1464: {
                   1465:        if (bs) {
                   1466:                fprintf(stderr, "file open already, try 'help close'\n");
                   1467:                return 1;
                   1468:        }
                   1469: 
                   1470:        if (growable) {
1.1.1.3 ! root     1471:                if (bdrv_file_open(&bs, name, flags)) {
        !          1472:                        fprintf(stderr, "%s: can't open device %s\n", progname, name);
        !          1473:                        return 1;
        !          1474:                }
        !          1475:        } else {
        !          1476:                bs = bdrv_new("hda");
        !          1477:                if (!bs)
        !          1478:                        return 1;
        !          1479: 
        !          1480:                if (bdrv_open(bs, name, flags, NULL) < 0) {
        !          1481:                        fprintf(stderr, "%s: can't open device %s\n", progname, name);
        !          1482:                        bs = NULL;
        !          1483:                        return 1;
        !          1484:                }
1.1       root     1485:        }
                   1486: 
                   1487:        return 0;
                   1488: }
                   1489: 
                   1490: static void
                   1491: open_help(void)
                   1492: {
                   1493:        printf(
                   1494: "\n"
                   1495: " opens a new file in the requested mode\n"
                   1496: "\n"
                   1497: " Example:\n"
                   1498: " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
                   1499: "\n"
                   1500: " Opens a file for subsequent use by all of the other qemu-io commands.\n"
                   1501: " -r, -- open file read-only\n"
                   1502: " -s, -- use snapshot file\n"
                   1503: " -n, -- disable host cache\n"
                   1504: " -g, -- allow file to grow (only applies to protocols)"
                   1505: "\n");
                   1506: }
                   1507: 
1.1.1.2   root     1508: static int open_f(int argc, char **argv);
                   1509: 
                   1510: static const cmdinfo_t open_cmd = {
                   1511:        .name           = "open",
                   1512:        .altname        = "o",
                   1513:        .cfunc          = open_f,
                   1514:        .argmin         = 1,
                   1515:        .argmax         = -1,
                   1516:        .flags          = CMD_NOFILE_OK,
                   1517:        .args           = "[-Crsn] [path]",
                   1518:        .oneline        = "open the file specified by path",
                   1519:        .help           = open_help,
                   1520: };
1.1       root     1521: 
                   1522: static int
                   1523: open_f(int argc, char **argv)
                   1524: {
                   1525:        int flags = 0;
                   1526:        int readonly = 0;
                   1527:        int growable = 0;
                   1528:        int c;
                   1529: 
1.1.1.3 ! root     1530:        while ((c = getopt(argc, argv, "snrg")) != EOF) {
1.1       root     1531:                switch (c) {
                   1532:                case 's':
                   1533:                        flags |= BDRV_O_SNAPSHOT;
                   1534:                        break;
                   1535:                case 'n':
                   1536:                        flags |= BDRV_O_NOCACHE;
                   1537:                        break;
                   1538:                case 'r':
                   1539:                        readonly = 1;
                   1540:                        break;
                   1541:                case 'g':
                   1542:                        growable = 1;
                   1543:                        break;
                   1544:                default:
                   1545:                        return command_usage(&open_cmd);
                   1546:                }
                   1547:        }
                   1548: 
1.1.1.3 ! root     1549:        if (!readonly) {
        !          1550:             flags |= BDRV_O_RDWR;
        !          1551:         }
1.1       root     1552: 
                   1553:        if (optind != argc - 1)
                   1554:                return command_usage(&open_cmd);
                   1555: 
                   1556:        return openfile(argv[optind], flags, growable);
                   1557: }
                   1558: 
                   1559: static int
                   1560: init_args_command(
                   1561:         int     index)
                   1562: {
                   1563:        /* only one device allowed so far */
                   1564:        if (index >= 1)
                   1565:                return 0;
                   1566:        return ++index;
                   1567: }
                   1568: 
                   1569: static int
                   1570: init_check_command(
                   1571:        const cmdinfo_t *ct)
                   1572: {
                   1573:        if (ct->flags & CMD_FLAG_GLOBAL)
                   1574:                return 1;
                   1575:        if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
                   1576:                fprintf(stderr, "no file open, try 'help open'\n");
                   1577:                return 0;
                   1578:        }
                   1579:        return 1;
                   1580: }
                   1581: 
                   1582: static void usage(const char *name)
                   1583: {
                   1584:        printf(
1.1.1.3 ! root     1585: "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
1.1       root     1586: "QEMU Disk exerciser\n"
                   1587: "\n"
                   1588: "  -c, --cmd            command to execute\n"
                   1589: "  -r, --read-only      export read-only\n"
                   1590: "  -s, --snapshot       use snapshot file\n"
                   1591: "  -n, --nocache        disable host cache\n"
                   1592: "  -g, --growable       allow file to grow (only applies to protocols)\n"
                   1593: "  -m, --misalign       misalign allocations for O_DIRECT\n"
1.1.1.2   root     1594: "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
1.1       root     1595: "  -h, --help           display this help and exit\n"
                   1596: "  -V, --version        output version information and exit\n"
                   1597: "\n",
                   1598:        name);
                   1599: }
                   1600: 
                   1601: 
                   1602: int main(int argc, char **argv)
                   1603: {
                   1604:        int readonly = 0;
                   1605:        int growable = 0;
1.1.1.3 ! root     1606:        const char *sopt = "hVc:rsnmgk";
        !          1607:         const struct option lopt[] = {
1.1       root     1608:                { "help", 0, NULL, 'h' },
                   1609:                { "version", 0, NULL, 'V' },
                   1610:                { "offset", 1, NULL, 'o' },
                   1611:                { "cmd", 1, NULL, 'c' },
                   1612:                { "read-only", 0, NULL, 'r' },
                   1613:                { "snapshot", 0, NULL, 's' },
                   1614:                { "nocache", 0, NULL, 'n' },
                   1615:                { "misalign", 0, NULL, 'm' },
                   1616:                { "growable", 0, NULL, 'g' },
1.1.1.2   root     1617:                { "native-aio", 0, NULL, 'k' },
1.1       root     1618:                { NULL, 0, NULL, 0 }
                   1619:        };
                   1620:        int c;
                   1621:        int opt_index = 0;
                   1622:        int flags = 0;
                   1623: 
                   1624:        progname = basename(argv[0]);
                   1625: 
                   1626:        while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
                   1627:                switch (c) {
                   1628:                case 's':
                   1629:                        flags |= BDRV_O_SNAPSHOT;
                   1630:                        break;
                   1631:                case 'n':
                   1632:                        flags |= BDRV_O_NOCACHE;
                   1633:                        break;
                   1634:                case 'c':
                   1635:                        add_user_command(optarg);
                   1636:                        break;
                   1637:                case 'r':
                   1638:                        readonly = 1;
                   1639:                        break;
                   1640:                case 'm':
                   1641:                        misalign = 1;
                   1642:                        break;
                   1643:                case 'g':
                   1644:                        growable = 1;
                   1645:                        break;
1.1.1.2   root     1646:                case 'k':
                   1647:                        flags |= BDRV_O_NATIVE_AIO;
                   1648:                        break;
1.1       root     1649:                case 'V':
                   1650:                        printf("%s version %s\n", progname, VERSION);
                   1651:                        exit(0);
                   1652:                case 'h':
                   1653:                        usage(progname);
                   1654:                        exit(0);
                   1655:                default:
                   1656:                        usage(progname);
                   1657:                        exit(1);
                   1658:                }
                   1659:        }
                   1660: 
                   1661:        if ((argc - optind) > 1) {
                   1662:                usage(progname);
                   1663:                exit(1);
                   1664:        }
                   1665: 
                   1666:        bdrv_init();
                   1667: 
                   1668:        /* initialize commands */
                   1669:        quit_init();
                   1670:        help_init();
                   1671:        add_command(&open_cmd);
                   1672:        add_command(&close_cmd);
                   1673:        add_command(&read_cmd);
                   1674:        add_command(&readv_cmd);
                   1675:        add_command(&write_cmd);
                   1676:        add_command(&writev_cmd);
1.1.1.3 ! root     1677:        add_command(&multiwrite_cmd);
1.1       root     1678:        add_command(&aio_read_cmd);
                   1679:        add_command(&aio_write_cmd);
                   1680:        add_command(&aio_flush_cmd);
                   1681:        add_command(&flush_cmd);
                   1682:        add_command(&truncate_cmd);
                   1683:        add_command(&length_cmd);
                   1684:        add_command(&info_cmd);
                   1685:        add_command(&alloc_cmd);
                   1686: 
                   1687:        add_args_command(init_args_command);
                   1688:        add_check_command(init_check_command);
                   1689: 
                   1690:        /* open the device */
1.1.1.3 ! root     1691:        if (!readonly) {
        !          1692:             flags |= BDRV_O_RDWR;
        !          1693:         }
1.1       root     1694: 
                   1695:        if ((argc - optind) == 1)
                   1696:                openfile(argv[optind], flags, growable);
                   1697:        command_loop();
                   1698: 
                   1699:        /*
                   1700:         * Make sure all outstanding requests get flushed the program exits.
                   1701:         */
                   1702:        qemu_aio_flush();
                   1703: 
                   1704:        if (bs)
                   1705:                bdrv_close(bs);
                   1706:        return 0;
                   1707: }

unix.superglobalmegacorp.com