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

unix.superglobalmegacorp.com