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

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;
1.1.1.4 ! root       64:        buf = qemu_blockalign(bs, len);
1.1       root       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.4 ! root      138:                 int64_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 */
1.1.1.4 ! root      147:                if (len > INT_MAX) {
1.1       root      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"
1.1.1.4 ! root      329: " -q, -- quiet mode, do not show I/O statistics\n"
1.1       root      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"
1.1.1.4 ! root      512: " -q, -- quiet mode, do not show I/O statistics\n"
1.1       root      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"
1.1.1.4 ! root      636: " -q, -- quiet mode, do not show I/O statistics\n"
1.1       root      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"
1.1.1.4 ! root      768: " -q, -- quiet mode, do not show I/O statistics\n"
1.1       root      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"
1.1.1.4 ! root     1103: " -q, -- quiet mode, do not show I/O statistics\n"
1.1       root     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);
1.1.1.4 ! root     1134:                        if (ctx->pattern < 0) {
        !          1135:                                 free(ctx);
1.1.1.2   root     1136:                                return 0;
1.1.1.4 ! root     1137:                         }
1.1       root     1138:                        break;
                   1139:                case 'q':
                   1140:                        ctx->qflag = 1;
                   1141:                        break;
                   1142:                case 'v':
                   1143:                        ctx->vflag = 1;
                   1144:                        break;
                   1145:                default:
                   1146:                        free(ctx);
                   1147:                        return command_usage(&aio_read_cmd);
                   1148:                }
                   1149:        }
                   1150: 
                   1151:        if (optind > argc - 2) {
                   1152:                free(ctx);
                   1153:                return command_usage(&aio_read_cmd);
                   1154:        }
                   1155: 
                   1156:        ctx->offset = cvtnum(argv[optind]);
                   1157:        if (ctx->offset < 0) {
                   1158:                printf("non-numeric length argument -- %s\n", argv[optind]);
                   1159:                free(ctx);
                   1160:                return 0;
                   1161:        }
                   1162:        optind++;
                   1163: 
                   1164:        if (ctx->offset & 0x1ff) {
1.1.1.3   root     1165:                printf("offset %" PRId64 " is not sector aligned\n",
                   1166:                        ctx->offset);
1.1       root     1167:                free(ctx);
                   1168:                return 0;
                   1169:        }
                   1170: 
                   1171:        nr_iov = argc - optind;
                   1172:        ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
                   1173: 
                   1174:        gettimeofday(&ctx->t1, NULL);
                   1175:        acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
                   1176:                              ctx->qiov.size >> 9, aio_read_done, ctx);
                   1177:        if (!acb) {
                   1178:                free(ctx->buf);
                   1179:                free(ctx);
                   1180:                return -EIO;
                   1181:        }
                   1182: 
                   1183:        return 0;
                   1184: }
                   1185: 
                   1186: static void
                   1187: aio_write_help(void)
                   1188: {
                   1189:        printf(
                   1190: "\n"
                   1191: " asynchronously writes a range of bytes from the given offset source \n"
                   1192: " from multiple buffers\n"
                   1193: "\n"
                   1194: " Example:\n"
                   1195: " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
                   1196: "\n"
                   1197: " Writes into a segment of the currently open file, using a buffer\n"
                   1198: " filled with a set pattern (0xcdcdcdcd).\n"
1.1.1.3   root     1199: " The write is performed asynchronously and the aio_flush command must be\n"
                   1200: " used to ensure all outstanding aio requests have been completed\n"
1.1       root     1201: " -P, -- use different pattern to fill file\n"
                   1202: " -C, -- report statistics in a machine parsable format\n"
1.1.1.4 ! root     1203: " -q, -- quiet mode, do not show I/O statistics\n"
1.1       root     1204: "\n");
                   1205: }
                   1206: 
1.1.1.2   root     1207: static int aio_write_f(int argc, char **argv);
                   1208: 
                   1209: static const cmdinfo_t aio_write_cmd = {
                   1210:        .name           = "aio_write",
                   1211:        .cfunc          = aio_write_f,
                   1212:        .argmin         = 2,
                   1213:        .argmax         = -1,
                   1214:        .args           = "[-Cq] [-P pattern ] off len [len..]",
                   1215:        .oneline        = "asynchronously writes a number of bytes",
                   1216:        .help           = aio_write_help,
                   1217: };
1.1       root     1218: 
                   1219: static int
                   1220: aio_write_f(int argc, char **argv)
                   1221: {
                   1222:        int nr_iov, c;
                   1223:        int pattern = 0xcd;
                   1224:        struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
                   1225:        BlockDriverAIOCB *acb;
                   1226: 
                   1227:        while ((c = getopt(argc, argv, "CqP:")) != EOF) {
                   1228:                switch (c) {
                   1229:                case 'C':
                   1230:                        ctx->Cflag = 1;
                   1231:                        break;
                   1232:                case 'q':
                   1233:                        ctx->qflag = 1;
                   1234:                        break;
                   1235:                case 'P':
1.1.1.2   root     1236:                        pattern = parse_pattern(optarg);
                   1237:                        if (pattern < 0)
                   1238:                                return 0;
1.1       root     1239:                        break;
                   1240:                default:
                   1241:                        free(ctx);
                   1242:                        return command_usage(&aio_write_cmd);
                   1243:                }
                   1244:        }
                   1245: 
                   1246:        if (optind > argc - 2) {
                   1247:                free(ctx);
                   1248:                return command_usage(&aio_write_cmd);
                   1249:        }
                   1250: 
                   1251:        ctx->offset = cvtnum(argv[optind]);
                   1252:        if (ctx->offset < 0) {
                   1253:                printf("non-numeric length argument -- %s\n", argv[optind]);
                   1254:                free(ctx);
                   1255:                return 0;
                   1256:        }
                   1257:        optind++;
                   1258: 
                   1259:        if (ctx->offset & 0x1ff) {
1.1.1.3   root     1260:                printf("offset %" PRId64 " is not sector aligned\n",
                   1261:                        ctx->offset);
1.1       root     1262:                free(ctx);
                   1263:                return 0;
                   1264:        }
                   1265: 
                   1266:        nr_iov = argc - optind;
                   1267:        ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
                   1268: 
                   1269:        gettimeofday(&ctx->t1, NULL);
                   1270:        acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
                   1271:                              ctx->qiov.size >> 9, aio_write_done, ctx);
                   1272:        if (!acb) {
                   1273:                free(ctx->buf);
                   1274:                free(ctx);
                   1275:                return -EIO;
                   1276:        }
                   1277: 
                   1278:        return 0;
                   1279: }
                   1280: 
                   1281: static int
                   1282: aio_flush_f(int argc, char **argv)
                   1283: {
                   1284:        qemu_aio_flush();
                   1285:        return 0;
                   1286: }
                   1287: 
                   1288: static const cmdinfo_t aio_flush_cmd = {
                   1289:        .name           = "aio_flush",
                   1290:        .cfunc          = aio_flush_f,
1.1.1.3   root     1291:        .oneline        = "completes all outstanding aio requests"
1.1       root     1292: };
                   1293: 
                   1294: static int
                   1295: flush_f(int argc, char **argv)
                   1296: {
                   1297:        bdrv_flush(bs);
                   1298:        return 0;
                   1299: }
                   1300: 
                   1301: static const cmdinfo_t flush_cmd = {
                   1302:        .name           = "flush",
                   1303:        .altname        = "f",
                   1304:        .cfunc          = flush_f,
                   1305:        .oneline        = "flush all in-core file state to disk",
                   1306: };
                   1307: 
                   1308: static int
                   1309: truncate_f(int argc, char **argv)
                   1310: {
                   1311:        int64_t offset;
                   1312:        int ret;
                   1313: 
                   1314:        offset = cvtnum(argv[1]);
                   1315:        if (offset < 0) {
                   1316:                printf("non-numeric truncate argument -- %s\n", argv[1]);
                   1317:                return 0;
                   1318:        }
                   1319: 
                   1320:        ret = bdrv_truncate(bs, offset);
                   1321:        if (ret < 0) {
1.1.1.3   root     1322:                printf("truncate: %s\n", strerror(-ret));
1.1       root     1323:                return 0;
                   1324:        }
                   1325: 
                   1326:        return 0;
                   1327: }
                   1328: 
                   1329: static const cmdinfo_t truncate_cmd = {
                   1330:        .name           = "truncate",
                   1331:        .altname        = "t",
                   1332:        .cfunc          = truncate_f,
                   1333:        .argmin         = 1,
                   1334:        .argmax         = 1,
                   1335:        .args           = "off",
                   1336:        .oneline        = "truncates the current file at the given offset",
                   1337: };
                   1338: 
                   1339: static int
                   1340: length_f(int argc, char **argv)
                   1341: {
                   1342:         int64_t size;
                   1343:        char s1[64];
                   1344: 
                   1345:        size = bdrv_getlength(bs);
                   1346:        if (size < 0) {
1.1.1.3   root     1347:                printf("getlength: %s\n", strerror(-size));
1.1       root     1348:                return 0;
                   1349:        }
                   1350: 
                   1351:        cvtstr(size, s1, sizeof(s1));
                   1352:        printf("%s\n", s1);
                   1353:        return 0;
                   1354: }
                   1355: 
                   1356: 
                   1357: static const cmdinfo_t length_cmd = {
                   1358:        .name           = "length",
                   1359:        .altname        = "l",
                   1360:        .cfunc          = length_f,
                   1361:        .oneline        = "gets the length of the current file",
                   1362: };
                   1363: 
                   1364: 
                   1365: static int
                   1366: info_f(int argc, char **argv)
                   1367: {
                   1368:        BlockDriverInfo bdi;
                   1369:        char s1[64], s2[64];
                   1370:        int ret;
                   1371: 
                   1372:        if (bs->drv && bs->drv->format_name)
                   1373:                printf("format name: %s\n", bs->drv->format_name);
                   1374:        if (bs->drv && bs->drv->protocol_name)
                   1375:                printf("format name: %s\n", bs->drv->protocol_name);
                   1376: 
                   1377:        ret = bdrv_get_info(bs, &bdi);
                   1378:        if (ret)
                   1379:                return 0;
                   1380: 
                   1381:        cvtstr(bdi.cluster_size, s1, sizeof(s1));
                   1382:        cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
                   1383: 
                   1384:        printf("cluster size: %s\n", s1);
                   1385:        printf("vm state offset: %s\n", s2);
                   1386: 
                   1387:        return 0;
                   1388: }
                   1389: 
                   1390: 
                   1391: 
                   1392: static const cmdinfo_t info_cmd = {
                   1393:        .name           = "info",
                   1394:        .altname        = "i",
                   1395:        .cfunc          = info_f,
                   1396:        .oneline        = "prints information about the current file",
                   1397: };
                   1398: 
1.1.1.4 ! root     1399: static void
        !          1400: discard_help(void)
        !          1401: {
        !          1402:        printf(
        !          1403: "\n"
        !          1404: " discards a range of bytes from the given offset\n"
        !          1405: "\n"
        !          1406: " Example:\n"
        !          1407: " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
        !          1408: "\n"
        !          1409: " Discards a segment of the currently open file.\n"
        !          1410: " -C, -- report statistics in a machine parsable format\n"
        !          1411: " -q, -- quiet mode, do not show I/O statistics\n"
        !          1412: "\n");
        !          1413: }
        !          1414: 
        !          1415: static int discard_f(int argc, char **argv);
        !          1416: 
        !          1417: static const cmdinfo_t discard_cmd = {
        !          1418:        .name           = "discard",
        !          1419:        .altname        = "d",
        !          1420:        .cfunc          = discard_f,
        !          1421:        .argmin         = 2,
        !          1422:        .argmax         = -1,
        !          1423:        .args           = "[-Cq] off len",
        !          1424:        .oneline        = "discards a number of bytes at a specified offset",
        !          1425:        .help           = discard_help,
        !          1426: };
        !          1427: 
        !          1428: static int
        !          1429: discard_f(int argc, char **argv)
        !          1430: {
        !          1431:        struct timeval t1, t2;
        !          1432:        int Cflag = 0, qflag = 0;
        !          1433:        int c, ret;
        !          1434:        int64_t offset;
        !          1435:        int count;
        !          1436: 
        !          1437:        while ((c = getopt(argc, argv, "Cq")) != EOF) {
        !          1438:                switch (c) {
        !          1439:                case 'C':
        !          1440:                        Cflag = 1;
        !          1441:                        break;
        !          1442:                case 'q':
        !          1443:                        qflag = 1;
        !          1444:                        break;
        !          1445:                default:
        !          1446:                        return command_usage(&discard_cmd);
        !          1447:                }
        !          1448:        }
        !          1449: 
        !          1450:        if (optind != argc - 2) {
        !          1451:                return command_usage(&discard_cmd);
        !          1452:        }
        !          1453: 
        !          1454:        offset = cvtnum(argv[optind]);
        !          1455:        if (offset < 0) {
        !          1456:                printf("non-numeric length argument -- %s\n", argv[optind]);
        !          1457:                return 0;
        !          1458:        }
        !          1459: 
        !          1460:        optind++;
        !          1461:        count = cvtnum(argv[optind]);
        !          1462:        if (count < 0) {
        !          1463:                printf("non-numeric length argument -- %s\n", argv[optind]);
        !          1464:                return 0;
        !          1465:        }
        !          1466: 
        !          1467:        gettimeofday(&t1, NULL);
        !          1468:        ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, count >> BDRV_SECTOR_BITS);
        !          1469:        gettimeofday(&t2, NULL);
        !          1470: 
        !          1471:        if (ret < 0) {
        !          1472:                printf("discard failed: %s\n", strerror(-ret));
        !          1473:                goto out;
        !          1474:        }
        !          1475: 
        !          1476:        /* Finally, report back -- -C gives a parsable format */
        !          1477:        if (!qflag) {
        !          1478:                t2 = tsub(t2, t1);
        !          1479:                print_report("discard", &t2, offset, count, count, 1, Cflag);
        !          1480:        }
        !          1481: 
        !          1482: out:
        !          1483:        return 0;
        !          1484: }
        !          1485: 
1.1       root     1486: static int
                   1487: alloc_f(int argc, char **argv)
                   1488: {
                   1489:        int64_t offset;
1.1.1.2   root     1490:        int nb_sectors, remaining;
1.1       root     1491:        char s1[64];
1.1.1.2   root     1492:        int num, sum_alloc;
1.1       root     1493:        int ret;
                   1494: 
                   1495:        offset = cvtnum(argv[1]);
                   1496:        if (offset & 0x1ff) {
1.1.1.3   root     1497:                 printf("offset %" PRId64 " is not sector aligned\n",
                   1498:                        offset);
1.1       root     1499:                return 0;
                   1500:        }
                   1501: 
                   1502:        if (argc == 3)
                   1503:                nb_sectors = cvtnum(argv[2]);
                   1504:        else
                   1505:                nb_sectors = 1;
                   1506: 
1.1.1.2   root     1507:        remaining = nb_sectors;
                   1508:        sum_alloc = 0;
                   1509:        while (remaining) {
                   1510:                ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
                   1511:                remaining -= num;
                   1512:                if (ret) {
                   1513:                        sum_alloc += num;
                   1514:                }
                   1515:        }
1.1       root     1516: 
                   1517:        cvtstr(offset, s1, sizeof(s1));
                   1518: 
1.1.1.4 ! root     1519:        printf("%d/%d sectors allocated at offset %s\n",
        !          1520:               sum_alloc, nb_sectors, s1);
1.1       root     1521:        return 0;
                   1522: }
                   1523: 
                   1524: static const cmdinfo_t alloc_cmd = {
                   1525:        .name           = "alloc",
                   1526:        .altname        = "a",
                   1527:        .argmin         = 1,
                   1528:        .argmax         = 2,
                   1529:        .cfunc          = alloc_f,
                   1530:        .args           = "off [sectors]",
                   1531:        .oneline        = "checks if a sector is present in the file",
                   1532: };
                   1533: 
                   1534: static int
1.1.1.4 ! root     1535: map_f(int argc, char **argv)
        !          1536: {
        !          1537:        int64_t offset;
        !          1538:        int64_t nb_sectors;
        !          1539:        char s1[64];
        !          1540:        int num, num_checked;
        !          1541:        int ret;
        !          1542:        const char *retstr;
        !          1543: 
        !          1544:        offset = 0;
        !          1545:        nb_sectors = bs->total_sectors;
        !          1546: 
        !          1547:        do {
        !          1548:                num_checked = MIN(nb_sectors, INT_MAX);
        !          1549:                ret = bdrv_is_allocated(bs, offset, num_checked, &num);
        !          1550:                retstr = ret ? "    allocated" : "not allocated";
        !          1551:                cvtstr(offset << 9ULL, s1, sizeof(s1));
        !          1552:                printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
        !          1553:                                offset << 9ULL, num, num_checked, retstr, s1, ret);
        !          1554: 
        !          1555:                offset += num;
        !          1556:                nb_sectors -= num;
        !          1557:        } while(offset < bs->total_sectors);
        !          1558: 
        !          1559:        return 0;
        !          1560: }
        !          1561: 
        !          1562: static const cmdinfo_t map_cmd = {
        !          1563:        .name           = "map",
        !          1564:        .argmin         = 0,
        !          1565:        .argmax         = 0,
        !          1566:        .cfunc          = map_f,
        !          1567:        .args           = "",
        !          1568:        .oneline        = "prints the allocated areas of a file",
        !          1569: };
        !          1570: 
        !          1571: 
        !          1572: static int
1.1       root     1573: close_f(int argc, char **argv)
                   1574: {
                   1575:        bdrv_close(bs);
                   1576:        bs = NULL;
                   1577:        return 0;
                   1578: }
                   1579: 
                   1580: static const cmdinfo_t close_cmd = {
                   1581:        .name           = "close",
                   1582:        .altname        = "c",
                   1583:        .cfunc          = close_f,
                   1584:        .oneline        = "close the current open file",
                   1585: };
                   1586: 
                   1587: static int openfile(char *name, int flags, int growable)
                   1588: {
                   1589:        if (bs) {
                   1590:                fprintf(stderr, "file open already, try 'help close'\n");
                   1591:                return 1;
                   1592:        }
                   1593: 
                   1594:        if (growable) {
1.1.1.3   root     1595:                if (bdrv_file_open(&bs, name, flags)) {
                   1596:                        fprintf(stderr, "%s: can't open device %s\n", progname, name);
                   1597:                        return 1;
                   1598:                }
                   1599:        } else {
                   1600:                bs = bdrv_new("hda");
                   1601: 
                   1602:                if (bdrv_open(bs, name, flags, NULL) < 0) {
                   1603:                        fprintf(stderr, "%s: can't open device %s\n", progname, name);
                   1604:                        bs = NULL;
                   1605:                        return 1;
                   1606:                }
1.1       root     1607:        }
                   1608: 
                   1609:        return 0;
                   1610: }
                   1611: 
                   1612: static void
                   1613: open_help(void)
                   1614: {
                   1615:        printf(
                   1616: "\n"
                   1617: " opens a new file in the requested mode\n"
                   1618: "\n"
                   1619: " Example:\n"
                   1620: " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
                   1621: "\n"
                   1622: " Opens a file for subsequent use by all of the other qemu-io commands.\n"
                   1623: " -r, -- open file read-only\n"
                   1624: " -s, -- use snapshot file\n"
                   1625: " -n, -- disable host cache\n"
                   1626: " -g, -- allow file to grow (only applies to protocols)"
                   1627: "\n");
                   1628: }
                   1629: 
1.1.1.2   root     1630: static int open_f(int argc, char **argv);
                   1631: 
                   1632: static const cmdinfo_t open_cmd = {
                   1633:        .name           = "open",
                   1634:        .altname        = "o",
                   1635:        .cfunc          = open_f,
                   1636:        .argmin         = 1,
                   1637:        .argmax         = -1,
                   1638:        .flags          = CMD_NOFILE_OK,
                   1639:        .args           = "[-Crsn] [path]",
                   1640:        .oneline        = "open the file specified by path",
                   1641:        .help           = open_help,
                   1642: };
1.1       root     1643: 
                   1644: static int
                   1645: open_f(int argc, char **argv)
                   1646: {
                   1647:        int flags = 0;
                   1648:        int readonly = 0;
                   1649:        int growable = 0;
                   1650:        int c;
                   1651: 
1.1.1.3   root     1652:        while ((c = getopt(argc, argv, "snrg")) != EOF) {
1.1       root     1653:                switch (c) {
                   1654:                case 's':
                   1655:                        flags |= BDRV_O_SNAPSHOT;
                   1656:                        break;
                   1657:                case 'n':
                   1658:                        flags |= BDRV_O_NOCACHE;
                   1659:                        break;
                   1660:                case 'r':
                   1661:                        readonly = 1;
                   1662:                        break;
                   1663:                case 'g':
                   1664:                        growable = 1;
                   1665:                        break;
                   1666:                default:
                   1667:                        return command_usage(&open_cmd);
                   1668:                }
                   1669:        }
                   1670: 
1.1.1.3   root     1671:        if (!readonly) {
                   1672:             flags |= BDRV_O_RDWR;
                   1673:         }
1.1       root     1674: 
                   1675:        if (optind != argc - 1)
                   1676:                return command_usage(&open_cmd);
                   1677: 
                   1678:        return openfile(argv[optind], flags, growable);
                   1679: }
                   1680: 
                   1681: static int
                   1682: init_args_command(
                   1683:         int     index)
                   1684: {
                   1685:        /* only one device allowed so far */
                   1686:        if (index >= 1)
                   1687:                return 0;
                   1688:        return ++index;
                   1689: }
                   1690: 
                   1691: static int
                   1692: init_check_command(
                   1693:        const cmdinfo_t *ct)
                   1694: {
                   1695:        if (ct->flags & CMD_FLAG_GLOBAL)
                   1696:                return 1;
                   1697:        if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
                   1698:                fprintf(stderr, "no file open, try 'help open'\n");
                   1699:                return 0;
                   1700:        }
                   1701:        return 1;
                   1702: }
                   1703: 
                   1704: static void usage(const char *name)
                   1705: {
                   1706:        printf(
1.1.1.3   root     1707: "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
1.1       root     1708: "QEMU Disk exerciser\n"
                   1709: "\n"
                   1710: "  -c, --cmd            command to execute\n"
                   1711: "  -r, --read-only      export read-only\n"
                   1712: "  -s, --snapshot       use snapshot file\n"
                   1713: "  -n, --nocache        disable host cache\n"
                   1714: "  -g, --growable       allow file to grow (only applies to protocols)\n"
                   1715: "  -m, --misalign       misalign allocations for O_DIRECT\n"
1.1.1.2   root     1716: "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
1.1       root     1717: "  -h, --help           display this help and exit\n"
                   1718: "  -V, --version        output version information and exit\n"
                   1719: "\n",
                   1720:        name);
                   1721: }
                   1722: 
                   1723: 
                   1724: int main(int argc, char **argv)
                   1725: {
                   1726:        int readonly = 0;
                   1727:        int growable = 0;
1.1.1.3   root     1728:        const char *sopt = "hVc:rsnmgk";
                   1729:         const struct option lopt[] = {
1.1       root     1730:                { "help", 0, NULL, 'h' },
                   1731:                { "version", 0, NULL, 'V' },
                   1732:                { "offset", 1, NULL, 'o' },
                   1733:                { "cmd", 1, NULL, 'c' },
                   1734:                { "read-only", 0, NULL, 'r' },
                   1735:                { "snapshot", 0, NULL, 's' },
                   1736:                { "nocache", 0, NULL, 'n' },
                   1737:                { "misalign", 0, NULL, 'm' },
                   1738:                { "growable", 0, NULL, 'g' },
1.1.1.2   root     1739:                { "native-aio", 0, NULL, 'k' },
1.1       root     1740:                { NULL, 0, NULL, 0 }
                   1741:        };
                   1742:        int c;
                   1743:        int opt_index = 0;
                   1744:        int flags = 0;
                   1745: 
                   1746:        progname = basename(argv[0]);
                   1747: 
                   1748:        while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
                   1749:                switch (c) {
                   1750:                case 's':
                   1751:                        flags |= BDRV_O_SNAPSHOT;
                   1752:                        break;
                   1753:                case 'n':
                   1754:                        flags |= BDRV_O_NOCACHE;
                   1755:                        break;
                   1756:                case 'c':
                   1757:                        add_user_command(optarg);
                   1758:                        break;
                   1759:                case 'r':
                   1760:                        readonly = 1;
                   1761:                        break;
                   1762:                case 'm':
                   1763:                        misalign = 1;
                   1764:                        break;
                   1765:                case 'g':
                   1766:                        growable = 1;
                   1767:                        break;
1.1.1.2   root     1768:                case 'k':
                   1769:                        flags |= BDRV_O_NATIVE_AIO;
                   1770:                        break;
1.1       root     1771:                case 'V':
                   1772:                        printf("%s version %s\n", progname, VERSION);
                   1773:                        exit(0);
                   1774:                case 'h':
                   1775:                        usage(progname);
                   1776:                        exit(0);
                   1777:                default:
                   1778:                        usage(progname);
                   1779:                        exit(1);
                   1780:                }
                   1781:        }
                   1782: 
                   1783:        if ((argc - optind) > 1) {
                   1784:                usage(progname);
                   1785:                exit(1);
                   1786:        }
                   1787: 
                   1788:        bdrv_init();
                   1789: 
                   1790:        /* initialize commands */
                   1791:        quit_init();
                   1792:        help_init();
                   1793:        add_command(&open_cmd);
                   1794:        add_command(&close_cmd);
                   1795:        add_command(&read_cmd);
                   1796:        add_command(&readv_cmd);
                   1797:        add_command(&write_cmd);
                   1798:        add_command(&writev_cmd);
1.1.1.3   root     1799:        add_command(&multiwrite_cmd);
1.1       root     1800:        add_command(&aio_read_cmd);
                   1801:        add_command(&aio_write_cmd);
                   1802:        add_command(&aio_flush_cmd);
                   1803:        add_command(&flush_cmd);
                   1804:        add_command(&truncate_cmd);
                   1805:        add_command(&length_cmd);
                   1806:        add_command(&info_cmd);
1.1.1.4 ! root     1807:        add_command(&discard_cmd);
1.1       root     1808:        add_command(&alloc_cmd);
1.1.1.4 ! root     1809:        add_command(&map_cmd);
1.1       root     1810: 
                   1811:        add_args_command(init_args_command);
                   1812:        add_check_command(init_check_command);
                   1813: 
                   1814:        /* open the device */
1.1.1.3   root     1815:        if (!readonly) {
                   1816:             flags |= BDRV_O_RDWR;
                   1817:         }
1.1       root     1818: 
                   1819:        if ((argc - optind) == 1)
                   1820:                openfile(argv[optind], flags, growable);
                   1821:        command_loop();
                   1822: 
                   1823:        /*
                   1824:         * Make sure all outstanding requests get flushed the program exits.
                   1825:         */
                   1826:        qemu_aio_flush();
                   1827: 
                   1828:        if (bs)
                   1829:                bdrv_close(bs);
                   1830:        return 0;
                   1831: }

unix.superglobalmegacorp.com