File:  [Qemu by Fabrice Bellard] / qemu / qemu-io.c
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:17:56 2018 UTC (17 months, 2 weeks ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, HEAD
qemu 1.0.1

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

unix.superglobalmegacorp.com