Commit db933fbe authored by Lidong Chen's avatar Lidong Chen Committed by Max Reitz
Browse files

qemu-img: use blk_co_pwrite_zeroes for zero sectors when compressed



When the buffer is zero, blk_co_pwrite_zeroes is more effective than
blk_co_pwritev with BDRV_REQ_WRITE_COMPRESSED. This patch can reduce
the time for converting qcow2 images with lots of zero data.

Signed-off-by: default avatarLidong Chen <lidongchen@tencent.com>
Message-id: 1493261907-18734-1-git-send-email-lidongchen@tencent.com
Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
parent 9f1b92ad
Loading
Loading
Loading
Loading
+14 −30
Original line number Diff line number Diff line
@@ -1649,6 +1649,8 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,

    while (nb_sectors > 0) {
        int n = nb_sectors;
        BdrvRequestFlags flags = s->compressed ? BDRV_REQ_WRITE_COMPRESSED : 0;

        switch (status) {
        case BLK_BACKING_FILE:
            /* If we have a backing file, leave clusters unallocated that are
@@ -1658,43 +1660,24 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
            break;

        case BLK_DATA:
            /* We must always write compressed clusters as a whole, so don't
             * try to find zeroed parts in the buffer. We can only save the
             * write if the buffer is completely zeroed and we're allowed to
             * keep the target sparse. */
            if (s->compressed) {
                if (s->has_zero_init && s->min_sparse &&
                    buffer_is_zero(buf, n * BDRV_SECTOR_SIZE))
                {
                    assert(!s->target_has_backing);
                    break;
                }

                iov.iov_base = buf;
                iov.iov_len = n << BDRV_SECTOR_BITS;
                qemu_iovec_init_external(&qiov, &iov, 1);

                ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
                                     n << BDRV_SECTOR_BITS, &qiov,
                                     BDRV_REQ_WRITE_COMPRESSED);
                if (ret < 0) {
                    return ret;
                }
                break;
            }

            /* If there is real non-zero data or we're told to keep the target
             * fully allocated (-S 0), we must write it. Otherwise we can treat
             * it as zero sectors. */
            /* If we're told to keep the target fully allocated (-S 0) or there
             * is real non-zero data, we must write it. Otherwise we can treat
             * it as zero sectors.
             * Compressed clusters need to be written as a whole, so in that
             * case we can only save the write if the buffer is completely
             * zeroed. */
            if (!s->min_sparse ||
                is_allocated_sectors_min(buf, n, &n, s->min_sparse))
                (!s->compressed &&
                 is_allocated_sectors_min(buf, n, &n, s->min_sparse)) ||
                (s->compressed &&
                 !buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)))
            {
                iov.iov_base = buf;
                iov.iov_len = n << BDRV_SECTOR_BITS;
                qemu_iovec_init_external(&qiov, &iov, 1);

                ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
                                     n << BDRV_SECTOR_BITS, &qiov, 0);
                                     n << BDRV_SECTOR_BITS, &qiov, flags);
                if (ret < 0) {
                    return ret;
                }
@@ -1704,6 +1687,7 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,

        case BLK_ZERO:
            if (s->has_zero_init) {
                assert(!s->target_has_backing);
                break;
            }
            ret = blk_co_pwrite_zeroes(s->target,