mirror of
https://github.com/xemu-project/xemu.git
synced 2025-02-05 11:39:54 +00:00
qcow2: refactor data compression
Make a separate function for compression to be parallelized later. - use .avail_out field instead of .next_out to calculate size of compressed data. It looks more natural and it allows to keep dest to be void pointer - set avail_out to be at least one byte less than input, to be sure avoid inefficient compression earlier Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
88481329c0
commit
2714f13d69
@ -23,11 +23,14 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#define ZLIB_CONST
|
||||
#include <zlib.h>
|
||||
|
||||
#include "block/block_int.h"
|
||||
#include "block/qdict.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qemu/module.h"
|
||||
#include <zlib.h>
|
||||
#include "qcow2.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
@ -3650,6 +3653,48 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* qcow2_compress()
|
||||
*
|
||||
* @dest - destination buffer, at least of @size-1 bytes
|
||||
* @src - source buffer, @size bytes
|
||||
*
|
||||
* Returns: compressed size on success
|
||||
* -1 if compression is inefficient
|
||||
* -2 on any other error
|
||||
*/
|
||||
static ssize_t qcow2_compress(void *dest, const void *src, size_t size)
|
||||
{
|
||||
ssize_t ret;
|
||||
z_stream strm;
|
||||
|
||||
/* 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) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* strm.next_in is not const in old zlib versions, such as those used on
|
||||
* OpenBSD/NetBSD, so cast the const away */
|
||||
strm.avail_in = size;
|
||||
strm.next_in = (void *) src;
|
||||
strm.avail_out = size - 1;
|
||||
strm.next_out = dest;
|
||||
|
||||
ret = deflate(&strm, Z_FINISH);
|
||||
if (ret == Z_STREAM_END) {
|
||||
ret = size - 1 - strm.avail_out;
|
||||
} else {
|
||||
ret = (ret == Z_OK ? -1 : -2);
|
||||
}
|
||||
|
||||
deflateEnd(&strm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* XXX: put compressed sectors first, then all the cluster aligned
|
||||
tables to avoid losing bytes in alignment */
|
||||
static coroutine_fn int
|
||||
@ -3659,8 +3704,8 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
QEMUIOVector hd_qiov;
|
||||
struct iovec iov;
|
||||
z_stream strm;
|
||||
int ret, out_len;
|
||||
int ret;
|
||||
size_t out_len;
|
||||
uint8_t *buf, *out_buf;
|
||||
int64_t cluster_offset;
|
||||
|
||||
@ -3694,32 +3739,11 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
|
||||
|
||||
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) {
|
||||
out_len = qcow2_compress(out_buf, buf, s->cluster_size);
|
||||
if (out_len == -2) {
|
||||
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) {
|
||||
} else if (out_len == -1) {
|
||||
/* could not compress: write normal cluster */
|
||||
ret = qcow2_co_pwritev(bs, offset, bytes, qiov, 0);
|
||||
if (ret < 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user