File:  [Qemu by Fabrice Bellard] / qemu / qemu-io.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:56:49 2018 UTC (17 months, 2 weeks ago) by root
Branches: qemu, MAIN
CVS tags: qemu1000, qemu0151, HEAD
qemu 0.15.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: 
  600:     gettimeofday(&t1, NULL);
  601:     cnt = do_aio_readv(&qiov, offset, &total);
  602:     gettimeofday(&t2, NULL);
  603: 
  604:     if (cnt < 0) {
  605:         printf("readv failed: %s\n", strerror(-cnt));
  606:         goto out;
  607:     }
  608: 
  609:     if (Pflag) {
  610:         void *cmp_buf = malloc(qiov.size);
  611:         memset(cmp_buf, pattern, qiov.size);
  612:         if (memcmp(buf, cmp_buf, qiov.size)) {
  613:             printf("Pattern verification failed at offset %"
  614:                    PRId64 ", %zd bytes\n", offset, qiov.size);
  615:         }
  616:         free(cmp_buf);
  617:     }
  618: 
  619:     if (qflag) {
  620:         goto out;
  621:     }
  622: 
  623:     if (vflag) {
  624:         dump_buffer(buf, offset, qiov.size);
  625:     }
  626: 
  627:     /* Finally, report back -- -C gives a parsable format */
  628:     t2 = tsub(t2, t1);
  629:     print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
  630: 
  631: out:
  632:     qemu_io_free(buf);
  633:     return 0;
  634: }
  635: 
  636: static void write_help(void)
  637: {
  638:     printf(
  639: "\n"
  640: " writes a range of bytes from the given offset\n"
  641: "\n"
  642: " Example:\n"
  643: " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
  644: "\n"
  645: " Writes into a segment of the currently open file, using a buffer\n"
  646: " filled with a set pattern (0xcdcdcdcd).\n"
  647: " -b, -- write to the VM state rather than the virtual disk\n"
  648: " -p, -- use bdrv_pwrite to write the file\n"
  649: " -P, -- use different pattern to fill file\n"
  650: " -C, -- report statistics in a machine parsable format\n"
  651: " -q, -- quiet mode, do not show I/O statistics\n"
  652: "\n");
  653: }
  654: 
  655: static int write_f(int argc, char **argv);
  656: 
  657: static const cmdinfo_t write_cmd = {
  658:     .name       = "write",
  659:     .altname    = "w",
  660:     .cfunc      = write_f,
  661:     .argmin     = 2,
  662:     .argmax     = -1,
  663:     .args       = "[-abCpq] [-P pattern ] off len",
  664:     .oneline    = "writes a number of bytes at a specified offset",
  665:     .help       = write_help,
  666: };
  667: 
  668: static int write_f(int argc, char **argv)
  669: {
  670:     struct timeval t1, t2;
  671:     int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
  672:     int c, cnt;
  673:     char *buf;
  674:     int64_t offset;
  675:     int count;
  676:     /* Some compilers get confused and warn if this is not initialized.  */
  677:     int total = 0;
  678:     int pattern = 0xcd;
  679: 
  680:     while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
  681:         switch (c) {
  682:         case 'b':
  683:             bflag = 1;
  684:             break;
  685:         case 'C':
  686:             Cflag = 1;
  687:             break;
  688:         case 'p':
  689:             pflag = 1;
  690:             break;
  691:         case 'P':
  692:             pattern = parse_pattern(optarg);
  693:             if (pattern < 0) {
  694:                 return 0;
  695:             }
  696:             break;
  697:         case 'q':
  698:             qflag = 1;
  699:             break;
  700:         default:
  701:             return command_usage(&write_cmd);
  702:         }
  703:     }
  704: 
  705:     if (optind != argc - 2) {
  706:         return command_usage(&write_cmd);
  707:     }
  708: 
  709:     if (bflag && pflag) {
  710:         printf("-b and -p cannot be specified at the same time\n");
  711:         return 0;
  712:     }
  713: 
  714:     offset = cvtnum(argv[optind]);
  715:     if (offset < 0) {
  716:         printf("non-numeric length argument -- %s\n", argv[optind]);
  717:         return 0;
  718:     }
  719: 
  720:     optind++;
  721:     count = cvtnum(argv[optind]);
  722:     if (count < 0) {
  723:         printf("non-numeric length argument -- %s\n", argv[optind]);
  724:         return 0;
  725:     }
  726: 
  727:     if (!pflag) {
  728:         if (offset & 0x1ff) {
  729:             printf("offset %" PRId64 " is not sector aligned\n",
  730:                    offset);
  731:             return 0;
  732:         }
  733: 
  734:         if (count & 0x1ff) {
  735:             printf("count %d is not sector aligned\n",
  736:                    count);
  737:             return 0;
  738:         }
  739:     }
  740: 
  741:     buf = qemu_io_alloc(count, pattern);
  742: 
  743:     gettimeofday(&t1, NULL);
  744:     if (pflag) {
  745:         cnt = do_pwrite(buf, offset, count, &total);
  746:     } else if (bflag) {
  747:         cnt = do_save_vmstate(buf, offset, count, &total);
  748:     } else {
  749:         cnt = do_write(buf, offset, count, &total);
  750:     }
  751:     gettimeofday(&t2, NULL);
  752: 
  753:     if (cnt < 0) {
  754:         printf("write failed: %s\n", strerror(-cnt));
  755:         goto out;
  756:     }
  757: 
  758:     if (qflag) {
  759:         goto out;
  760:     }
  761: 
  762:     /* Finally, report back -- -C gives a parsable format */
  763:     t2 = tsub(t2, t1);
  764:     print_report("wrote", &t2, offset, count, total, cnt, Cflag);
  765: 
  766: out:
  767:     qemu_io_free(buf);
  768: 
  769:     return 0;
  770: }
  771: 
  772: static void
  773: writev_help(void)
  774: {
  775:     printf(
  776: "\n"
  777: " writes a range of bytes from the given offset source from multiple buffers\n"
  778: "\n"
  779: " Example:\n"
  780: " 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
  781: "\n"
  782: " Writes into a segment of the currently open file, using a buffer\n"
  783: " filled with a set pattern (0xcdcdcdcd).\n"
  784: " -P, -- use different pattern to fill file\n"
  785: " -C, -- report statistics in a machine parsable format\n"
  786: " -q, -- quiet mode, do not show I/O statistics\n"
  787: "\n");
  788: }
  789: 
  790: static int writev_f(int argc, char **argv);
  791: 
  792: static const cmdinfo_t writev_cmd = {
  793:     .name       = "writev",
  794:     .cfunc      = writev_f,
  795:     .argmin     = 2,
  796:     .argmax     = -1,
  797:     .args       = "[-Cq] [-P pattern ] off len [len..]",
  798:     .oneline    = "writes a number of bytes at a specified offset",
  799:     .help       = writev_help,
  800: };
  801: 
  802: static int writev_f(int argc, char **argv)
  803: {
  804:     struct timeval t1, t2;
  805:     int Cflag = 0, qflag = 0;
  806:     int c, cnt;
  807:     char *buf;
  808:     int64_t offset;
  809:     /* Some compilers get confused and warn if this is not initialized.  */
  810:     int total = 0;
  811:     int nr_iov;
  812:     int pattern = 0xcd;
  813:     QEMUIOVector qiov;
  814: 
  815:     while ((c = getopt(argc, argv, "CqP:")) != EOF) {
  816:         switch (c) {
  817:         case 'C':
  818:             Cflag = 1;
  819:             break;
  820:         case 'q':
  821:             qflag = 1;
  822:             break;
  823:         case 'P':
  824:             pattern = parse_pattern(optarg);
  825:             if (pattern < 0) {
  826:                 return 0;
  827:             }
  828:             break;
  829:         default:
  830:             return command_usage(&writev_cmd);
  831:         }
  832:     }
  833: 
  834:     if (optind > argc - 2) {
  835:         return command_usage(&writev_cmd);
  836:     }
  837: 
  838:     offset = cvtnum(argv[optind]);
  839:     if (offset < 0) {
  840:         printf("non-numeric length argument -- %s\n", argv[optind]);
  841:         return 0;
  842:     }
  843:     optind++;
  844: 
  845:     if (offset & 0x1ff) {
  846:         printf("offset %" PRId64 " is not sector aligned\n",
  847:                offset);
  848:         return 0;
  849:     }
  850: 
  851:     nr_iov = argc - optind;
  852:     buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
  853: 
  854:     gettimeofday(&t1, NULL);
  855:     cnt = do_aio_writev(&qiov, offset, &total);
  856:     gettimeofday(&t2, NULL);
  857: 
  858:     if (cnt < 0) {
  859:         printf("writev failed: %s\n", strerror(-cnt));
  860:         goto out;
  861:     }
  862: 
  863:     if (qflag) {
  864:         goto out;
  865:     }
  866: 
  867:     /* Finally, report back -- -C gives a parsable format */
  868:     t2 = tsub(t2, t1);
  869:     print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
  870: out:
  871:     qemu_io_free(buf);
  872:     return 0;
  873: }
  874: 
  875: static void multiwrite_help(void)
  876: {
  877:     printf(
  878: "\n"
  879: " writes a range of bytes from the given offset source from multiple buffers,\n"
  880: " in a batch of requests that may be merged by qemu\n"
  881: "\n"
  882: " Example:\n"
  883: " 'multiwrite 512 1k 1k ; 4k 1k' \n"
  884: "  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
  885: "\n"
  886: " Writes into a segment of the currently open file, using a buffer\n"
  887: " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
  888: " by one for each request contained in the multiwrite command.\n"
  889: " -P, -- use different pattern to fill file\n"
  890: " -C, -- report statistics in a machine parsable format\n"
  891: " -q, -- quiet mode, do not show I/O statistics\n"
  892: "\n");
  893: }
  894: 
  895: static int multiwrite_f(int argc, char **argv);
  896: 
  897: static const cmdinfo_t multiwrite_cmd = {
  898:     .name       = "multiwrite",
  899:     .cfunc      = multiwrite_f,
  900:     .argmin     = 2,
  901:     .argmax     = -1,
  902:     .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
  903:     .oneline    = "issues multiple write requests at once",
  904:     .help       = multiwrite_help,
  905: };
  906: 
  907: static int multiwrite_f(int argc, char **argv)
  908: {
  909:     struct timeval t1, t2;
  910:     int Cflag = 0, qflag = 0;
  911:     int c, cnt;
  912:     char **buf;
  913:     int64_t offset, first_offset = 0;
  914:     /* Some compilers get confused and warn if this is not initialized.  */
  915:     int total = 0;
  916:     int nr_iov;
  917:     int nr_reqs;
  918:     int pattern = 0xcd;
  919:     QEMUIOVector *qiovs;
  920:     int i;
  921:     BlockRequest *reqs;
  922: 
  923:     while ((c = getopt(argc, argv, "CqP:")) != EOF) {
  924:         switch (c) {
  925:         case 'C':
  926:             Cflag = 1;
  927:             break;
  928:         case 'q':
  929:             qflag = 1;
  930:             break;
  931:         case 'P':
  932:             pattern = parse_pattern(optarg);
  933:             if (pattern < 0) {
  934:                 return 0;
  935:             }
  936:             break;
  937:         default:
  938:             return command_usage(&writev_cmd);
  939:         }
  940:     }
  941: 
  942:     if (optind > argc - 2) {
  943:         return command_usage(&writev_cmd);
  944:     }
  945: 
  946:     nr_reqs = 1;
  947:     for (i = optind; i < argc; i++) {
  948:         if (!strcmp(argv[i], ";")) {
  949:             nr_reqs++;
  950:         }
  951:     }
  952: 
  953:     reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
  954:     buf = qemu_malloc(nr_reqs * sizeof(*buf));
  955:     qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));
  956: 
  957:     for (i = 0; i < nr_reqs; i++) {
  958:         int j;
  959: 
  960:         /* Read the offset of the request */
  961:         offset = cvtnum(argv[optind]);
  962:         if (offset < 0) {
  963:             printf("non-numeric offset argument -- %s\n", argv[optind]);
  964:             return 0;
  965:         }
  966:         optind++;
  967: 
  968:         if (offset & 0x1ff) {
  969:             printf("offset %lld is not sector aligned\n",
  970:                    (long long)offset);
  971:             return 0;
  972:         }
  973: 
  974:         if (i == 0) {
  975:             first_offset = offset;
  976:         }
  977: 
  978:         /* Read lengths for qiov entries */
  979:         for (j = optind; j < argc; j++) {
  980:             if (!strcmp(argv[j], ";")) {
  981:                 break;
  982:             }
  983:         }
  984: 
  985:         nr_iov = j - optind;
  986: 
  987:         /* Build request */
  988:         reqs[i].qiov = &qiovs[i];
  989:         buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern);
  990:         reqs[i].sector = offset >> 9;
  991:         reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
  992: 
  993:         optind = j + 1;
  994: 
  995:         offset += reqs[i].qiov->size;
  996:         pattern++;
  997:     }
  998: 
  999:     gettimeofday(&t1, NULL);
 1000:     cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
 1001:     gettimeofday(&t2, NULL);
 1002: 
 1003:     if (cnt < 0) {
 1004:         printf("aio_multiwrite failed: %s\n", strerror(-cnt));
 1005:         goto out;
 1006:     }
 1007: 
 1008:     if (qflag) {
 1009:         goto out;
 1010:     }
 1011: 
 1012:     /* Finally, report back -- -C gives a parsable format */
 1013:     t2 = tsub(t2, t1);
 1014:     print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
 1015: out:
 1016:     for (i = 0; i < nr_reqs; i++) {
 1017:         qemu_io_free(buf[i]);
 1018:         qemu_iovec_destroy(&qiovs[i]);
 1019:     }
 1020:     qemu_free(buf);
 1021:     qemu_free(reqs);
 1022:     qemu_free(qiovs);
 1023:     return 0;
 1024: }
 1025: 
 1026: struct aio_ctx {
 1027:     QEMUIOVector qiov;
 1028:     int64_t offset;
 1029:     char *buf;
 1030:     int qflag;
 1031:     int vflag;
 1032:     int Cflag;
 1033:     int Pflag;
 1034:     int pattern;
 1035:     struct timeval t1;
 1036: };
 1037: 
 1038: static void aio_write_done(void *opaque, int ret)
 1039: {
 1040:     struct aio_ctx *ctx = opaque;
 1041:     struct timeval t2;
 1042: 
 1043:     gettimeofday(&t2, NULL);
 1044: 
 1045: 
 1046:     if (ret < 0) {
 1047:         printf("aio_write failed: %s\n", strerror(-ret));
 1048:         goto out;
 1049:     }
 1050: 
 1051:     if (ctx->qflag) {
 1052:         goto out;
 1053:     }
 1054: 
 1055:     /* Finally, report back -- -C gives a parsable format */
 1056:     t2 = tsub(t2, ctx->t1);
 1057:     print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
 1058:                  ctx->qiov.size, 1, ctx->Cflag);
 1059: out:
 1060:     qemu_io_free(ctx->buf);
 1061:     free(ctx);
 1062: }
 1063: 
 1064: static void aio_read_done(void *opaque, int ret)
 1065: {
 1066:     struct aio_ctx *ctx = opaque;
 1067:     struct timeval t2;
 1068: 
 1069:     gettimeofday(&t2, NULL);
 1070: 
 1071:     if (ret < 0) {
 1072:         printf("readv failed: %s\n", strerror(-ret));
 1073:         goto out;
 1074:     }
 1075: 
 1076:     if (ctx->Pflag) {
 1077:         void *cmp_buf = malloc(ctx->qiov.size);
 1078: 
 1079:         memset(cmp_buf, ctx->pattern, ctx->qiov.size);
 1080:         if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
 1081:             printf("Pattern verification failed at offset %"
 1082:                    PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
 1083:         }
 1084:         free(cmp_buf);
 1085:     }
 1086: 
 1087:     if (ctx->qflag) {
 1088:         goto out;
 1089:     }
 1090: 
 1091:     if (ctx->vflag) {
 1092:         dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
 1093:     }
 1094: 
 1095:     /* Finally, report back -- -C gives a parsable format */
 1096:     t2 = tsub(t2, ctx->t1);
 1097:     print_report("read", &t2, ctx->offset, ctx->qiov.size,
 1098:                  ctx->qiov.size, 1, ctx->Cflag);
 1099: out:
 1100:     qemu_io_free(ctx->buf);
 1101:     free(ctx);
 1102: }
 1103: 
 1104: static void aio_read_help(void)
 1105: {
 1106:     printf(
 1107: "\n"
 1108: " asynchronously reads a range of bytes from the given offset\n"
 1109: "\n"
 1110: " Example:\n"
 1111: " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
 1112: "\n"
 1113: " Reads a segment of the currently open file, optionally dumping it to the\n"
 1114: " standard output stream (with -v option) for subsequent inspection.\n"
 1115: " The read is performed asynchronously and the aio_flush command must be\n"
 1116: " used to ensure all outstanding aio requests have been completed\n"
 1117: " -C, -- report statistics in a machine parsable format\n"
 1118: " -P, -- use a pattern to verify read data\n"
 1119: " -v, -- dump buffer to standard output\n"
 1120: " -q, -- quiet mode, do not show I/O statistics\n"
 1121: "\n");
 1122: }
 1123: 
 1124: static int aio_read_f(int argc, char **argv);
 1125: 
 1126: static const cmdinfo_t aio_read_cmd = {
 1127:     .name       = "aio_read",
 1128:     .cfunc      = aio_read_f,
 1129:     .argmin     = 2,
 1130:     .argmax     = -1,
 1131:     .args       = "[-Cqv] [-P pattern ] off len [len..]",
 1132:     .oneline    = "asynchronously reads a number of bytes",
 1133:     .help       = aio_read_help,
 1134: };
 1135: 
 1136: static int aio_read_f(int argc, char **argv)
 1137: {
 1138:     int nr_iov, c;
 1139:     struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
 1140:     BlockDriverAIOCB *acb;
 1141: 
 1142:     while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
 1143:         switch (c) {
 1144:         case 'C':
 1145:             ctx->Cflag = 1;
 1146:             break;
 1147:         case 'P':
 1148:             ctx->Pflag = 1;
 1149:             ctx->pattern = parse_pattern(optarg);
 1150:             if (ctx->pattern < 0) {
 1151:                 free(ctx);
 1152:                 return 0;
 1153:             }
 1154:             break;
 1155:         case 'q':
 1156:             ctx->qflag = 1;
 1157:             break;
 1158:         case 'v':
 1159:             ctx->vflag = 1;
 1160:             break;
 1161:         default:
 1162:             free(ctx);
 1163:             return command_usage(&aio_read_cmd);
 1164:         }
 1165:     }
 1166: 
 1167:     if (optind > argc - 2) {
 1168:         free(ctx);
 1169:         return command_usage(&aio_read_cmd);
 1170:     }
 1171: 
 1172:     ctx->offset = cvtnum(argv[optind]);
 1173:     if (ctx->offset < 0) {
 1174:         printf("non-numeric length argument -- %s\n", argv[optind]);
 1175:         free(ctx);
 1176:         return 0;
 1177:     }
 1178:     optind++;
 1179: 
 1180:     if (ctx->offset & 0x1ff) {
 1181:         printf("offset %" PRId64 " is not sector aligned\n",
 1182:                ctx->offset);
 1183:         free(ctx);
 1184:         return 0;
 1185:     }
 1186: 
 1187:     nr_iov = argc - optind;
 1188:     ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab);
 1189: 
 1190:     gettimeofday(&ctx->t1, NULL);
 1191:     acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
 1192:                          ctx->qiov.size >> 9, aio_read_done, ctx);
 1193:     if (!acb) {
 1194:         free(ctx->buf);
 1195:         free(ctx);
 1196:         return -EIO;
 1197:     }
 1198: 
 1199:     return 0;
 1200: }
 1201: 
 1202: static void aio_write_help(void)
 1203: {
 1204:     printf(
 1205: "\n"
 1206: " asynchronously writes a range of bytes from the given offset source\n"
 1207: " from multiple buffers\n"
 1208: "\n"
 1209: " Example:\n"
 1210: " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
 1211: "\n"
 1212: " Writes into a segment of the currently open file, using a buffer\n"
 1213: " filled with a set pattern (0xcdcdcdcd).\n"
 1214: " The write is performed asynchronously and the aio_flush command must be\n"
 1215: " used to ensure all outstanding aio requests have been completed\n"
 1216: " -P, -- use different pattern to fill file\n"
 1217: " -C, -- report statistics in a machine parsable format\n"
 1218: " -q, -- quiet mode, do not show I/O statistics\n"
 1219: "\n");
 1220: }
 1221: 
 1222: static int aio_write_f(int argc, char **argv);
 1223: 
 1224: static const cmdinfo_t aio_write_cmd = {
 1225:     .name       = "aio_write",
 1226:     .cfunc      = aio_write_f,
 1227:     .argmin     = 2,
 1228:     .argmax     = -1,
 1229:     .args       = "[-Cq] [-P pattern ] off len [len..]",
 1230:     .oneline    = "asynchronously writes a number of bytes",
 1231:     .help       = aio_write_help,
 1232: };
 1233: 
 1234: static int aio_write_f(int argc, char **argv)
 1235: {
 1236:     int nr_iov, c;
 1237:     int pattern = 0xcd;
 1238:     struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
 1239:     BlockDriverAIOCB *acb;
 1240: 
 1241:     while ((c = getopt(argc, argv, "CqP:")) != EOF) {
 1242:         switch (c) {
 1243:         case 'C':
 1244:             ctx->Cflag = 1;
 1245:             break;
 1246:         case 'q':
 1247:             ctx->qflag = 1;
 1248:             break;
 1249:         case 'P':
 1250:             pattern = parse_pattern(optarg);
 1251:             if (pattern < 0) {
 1252:                 return 0;
 1253:             }
 1254:             break;
 1255:         default:
 1256:             free(ctx);
 1257:             return command_usage(&aio_write_cmd);
 1258:         }
 1259:     }
 1260: 
 1261:     if (optind > argc - 2) {
 1262:         free(ctx);
 1263:         return command_usage(&aio_write_cmd);
 1264:     }
 1265: 
 1266:     ctx->offset = cvtnum(argv[optind]);
 1267:     if (ctx->offset < 0) {
 1268:         printf("non-numeric length argument -- %s\n", argv[optind]);
 1269:         free(ctx);
 1270:         return 0;
 1271:     }
 1272:     optind++;
 1273: 
 1274:     if (ctx->offset & 0x1ff) {
 1275:         printf("offset %" PRId64 " is not sector aligned\n",
 1276:                ctx->offset);
 1277:         free(ctx);
 1278:         return 0;
 1279:     }
 1280: 
 1281:     nr_iov = argc - optind;
 1282:     ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);
 1283: 
 1284:     gettimeofday(&ctx->t1, NULL);
 1285:     acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
 1286:                           ctx->qiov.size >> 9, aio_write_done, ctx);
 1287:     if (!acb) {
 1288:         free(ctx->buf);
 1289:         free(ctx);
 1290:         return -EIO;
 1291:     }
 1292: 
 1293:     return 0;
 1294: }
 1295: 
 1296: static int aio_flush_f(int argc, char **argv)
 1297: {
 1298:     qemu_aio_flush();
 1299:     return 0;
 1300: }
 1301: 
 1302: static const cmdinfo_t aio_flush_cmd = {
 1303:     .name       = "aio_flush",
 1304:     .cfunc      = aio_flush_f,
 1305:     .oneline    = "completes all outstanding aio requests"
 1306: };
 1307: 
 1308: static int flush_f(int argc, char **argv)
 1309: {
 1310:     bdrv_flush(bs);
 1311:     return 0;
 1312: }
 1313: 
 1314: static const cmdinfo_t flush_cmd = {
 1315:     .name       = "flush",
 1316:     .altname    = "f",
 1317:     .cfunc      = flush_f,
 1318:     .oneline    = "flush all in-core file state to disk",
 1319: };
 1320: 
 1321: static int truncate_f(int argc, char **argv)
 1322: {
 1323:     int64_t offset;
 1324:     int ret;
 1325: 
 1326:     offset = cvtnum(argv[1]);
 1327:     if (offset < 0) {
 1328:         printf("non-numeric truncate argument -- %s\n", argv[1]);
 1329:         return 0;
 1330:     }
 1331: 
 1332:     ret = bdrv_truncate(bs, offset);
 1333:     if (ret < 0) {
 1334:         printf("truncate: %s\n", strerror(-ret));
 1335:         return 0;
 1336:     }
 1337: 
 1338:     return 0;
 1339: }
 1340: 
 1341: static const cmdinfo_t truncate_cmd = {
 1342:     .name       = "truncate",
 1343:     .altname    = "t",
 1344:     .cfunc      = truncate_f,
 1345:     .argmin     = 1,
 1346:     .argmax     = 1,
 1347:     .args       = "off",
 1348:     .oneline    = "truncates the current file at the given offset",
 1349: };
 1350: 
 1351: static int length_f(int argc, char **argv)
 1352: {
 1353:     int64_t size;
 1354:     char s1[64];
 1355: 
 1356:     size = bdrv_getlength(bs);
 1357:     if (size < 0) {
 1358:         printf("getlength: %s\n", strerror(-size));
 1359:         return 0;
 1360:     }
 1361: 
 1362:     cvtstr(size, s1, sizeof(s1));
 1363:     printf("%s\n", s1);
 1364:     return 0;
 1365: }
 1366: 
 1367: 
 1368: static const cmdinfo_t length_cmd = {
 1369:     .name   = "length",
 1370:     .altname    = "l",
 1371:     .cfunc      = length_f,
 1372:     .oneline    = "gets the length of the current file",
 1373: };
 1374: 
 1375: 
 1376: static int info_f(int argc, char **argv)
 1377: {
 1378:     BlockDriverInfo bdi;
 1379:     char s1[64], s2[64];
 1380:     int ret;
 1381: 
 1382:     if (bs->drv && bs->drv->format_name) {
 1383:         printf("format name: %s\n", bs->drv->format_name);
 1384:     }
 1385:     if (bs->drv && bs->drv->protocol_name) {
 1386:         printf("format name: %s\n", bs->drv->protocol_name);
 1387:     }
 1388: 
 1389:     ret = bdrv_get_info(bs, &bdi);
 1390:     if (ret) {
 1391:         return 0;
 1392:     }
 1393: 
 1394:     cvtstr(bdi.cluster_size, s1, sizeof(s1));
 1395:     cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
 1396: 
 1397:     printf("cluster size: %s\n", s1);
 1398:     printf("vm state offset: %s\n", s2);
 1399: 
 1400:     return 0;
 1401: }
 1402: 
 1403: 
 1404: 
 1405: static const cmdinfo_t info_cmd = {
 1406:     .name       = "info",
 1407:     .altname    = "i",
 1408:     .cfunc      = info_f,
 1409:     .oneline    = "prints information about the current file",
 1410: };
 1411: 
 1412: static void discard_help(void)
 1413: {
 1414:     printf(
 1415: "\n"
 1416: " discards a range of bytes from the given offset\n"
 1417: "\n"
 1418: " Example:\n"
 1419: " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
 1420: "\n"
 1421: " Discards a segment of the currently open file.\n"
 1422: " -C, -- report statistics in a machine parsable format\n"
 1423: " -q, -- quiet mode, do not show I/O statistics\n"
 1424: "\n");
 1425: }
 1426: 
 1427: static int discard_f(int argc, char **argv);
 1428: 
 1429: static const cmdinfo_t discard_cmd = {
 1430:     .name       = "discard",
 1431:     .altname    = "d",
 1432:     .cfunc      = discard_f,
 1433:     .argmin     = 2,
 1434:     .argmax     = -1,
 1435:     .args       = "[-Cq] off len",
 1436:     .oneline    = "discards a number of bytes at a specified offset",
 1437:     .help       = discard_help,
 1438: };
 1439: 
 1440: static int discard_f(int argc, char **argv)
 1441: {
 1442:     struct timeval t1, t2;
 1443:     int Cflag = 0, qflag = 0;
 1444:     int c, ret;
 1445:     int64_t offset;
 1446:     int count;
 1447: 
 1448:     while ((c = getopt(argc, argv, "Cq")) != EOF) {
 1449:         switch (c) {
 1450:         case 'C':
 1451:             Cflag = 1;
 1452:             break;
 1453:         case 'q':
 1454:             qflag = 1;
 1455:             break;
 1456:         default:
 1457:             return command_usage(&discard_cmd);
 1458:         }
 1459:     }
 1460: 
 1461:     if (optind != argc - 2) {
 1462:         return command_usage(&discard_cmd);
 1463:     }
 1464: 
 1465:     offset = cvtnum(argv[optind]);
 1466:     if (offset < 0) {
 1467:         printf("non-numeric length argument -- %s\n", argv[optind]);
 1468:         return 0;
 1469:     }
 1470: 
 1471:     optind++;
 1472:     count = cvtnum(argv[optind]);
 1473:     if (count < 0) {
 1474:         printf("non-numeric length argument -- %s\n", argv[optind]);
 1475:         return 0;
 1476:     }
 1477: 
 1478:     gettimeofday(&t1, NULL);
 1479:     ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
 1480:                        count >> BDRV_SECTOR_BITS);
 1481:     gettimeofday(&t2, NULL);
 1482: 
 1483:     if (ret < 0) {
 1484:         printf("discard failed: %s\n", strerror(-ret));
 1485:         goto out;
 1486:     }
 1487: 
 1488:     /* Finally, report back -- -C gives a parsable format */
 1489:     if (!qflag) {
 1490:         t2 = tsub(t2, t1);
 1491:         print_report("discard", &t2, offset, count, count, 1, Cflag);
 1492:     }
 1493: 
 1494: out:
 1495:     return 0;
 1496: }
 1497: 
 1498: static int alloc_f(int argc, char **argv)
 1499: {
 1500:     int64_t offset;
 1501:     int nb_sectors, remaining;
 1502:     char s1[64];
 1503:     int num, sum_alloc;
 1504:     int ret;
 1505: 
 1506:     offset = cvtnum(argv[1]);
 1507:     if (offset & 0x1ff) {
 1508:         printf("offset %" PRId64 " is not sector aligned\n",
 1509:                offset);
 1510:         return 0;
 1511:     }
 1512: 
 1513:     if (argc == 3) {
 1514:         nb_sectors = cvtnum(argv[2]);
 1515:     } else {
 1516:         nb_sectors = 1;
 1517:     }
 1518: 
 1519:     remaining = nb_sectors;
 1520:     sum_alloc = 0;
 1521:     while (remaining) {
 1522:         ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
 1523:         remaining -= num;
 1524:         if (ret) {
 1525:             sum_alloc += num;
 1526:         }
 1527:     }
 1528: 
 1529:     cvtstr(offset, s1, sizeof(s1));
 1530: 
 1531:     printf("%d/%d sectors allocated at offset %s\n",
 1532:            sum_alloc, nb_sectors, s1);
 1533:     return 0;
 1534: }
 1535: 
 1536: static const cmdinfo_t alloc_cmd = {
 1537:     .name       = "alloc",
 1538:     .altname    = "a",
 1539:     .argmin     = 1,
 1540:     .argmax     = 2,
 1541:     .cfunc      = alloc_f,
 1542:     .args       = "off [sectors]",
 1543:     .oneline    = "checks if a sector is present in the file",
 1544: };
 1545: 
 1546: static int map_f(int argc, char **argv)
 1547: {
 1548:     int64_t offset;
 1549:     int64_t nb_sectors;
 1550:     char s1[64];
 1551:     int num, num_checked;
 1552:     int ret;
 1553:     const char *retstr;
 1554: 
 1555:     offset = 0;
 1556:     nb_sectors = bs->total_sectors;
 1557: 
 1558:     do {
 1559:         num_checked = MIN(nb_sectors, INT_MAX);
 1560:         ret = bdrv_is_allocated(bs, offset, num_checked, &num);
 1561:         retstr = ret ? "    allocated" : "not allocated";
 1562:         cvtstr(offset << 9ULL, s1, sizeof(s1));
 1563:         printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n",
 1564:                offset << 9ULL, num, num_checked, retstr, s1, ret);
 1565: 
 1566:         offset += num;
 1567:         nb_sectors -= num;
 1568:     } while (offset < bs->total_sectors);
 1569: 
 1570:     return 0;
 1571: }
 1572: 
 1573: static const cmdinfo_t map_cmd = {
 1574:        .name           = "map",
 1575:        .argmin         = 0,
 1576:        .argmax         = 0,
 1577:        .cfunc          = map_f,
 1578:        .args           = "",
 1579:        .oneline        = "prints the allocated areas of a file",
 1580: };
 1581: 
 1582: 
 1583: static int close_f(int argc, char **argv)
 1584: {
 1585:     bdrv_close(bs);
 1586:     bs = NULL;
 1587:     return 0;
 1588: }
 1589: 
 1590: static const cmdinfo_t close_cmd = {
 1591:     .name       = "close",
 1592:     .altname    = "c",
 1593:     .cfunc      = close_f,
 1594:     .oneline    = "close the current open file",
 1595: };
 1596: 
 1597: static int openfile(char *name, int flags, int growable)
 1598: {
 1599:     if (bs) {
 1600:         fprintf(stderr, "file open already, try 'help close'\n");
 1601:         return 1;
 1602:     }
 1603: 
 1604:     if (growable) {
 1605:         if (bdrv_file_open(&bs, name, flags)) {
 1606:             fprintf(stderr, "%s: can't open device %s\n", progname, name);
 1607:             return 1;
 1608:         }
 1609:     } else {
 1610:         bs = bdrv_new("hda");
 1611: 
 1612:         if (bdrv_open(bs, name, flags, NULL) < 0) {
 1613:             fprintf(stderr, "%s: can't open device %s\n", progname, name);
 1614:             bs = NULL;
 1615:             return 1;
 1616:         }
 1617:     }
 1618: 
 1619:     return 0;
 1620: }
 1621: 
 1622: static void open_help(void)
 1623: {
 1624:     printf(
 1625: "\n"
 1626: " opens a new file in the requested mode\n"
 1627: "\n"
 1628: " Example:\n"
 1629: " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
 1630: "\n"
 1631: " Opens a file for subsequent use by all of the other qemu-io commands.\n"
 1632: " -r, -- open file read-only\n"
 1633: " -s, -- use snapshot file\n"
 1634: " -n, -- disable host cache\n"
 1635: " -g, -- allow file to grow (only applies to protocols)"
 1636: "\n");
 1637: }
 1638: 
 1639: static int open_f(int argc, char **argv);
 1640: 
 1641: static const cmdinfo_t open_cmd = {
 1642:     .name       = "open",
 1643:     .altname    = "o",
 1644:     .cfunc      = open_f,
 1645:     .argmin     = 1,
 1646:     .argmax     = -1,
 1647:     .flags      = CMD_NOFILE_OK,
 1648:     .args       = "[-Crsn] [path]",
 1649:     .oneline    = "open the file specified by path",
 1650:     .help       = open_help,
 1651: };
 1652: 
 1653: static int open_f(int argc, char **argv)
 1654: {
 1655:     int flags = 0;
 1656:     int readonly = 0;
 1657:     int growable = 0;
 1658:     int c;
 1659: 
 1660:     while ((c = getopt(argc, argv, "snrg")) != EOF) {
 1661:         switch (c) {
 1662:         case 's':
 1663:             flags |= BDRV_O_SNAPSHOT;
 1664:             break;
 1665:         case 'n':
 1666:             flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
 1667:             break;
 1668:         case 'r':
 1669:             readonly = 1;
 1670:             break;
 1671:         case 'g':
 1672:             growable = 1;
 1673:             break;
 1674:         default:
 1675:             return command_usage(&open_cmd);
 1676:         }
 1677:     }
 1678: 
 1679:     if (!readonly) {
 1680:         flags |= BDRV_O_RDWR;
 1681:     }
 1682: 
 1683:     if (optind != argc - 1) {
 1684:         return command_usage(&open_cmd);
 1685:     }
 1686: 
 1687:     return openfile(argv[optind], flags, growable);
 1688: }
 1689: 
 1690: static int init_args_command(int index)
 1691: {
 1692:     /* only one device allowed so far */
 1693:     if (index >= 1) {
 1694:         return 0;
 1695:     }
 1696:     return ++index;
 1697: }
 1698: 
 1699: static int init_check_command(const cmdinfo_t *ct)
 1700: {
 1701:     if (ct->flags & CMD_FLAG_GLOBAL) {
 1702:         return 1;
 1703:     }
 1704:     if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
 1705:         fprintf(stderr, "no file open, try 'help open'\n");
 1706:         return 0;
 1707:     }
 1708:     return 1;
 1709: }
 1710: 
 1711: static void usage(const char *name)
 1712: {
 1713:     printf(
 1714: "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
 1715: "QEMU Disk exerciser\n"
 1716: "\n"
 1717: "  -c, --cmd            command to execute\n"
 1718: "  -r, --read-only      export read-only\n"
 1719: "  -s, --snapshot       use snapshot file\n"
 1720: "  -n, --nocache        disable host cache\n"
 1721: "  -g, --growable       allow file to grow (only applies to protocols)\n"
 1722: "  -m, --misalign       misalign allocations for O_DIRECT\n"
 1723: "  -k, --native-aio     use kernel AIO implementation (on Linux only)\n"
 1724: "  -h, --help           display this help and exit\n"
 1725: "  -V, --version        output version information and exit\n"
 1726: "\n",
 1727:     name);
 1728: }
 1729: 
 1730: 
 1731: int main(int argc, char **argv)
 1732: {
 1733:     int readonly = 0;
 1734:     int growable = 0;
 1735:     const char *sopt = "hVc:rsnmgk";
 1736:     const struct option lopt[] = {
 1737:         { "help", 0, NULL, 'h' },
 1738:         { "version", 0, NULL, 'V' },
 1739:         { "offset", 1, NULL, 'o' },
 1740:         { "cmd", 1, NULL, 'c' },
 1741:         { "read-only", 0, NULL, 'r' },
 1742:         { "snapshot", 0, NULL, 's' },
 1743:         { "nocache", 0, NULL, 'n' },
 1744:         { "misalign", 0, NULL, 'm' },
 1745:         { "growable", 0, NULL, 'g' },
 1746:         { "native-aio", 0, NULL, 'k' },
 1747:         { NULL, 0, NULL, 0 }
 1748:     };
 1749:     int c;
 1750:     int opt_index = 0;
 1751:     int flags = 0;
 1752: 
 1753:     progname = basename(argv[0]);
 1754: 
 1755:     while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
 1756:         switch (c) {
 1757:         case 's':
 1758:             flags |= BDRV_O_SNAPSHOT;
 1759:             break;
 1760:         case 'n':
 1761:             flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
 1762:             break;
 1763:         case 'c':
 1764:             add_user_command(optarg);
 1765:             break;
 1766:         case 'r':
 1767:             readonly = 1;
 1768:             break;
 1769:         case 'm':
 1770:             misalign = 1;
 1771:             break;
 1772:         case 'g':
 1773:             growable = 1;
 1774:             break;
 1775:         case 'k':
 1776:             flags |= BDRV_O_NATIVE_AIO;
 1777:             break;
 1778:         case 'V':
 1779:             printf("%s version %s\n", progname, VERSION);
 1780:             exit(0);
 1781:         case 'h':
 1782:             usage(progname);
 1783:             exit(0);
 1784:         default:
 1785:             usage(progname);
 1786:             exit(1);
 1787:         }
 1788:     }
 1789: 
 1790:     if ((argc - optind) > 1) {
 1791:         usage(progname);
 1792:         exit(1);
 1793:     }
 1794: 
 1795:     bdrv_init();
 1796: 
 1797:     /* initialize commands */
 1798:     quit_init();
 1799:     help_init();
 1800:     add_command(&open_cmd);
 1801:     add_command(&close_cmd);
 1802:     add_command(&read_cmd);
 1803:     add_command(&readv_cmd);
 1804:     add_command(&write_cmd);
 1805:     add_command(&writev_cmd);
 1806:     add_command(&multiwrite_cmd);
 1807:     add_command(&aio_read_cmd);
 1808:     add_command(&aio_write_cmd);
 1809:     add_command(&aio_flush_cmd);
 1810:     add_command(&flush_cmd);
 1811:     add_command(&truncate_cmd);
 1812:     add_command(&length_cmd);
 1813:     add_command(&info_cmd);
 1814:     add_command(&discard_cmd);
 1815:     add_command(&alloc_cmd);
 1816:     add_command(&map_cmd);
 1817: 
 1818:     add_args_command(init_args_command);
 1819:     add_check_command(init_check_command);
 1820: 
 1821:     /* open the device */
 1822:     if (!readonly) {
 1823:         flags |= BDRV_O_RDWR;
 1824:     }
 1825: 
 1826:     if ((argc - optind) == 1) {
 1827:         openfile(argv[optind], flags, growable);
 1828:     }
 1829:     command_loop();
 1830: 
 1831:     /*
 1832:      * Make sure all outstanding requests get flushed the program exits.
 1833:      */
 1834:     qemu_aio_flush();
 1835: 
 1836:     if (bs) {
 1837:         bdrv_close(bs);
 1838:     }
 1839:     return 0;
 1840: }

unix.superglobalmegacorp.com