qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,

                            uint64_t bytes, QEMUIOVector *qiov)

{

    BDRVQcow2State *s = bs->opaque;

    QEMUIOVector hd_qiov;

    struct iovec iov;

    z_stream strm;

    int ret, out_len;

    uint8_t *buf, *out_buf;

    uint64_t cluster_offset;



    if (bytes == 0) {

        /* align end of file to a sector boundary to ease reading with

           sector based I/Os */

        cluster_offset = bdrv_getlength(bs->file->bs);

        return bdrv_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF, NULL);

    }



    buf = qemu_blockalign(bs, s->cluster_size);

    if (bytes != s->cluster_size) {

        if (bytes > s->cluster_size ||

            offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)

        {

            qemu_vfree(buf);

            return -EINVAL;

        }

        /* Zero-pad last write if image size is not cluster aligned */

        memset(buf + bytes, 0, s->cluster_size - bytes);

    }

    qemu_iovec_to_buf(qiov, 0, buf, bytes);



    out_buf = g_malloc(s->cluster_size);



    /* best compression, small window, no zlib header */

    memset(&strm, 0, sizeof(strm));

    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,

                       Z_DEFLATED, -12,

                       9, Z_DEFAULT_STRATEGY);

    if (ret != 0) {

        ret = -EINVAL;

        goto fail;

    }



    strm.avail_in = s->cluster_size;

    strm.next_in = (uint8_t *)buf;

    strm.avail_out = s->cluster_size;

    strm.next_out = out_buf;



    ret = deflate(&strm, Z_FINISH);

    if (ret != Z_STREAM_END && ret != Z_OK) {

        deflateEnd(&strm);

        ret = -EINVAL;

        goto fail;

    }

    out_len = strm.next_out - out_buf;



    deflateEnd(&strm);



    if (ret != Z_STREAM_END || out_len >= s->cluster_size) {

        /* could not compress: write normal cluster */

        ret = qcow2_co_pwritev(bs, offset, bytes, qiov, 0);

        if (ret < 0) {

            goto fail;

        }

        goto success;

    }



    qemu_co_mutex_lock(&s->lock);

    cluster_offset =

        qcow2_alloc_compressed_cluster_offset(bs, offset, out_len);

    if (!cluster_offset) {

        qemu_co_mutex_unlock(&s->lock);

        ret = -EIO;

        goto fail;

    }

    cluster_offset &= s->cluster_offset_mask;



    ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);

    qemu_co_mutex_unlock(&s->lock);

    if (ret < 0) {

        goto fail;

    }



    iov = (struct iovec) {

        .iov_base   = out_buf,

        .iov_len    = out_len,

    };

    qemu_iovec_init_external(&hd_qiov, &iov, 1);



    BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);

    ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);

    if (ret < 0) {

        goto fail;

    }

success:

    ret = 0;

fail:

    qemu_vfree(buf);

    g_free(out_buf);

    return ret;

}

qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,

                            uint64_t bytes, QEMUIOVector *qiov)

{

    BDRVQcow2State *s = bs->opaque;

    QEMUIOVector hd_qiov;

    struct iovec iov;

    z_stream strm;

    int ret, out_len;

    uint8_t *buf, *out_buf;

    uint64_t cluster_offset;



    if (bytes == 0) {

        



        cluster_offset = bdrv_getlength(bs->file->bs);

        return bdrv_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF, NULL);

    }



    buf = qemu_blockalign(bs, s->cluster_size);

    if (bytes != s->cluster_size) {

        if (bytes > s->cluster_size ||

            offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)

        {

            qemu_vfree(buf);

            return -EINVAL;

        }

        

        memset(buf + bytes, 0, s->cluster_size - bytes);

    }

    qemu_iovec_to_buf(qiov, 0, buf, bytes);



    out_buf = g_malloc(s->cluster_size);



    

    memset(&strm, 0, sizeof(strm));

    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,

                       Z_DEFLATED, -12,

                       9, Z_DEFAULT_STRATEGY);

    if (ret != 0) {

        ret = -EINVAL;

        goto fail;

    }



    strm.avail_in = s->cluster_size;

    strm.next_in = (uint8_t *)buf;

    strm.avail_out = s->cluster_size;

    strm.next_out = out_buf;



    ret = deflate(&strm, Z_FINISH);

    if (ret != Z_STREAM_END && ret != Z_OK) {

        deflateEnd(&strm);

        ret = -EINVAL;

        goto fail;

    }

    out_len = strm.next_out - out_buf;



    deflateEnd(&strm);



    if (ret != Z_STREAM_END || out_len >= s->cluster_size) {

        

        ret = qcow2_co_pwritev(bs, offset, bytes, qiov, 0);

        if (ret < 0) {

            goto fail;

        }

        goto success;

    }



    qemu_co_mutex_lock(&s->lock);

    cluster_offset =

        qcow2_alloc_compressed_cluster_offset(bs, offset, out_len);

    if (!cluster_offset) {

        qemu_co_mutex_unlock(&s->lock);

        ret = -EIO;

        goto fail;

    }

    cluster_offset &= s->cluster_offset_mask;



    ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);

    qemu_co_mutex_unlock(&s->lock);

    if (ret < 0) {

        goto fail;

    }



    iov = (struct iovec) {

        .iov_base   = out_buf,

        .iov_len    = out_len,

    };

    qemu_iovec_init_external(&hd_qiov, &iov, 1);



    BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);

    ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);

    if (ret < 0) {

        goto fail;

    }

success:

    ret = 0;

fail:

    qemu_vfree(buf);

    g_free(out_buf);

    return ret;

}

    uint64_t cluster_offset;
FUNC_0(BlockDriverState *VAR_0, uint64_t VAR_1,

                            uint64_t VAR_2, QEMUIOVector *VAR_3)

{

    BDRVQcow2State *s = VAR_0->opaque;

    QEMUIOVector hd_qiov;

    struct iovec VAR_4;

    z_stream strm;

    int VAR_5, VAR_6;

    uint8_t *buf, *out_buf;

    uint64_t cluster_offset;



    if (VAR_2 == 0) {

        



        cluster_offset = bdrv_getlength(VAR_0->file->VAR_0);

        return bdrv_truncate(VAR_0->file, cluster_offset, PREALLOC_MODE_OFF, NULL);

    }



    buf = qemu_blockalign(VAR_0, s->cluster_size);

    if (VAR_2 != s->cluster_size) {

        if (VAR_2 > s->cluster_size ||

            VAR_1 + VAR_2 != VAR_0->total_sectors << BDRV_SECTOR_BITS)

        {

            qemu_vfree(buf);

            return -EINVAL;

        }

        

        memset(buf + VAR_2, 0, s->cluster_size - VAR_2);

    }

    qemu_iovec_to_buf(VAR_3, 0, buf, VAR_2);



    out_buf = g_malloc(s->cluster_size);



    

    memset(&strm, 0, sizeof(strm));

    VAR_5 = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,

                       Z_DEFLATED, -12,

                       9, Z_DEFAULT_STRATEGY);

    if (VAR_5 != 0) {

        VAR_5 = -EINVAL;

        goto fail;

    }



    strm.avail_in = s->cluster_size;

    strm.next_in = (uint8_t *)buf;

    strm.avail_out = s->cluster_size;

    strm.next_out = out_buf;



    VAR_5 = deflate(&strm, Z_FINISH);

    if (VAR_5 != Z_STREAM_END && VAR_5 != Z_OK) {

        deflateEnd(&strm);

        VAR_5 = -EINVAL;

        goto fail;

    }

    VAR_6 = strm.next_out - out_buf;



    deflateEnd(&strm);



    if (VAR_5 != Z_STREAM_END || VAR_6 >= s->cluster_size) {

        

        VAR_5 = qcow2_co_pwritev(VAR_0, VAR_1, VAR_2, VAR_3, 0);

        if (VAR_5 < 0) {

            goto fail;

        }

        goto success;

    }



    qemu_co_mutex_lock(&s->lock);

    cluster_offset =

        qcow2_alloc_compressed_cluster_offset(VAR_0, VAR_1, VAR_6);

    if (!cluster_offset) {

        qemu_co_mutex_unlock(&s->lock);

        VAR_5 = -EIO;

        goto fail;

    }

    cluster_offset &= s->cluster_offset_mask;



    VAR_5 = qcow2_pre_write_overlap_check(VAR_0, 0, cluster_offset, VAR_6);

    qemu_co_mutex_unlock(&s->lock);

    if (VAR_5 < 0) {

        goto fail;

    }



    VAR_4 = (struct iovec) {

        .iov_base   = out_buf,

        .iov_len    = VAR_6,

    };

    qemu_iovec_init_external(&hd_qiov, &VAR_4, 1);



    BLKDBG_EVENT(VAR_0->file, BLKDBG_WRITE_COMPRESSED);

    VAR_5 = bdrv_co_pwritev(VAR_0->file, cluster_offset, VAR_6, &hd_qiov, 0);

    if (VAR_5 < 0) {

        goto fail;

    }

success:

    VAR_5 = 0;

fail:

    qemu_vfree(buf);

    g_free(out_buf);

    return VAR_5;

}

FUNC_0(BlockDriverState *VAR_0, uint64_t VAR_1,
uint64_t VAR_2, QEMUIOVector *VAR_3)
{ BDRVQcow2State *s = VAR_0->opaque; QEMUIOVector hd_qiov; struct iovec VAR_4; z_stream strm; int VAR_5, VAR_6; uint8_t *buf, *out_buf; uint64_t cluster_offset; if (VAR_2 == 0) { cluster_offset = bdrv_getlength(VAR_0->file->VAR_0); return bdrv_truncate(VAR_0->file, cluster_offset, PREALLOC_MODE_OFF, NULL); } buf = qemu_blockalign(VAR_0, s->cluster_size); if (VAR_2 != s->cluster_size) { if (VAR_2 > s->cluster_size ||
VAR_1 + VAR_2 != VAR_0->total_sectors << BDRV_SECTOR_BITS)
{ qemu_vfree(buf); return -EINVAL; } memset(buf + VAR_2, 0, s->cluster_size - VAR_2); } qemu_iovec_to_buf(VAR_3, 0, buf, VAR_2); out_buf = g_malloc(s->cluster_size); memset(&strm, 0, sizeof(strm)); VAR_5 = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, -12,
9, Z_DEFAULT_STRATEGY); if (VAR_5 != 0) { VAR_5 = -EINVAL; goto fail; } strm.avail_in = s->cluster_size; strm.next_in = (uint8_t *)buf; strm.avail_out = s->cluster_size; strm.next_out = out_buf; VAR_5 = deflate(&strm, Z_FINISH); if (VAR_5 != Z_STREAM_END && VAR_5 != Z_OK) { deflateEnd(&strm); VAR_5 = -EINVAL; goto fail; } VAR_6 = strm.next_out - out_buf; deflateEnd(&strm); if (VAR_5 != Z_STREAM_END || VAR_6 >= s->cluster_size) { VAR_5 = qcow2_co_pwritev(VAR_0, VAR_1, VAR_2, VAR_3, 0); if (VAR_5 < 0) { goto fail; } goto success; } qemu_co_mutex_lock(&s->lock); cluster_offset =
qcow2_alloc_compressed_cluster_offset(VAR_0, VAR_1, VAR_6); if (!cluster_offset) { qemu_co_mutex_unlock(&s->lock); VAR_5 = -EIO; goto fail; } cluster_offset &= s->cluster_offset_mask; VAR_5 = qcow2_pre_write_overlap_check(VAR_0, 0, cluster_offset, VAR_6); qemu_co_mutex_unlock(&s->lock); if (VAR_5 < 0) { goto fail; } VAR_4 = (struct iovec) { .iov_base   = out_buf,
.iov_len    = VAR_6,
}; qemu_iovec_init_external(&hd_qiov, &VAR_4, 1); BLKDBG_EVENT(VAR_0->file, BLKDBG_WRITE_COMPRESSED); VAR_5 = bdrv_co_pwritev(VAR_0->file, cluster_offset, VAR_6, &hd_qiov, 0); if (VAR_5 < 0) { goto fail; } success:
VAR_5 = 0; fail:
qemu_vfree(buf); g_free(out_buf); return VAR_5; }