Revision a22f123c qemu-img.c

b/qemu-img.c
82 82
           "       rebasing in this case (useful for renaming the backing file)\n"
83 83
           "  '-h' with or without a command shows this help and lists the supported formats\n"
84 84
           "  '-p' show progress of command (only certain commands)\n"
85
           "  '-S' indicates the consecutive number of bytes that must contain only zeros\n"
86
           "       for qemu-img to create a sparse image during conversion\n"
85 87
           "\n"
86 88
           "Parameters to snapshot subcommand:\n"
87 89
           "  'snapshot' is the name of the snapshot to create, apply or delete\n"
......
571 573
}
572 574

  
573 575
/*
576
 * Like is_allocated_sectors, but if the buffer starts with a used sector,
577
 * up to 'min' consecutive sectors containing zeros are ignored. This avoids
578
 * breaking up write requests for only small sparse areas.
579
 */
580
static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
581
    int min)
582
{
583
    int ret;
584
    int num_checked, num_used;
585

  
586
    if (n < min) {
587
        min = n;
588
    }
589

  
590
    ret = is_allocated_sectors(buf, n, pnum);
591
    if (!ret) {
592
        return ret;
593
    }
594

  
595
    num_used = *pnum;
596
    buf += BDRV_SECTOR_SIZE * *pnum;
597
    n -= *pnum;
598
    num_checked = num_used;
599

  
600
    while (n > 0) {
601
        ret = is_allocated_sectors(buf, n, pnum);
602

  
603
        buf += BDRV_SECTOR_SIZE * *pnum;
604
        n -= *pnum;
605
        num_checked += *pnum;
606
        if (ret) {
607
            num_used = num_checked;
608
        } else if (*pnum >= min) {
609
            break;
610
        }
611
    }
612

  
613
    *pnum = num_used;
614
    return 1;
615
}
616

  
617
/*
574 618
 * Compares two buffers sector by sector. Returns 0 if the first sector of both
575 619
 * buffers matches, non-zero otherwise.
576 620
 *
......
620 664
    char *options = NULL;
621 665
    const char *snapshot_name = NULL;
622 666
    float local_progress;
667
    int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
623 668

  
624 669
    fmt = NULL;
625 670
    out_fmt = "raw";
......
627 672
    out_baseimg = NULL;
628 673
    compress = 0;
629 674
    for(;;) {
630
        c = getopt(argc, argv, "f:O:B:s:hce6o:pt:");
675
        c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:");
631 676
        if (c == -1) {
632 677
            break;
633 678
        }
......
662 707
        case 's':
663 708
            snapshot_name = optarg;
664 709
            break;
710
        case 'S':
711
        {
712
            int64_t sval;
713
            sval = strtosz_suffix(optarg, NULL, STRTOSZ_DEFSUFFIX_B);
714
            if (sval < 0) {
715
                error_report("Invalid minimum zero buffer size for sparse output specified");
716
                return 1;
717
            }
718

  
719
            min_sparse = sval / BDRV_SECTOR_SIZE;
720
            break;
721
        }
665 722
        case 'p':
666 723
            progress = 1;
667 724
            break;
......
970 1027
                   sectors that are entirely 0, since whatever data was
971 1028
                   already there is garbage, not 0s. */
972 1029
                if (!has_zero_init || out_baseimg ||
973
                    is_allocated_sectors(buf1, n, &n1)) {
1030
                    is_allocated_sectors_min(buf1, n, &n1, min_sparse)) {
974 1031
                    ret = bdrv_write(out_bs, sector_num, buf1, n1);
975 1032
                    if (ret < 0) {
976 1033
                        error_report("error while writing sector %" PRId64

Also available in: Unified diff