From nobody Sat Feb 7 10:08:02 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com ARC-Seal: i=1; a=rsa-sha256; t=1559054494; cv=none; d=zoho.com; s=zohoarc; b=Ly+o68VvbalPLvD92G0qoPMSIH7kMM5EJTf9us++KoLLDwh8gWqFj/VfhI0kUZcT2xNuNotHKkJmvOhbVj+uVklf/hXj/l/VuepE3YLX+CDEvvSiGESq9Yfc4Sq6UKkBzJQfN91dD44P+7liHJ5qRe9DSdnKEecYVMi2UHlsAOE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559054494; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=8gdqjmaM5j4NJM6tctURoN6rOW66hd9TcsNdRCMxcyY=; b=RSeEA+SoIrHrYPiXcsnhcK3+moXaOc5U7vpoAk9U6hKDLUXG/UhIPjzL9Ns714otRBXD4Dxfzbyolnj7/crOmM8NK5OpWyEmDF2vW5PTRdj5yhpzDAELXSoo/Ae+8MBCTAptdTAe0JZ/CWcLQXC4tT6gXEqkDVp5oVwvAE+G+qs= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559054494335728.2806508975065; Tue, 28 May 2019 07:41:34 -0700 (PDT) Received: from localhost ([127.0.0.1]:36048 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVdI7-00040O-Ay for importer@patchew.org; Tue, 28 May 2019 10:41:27 -0400 Received: from eggs.gnu.org ([209.51.188.92]:50816) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVdFj-0002QU-5w for qemu-devel@nongnu.org; Tue, 28 May 2019 10:39:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hVdFX-0007tz-0b for qemu-devel@nongnu.org; Tue, 28 May 2019 10:38:49 -0400 Received: from relay.sw.ru ([185.231.240.75]:46362) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hVdFR-0006uA-PB; Tue, 28 May 2019 10:38:42 -0400 Received: from [10.94.4.71] (helo=dptest2.qa.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1hVdEM-0004ye-6p; Tue, 28 May 2019 17:37:34 +0300 From: Denis Plotnikov To: kwolf@redhat.com, mreitz@redhat.com, eblake@redhat.com, armbru@redhat.com, qemu-block@nongnu.org Date: Tue, 28 May 2019 17:37:26 +0300 Message-Id: <20190528143727.10529-3-dplotnikov@virtuozzo.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20190528143727.10529-1-dplotnikov@virtuozzo.com> References: <20190528143727.10529-1-dplotnikov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v0 2/3] qcow2: add compression type processing X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: vsementsov@virtuozzo.com, qemu-devel@nongnu.org, den@virtuozzo.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" With the patch, qcow2 is able to process image compression type defined in the image header and choose the corresponding method for clusters compressing. Also, it rework the cluster compression code for adding more compression types. Signed-off-by: Denis Plotnikov --- block/qcow2.c | 103 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 11 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index c4b5b93408..90f15cc3c9 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -400,11 +400,39 @@ static int qcow2_read_extensions(BlockDriverState *bs= , uint64_t start_offset, break; =20 case QCOW2_EXT_MAGIC_COMPRESSION_TYPE: + /* Compression type always goes with the compression type bit = set */ + if (!(s->incompatible_features & QCOW2_INCOMPAT_COMPRESSION_TY= PE)) { + error_setg(errp, + "compression_type_ext: " + "expect compression type bit set"); + return -EINVAL; + } + + ret =3D bdrv_pread(bs->file, offset, &s->compression_type, ext= .len); + s->compression_type =3D be32_to_cpu(s->compression_type); + + if (ret < 0) { + error_setg_errno(errp, -ret, + "ERROR: Could not read compression type"); + return ret; + } + /* - * Setting compression type to BDRVQcow2State->compression_type - * from the image header is going to be here + * The default compression type is not allowed when the extens= ion + * is present. ZLIB is used as the default compression type. + * When compression type extension header is present then + * compression_type should have a value different from the def= ault. */ - break; + if (s->compression_type =3D=3D QCOW2_COMPRESSION_TYPE_ZLIB) { + error_setg(errp, + "compression_type_ext:" + "invalid compression type %d", + QCOW2_COMPRESSION_TYPE_ZLIB); + } +#ifdef DEBUG_EXT + printf("Qcow2: image compression type %s\n", s->compression_ty= pe); +#endif + break; =20 case QCOW2_EXT_MAGIC_DATA_FILE: { @@ -1492,6 +1520,9 @@ static int coroutine_fn qcow2_do_open(BlockDriverStat= e *bs, QDict *options, QLIST_INIT(&s->cluster_allocs); QTAILQ_INIT(&s->discards); =20 + /* Set default compression type */ + s->compression_type =3D QCOW2_COMPRESSION_TYPE_ZLIB; + /* read qcow2 extensions */ if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL, flags, &update_header, &local_err)) { @@ -1500,6 +1531,34 @@ static int coroutine_fn qcow2_do_open(BlockDriverSta= te *bs, QDict *options, goto fail; } =20 + /* + * The compression type is set on the extension header processing + * if the compression type extension header is present. + * When the compression type is different from ZLIB (default) there + * should be both the compression type bit and the compression + * type extension header set. When the ZLIB (default) compression + * type is used there should be neither the compression type bit nor + * the compression type extension header set. + */ + + if ((s->incompatible_features & QCOW2_INCOMPAT_COMPRESSION_TYPE) & + (s->compression_type =3D=3D QCOW2_COMPRESSION_TYPE_ZLIB)) { + error_setg(errp, "Illegal compression type setting"); + ret =3D -EINVAL; + goto fail; + } + + /* Check available compression types */ + switch (s->compression_type) { + case QCOW2_COMPRESSION_TYPE_ZLIB: + break; + + default: + error_setg(errp, "Unknown compression type"); + ret =3D -EINVAL; + goto fail; + } + /* Open external data file */ s->data_file =3D bdrv_open_child(NULL, options, "data-file", bs, &chil= d_file, true, &local_err); @@ -3970,7 +4029,7 @@ fail: } =20 /* - * qcow2_compress() + * zlib_compress() * * @dest - destination buffer, @dest_size bytes * @src - source buffer, @src_size bytes @@ -3979,7 +4038,7 @@ fail: * -1 destination buffer is not enough to store compressed data * -2 on any other error */ -static ssize_t qcow2_compress(void *dest, size_t dest_size, +static ssize_t zlib_compress(void *dest, size_t dest_size, const void *src, size_t src_size) { ssize_t ret; @@ -4013,7 +4072,7 @@ static ssize_t qcow2_compress(void *dest, size_t dest= _size, } =20 /* - * qcow2_decompress() + * zlib_decompress() * * Decompress some data (not more than @src_size bytes) to produce exactly * @dest_size bytes. @@ -4024,7 +4083,7 @@ static ssize_t qcow2_compress(void *dest, size_t dest= _size, * Returns: 0 on success * -1 on fail */ -static ssize_t qcow2_decompress(void *dest, size_t dest_size, +static ssize_t zlib_decompress(void *dest, size_t dest_size, const void *src, size_t src_size) { int ret =3D 0; @@ -4122,16 +4181,38 @@ static ssize_t coroutine_fn qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, const void *src, size_t src_size) { - return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, - qcow2_compress); + BDRVQcow2State *s =3D bs->opaque; + Qcow2CompressFunc fn; + + switch (s->compression_type) { + case QCOW2_COMPRESSION_TYPE_ZLIB: + fn =3D zlib_compress; + break; + + default: + return -ENOTSUP; + } + + return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn); } =20 static ssize_t coroutine_fn qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, const void *src, size_t src_size) { - return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, - qcow2_decompress); + BDRVQcow2State *s =3D bs->opaque; + Qcow2CompressFunc fn; + + switch (s->compression_type) { + case QCOW2_COMPRESSION_TYPE_ZLIB: + fn =3D zlib_decompress; + break; + + default: + return -ENOTSUP; + } + + return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn); } =20 /* XXX: put compressed sectors first, then all the cluster aligned --=20 2.17.0