From nobody Sun Feb 8 20:52:29 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.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 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1500994433443926.7281013227534; Tue, 25 Jul 2017 07:53:53 -0700 (PDT) Received: from localhost ([::1]:33000 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1da1DZ-0002rm-Ul for importer@patchew.org; Tue, 25 Jul 2017 10:53:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36594) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1da12E-00021B-6Z for qemu-devel@nongnu.org; Tue, 25 Jul 2017 10:42:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1da12C-00011e-Ui for qemu-devel@nongnu.org; Tue, 25 Jul 2017 10:42:06 -0400 Received: from mx-v6.kamp.de ([2a02:248:0:51::16]:54360 helo=mx01.kamp.de) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1da12C-00010i-LT for qemu-devel@nongnu.org; Tue, 25 Jul 2017 10:42:04 -0400 Received: (qmail 15729 invoked by uid 89); 25 Jul 2017 14:42:03 -0000 Received: from [195.62.97.28] by client-16-kamp (envelope-from , uid 89) with qmail-scanner-2010/03/19-MF (clamdscan: 0.99.2/23595. avast: 1.2.2/17010300. spamassassin: 3.4.1. Clear:RC:1(195.62.97.28):. Processed in 0.222217 secs); 25 Jul 2017 14:42:03 -0000 Received: from smtp.kamp.de (HELO submission.kamp.de) ([195.62.97.28]) by mx01.kamp.de with ESMTPS (DHE-RSA-AES256-GCM-SHA384 encrypted); 25 Jul 2017 14:42:00 -0000 Received: (qmail 9645 invoked from network); 25 Jul 2017 14:41:40 -0000 Received: from lieven-pc.kamp-intra.net (HELO lieven-pc) (relay@kamp.de@::ffff:172.21.12.60) by submission.kamp.de with ESMTPS (DHE-RSA-AES256-GCM-SHA384 encrypted) ESMTPA; 25 Jul 2017 14:41:40 -0000 Received: by lieven-pc (Postfix, from userid 1000) id 5743020ECC; Tue, 25 Jul 2017 16:41:40 +0200 (CEST) X-GL_Whitelist: yes From: Peter Lieven To: qemu-block@nongnu.org Date: Tue, 25 Jul 2017 16:41:34 +0200 Message-Id: <1500993699-19299-6-git-send-email-pl@kamp.de> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1500993699-19299-1-git-send-email-pl@kamp.de> References: <1500993699-19299-1-git-send-email-pl@kamp.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a02:248:0:51::16 Subject: [Qemu-devel] [PATCH V5 05/10] block/qcow2: read and write the compress format extension 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: kwolf@redhat.com, Peter Lieven , qemu-devel@nongnu.org, mreitz@redhat.com, den@openvz.org, lersek@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" we now read the extension on open and write it on update, but do not yet use it. Signed-off-by: Peter Lieven --- block/qcow2.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ block/qcow2.h | 21 ++++++++++---- 2 files changed, 108 insertions(+), 5 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index a5270a6..7fd52e1 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -70,6 +70,7 @@ typedef struct { #define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857 #define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77 #define QCOW2_EXT_MAGIC_BITMAPS 0x23852875 +#define QCOW2_EXT_MAGIC_COMPRESS_FORMAT 0xC03183A3 =20 static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filen= ame) { @@ -269,6 +270,57 @@ static int qcow2_read_extensions(BlockDriverState *bs,= uint64_t start_offset, #endif break; =20 + case QCOW2_EXT_MAGIC_COMPRESS_FORMAT: + { + Qcow2CompressFormatExt compress_ext; + Error *local_err =3D NULL; + if (ext.len !=3D sizeof(compress_ext)) { + error_setg(errp, "ERROR: ext_compress_format: len=3D%" + PRIu32 " invalid (!=3D%zu)", ext.len, + sizeof(compress_ext)); + return 2; + } + ret =3D bdrv_pread(bs->file, offset, &compress_ext, + ext.len); + if (ret < 0) { + error_setg_errno(errp, -ret, "ERROR: ext_compress_fromat:" + " Could not read extension"); + return 3; + } + + s->compress.format =3D + qapi_enum_parse(Qcow2CompressFormat_lookup, + compress_ext.name, QCOW2_COMPRESS_FORMAT__= MAX, + -1, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return 4; + } + + if (s->compress.format =3D=3D QCOW2_COMPRESS_FORMAT_DEFLATE) { + s->compress.u.deflate.has_level =3D true; + s->compress.u.deflate.level =3D compress_ext.level; + s->compress.u.deflate.has_window_size =3D true; + s->compress.u.deflate.window_size =3D compress_ext.window_= size; + } + + qcow2_check_compress_settings(&s->compress, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return 5; + } + +#ifdef DEBUG_EXT + if (s->compress.format =3D=3D QCOW2_COMPRESS_FORMAT_DEFLATE) { + printf("Qcow2: Got compress format %s with level %" PRIu8 + " window_size %" PRIu8 "\n", + Qcow2CompressFormat_lookup[s->compress.format], + s->compress.u.deflate.level, + s->compress.u.deflate.window_size); + } +#endif + break; + } case QCOW2_EXT_MAGIC_FEATURE_TABLE: if (p_feature_table !=3D NULL) { void* feature_table =3D g_malloc0(ext.len + 2 * sizeof(Qco= w2Feature)); @@ -1403,6 +1455,12 @@ static int qcow2_do_open(BlockDriverState *bs, QDict= *options, int flags, s->cluster_cache_offset =3D -1; s->flags =3D flags; =20 + s->compress.format =3D QCOW2_COMPRESS_FORMAT_DEFLATE; + s->compress.u.deflate.has_level =3D true; + s->compress.u.deflate.level =3D 0; + s->compress.u.deflate.has_window_size =3D true; + s->compress.u.deflate.window_size =3D 12; + ret =3D qcow2_refcount_init(bs); if (ret !=3D 0) { error_setg_errno(errp, -ret, "Could not initialize refcount handli= ng"); @@ -2320,6 +2378,30 @@ int qcow2_update_header(BlockDriverState *bs) buflen -=3D ret; } =20 + /* Compress Format header extension */ + if (s->compress.format !=3D QCOW2_COMPRESS_FORMAT_DEFLATE || + s->compress.u.deflate.level !=3D 0 || + s->compress.u.deflate.window_size !=3D 12) { + Qcow2CompressFormatExt ext =3D {}; + assert(s->compress.format < QCOW2_COMPRESS_FORMAT__MAX); + strncpy((char *) &ext.name, + Qcow2CompressFormat_lookup[s->compress.format], + sizeof(ext.name)); + if (s->compress.format =3D=3D QCOW2_COMPRESS_FORMAT_DEFLATE) { + ext.level =3D s->compress.u.deflate.level; + ext.window_size =3D s->compress.u.deflate.window_size; + } + ret =3D header_ext_add(buf, QCOW2_EXT_MAGIC_COMPRESS_FORMAT, + &ext, sizeof(ext), + buflen); + if (ret < 0) { + goto fail; + } + buf +=3D ret; + buflen -=3D ret; + header->incompatible_features |=3D cpu_to_be64(QCOW2_INCOMPAT_COMP= RESS); + } + /* Feature table */ if (s->qcow_version >=3D 3) { Qcow2Feature features[] =3D { @@ -2334,6 +2416,11 @@ int qcow2_update_header(BlockDriverState *bs) .name =3D "corrupt bit", }, { + .type =3D QCOW2_FEAT_TYPE_INCOMPATIBLE, + .bit =3D QCOW2_INCOMPAT_COMPRESS_BITNR, + .name =3D "compress format bit", + }, + { .type =3D QCOW2_FEAT_TYPE_COMPATIBLE, .bit =3D QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, .name =3D "lazy refcounts", @@ -2855,6 +2942,11 @@ static int qcow2_create2(const char *filename, int64= _t total_size, abort(); } =20 + if (compress) { + BDRVQcow2State *s =3D blk_bs(blk)->opaque; + memcpy(&s->compress, compress, sizeof(Qcow2Compress)); + } + /* Create a full header (including things like feature table) */ ret =3D qcow2_update_header(blk_bs(blk)); if (ret < 0) { diff --git a/block/qcow2.h b/block/qcow2.h index 96a8d43..abd35dd 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -188,13 +188,16 @@ enum { =20 /* Incompatible feature bits */ enum { - QCOW2_INCOMPAT_DIRTY_BITNR =3D 0, - QCOW2_INCOMPAT_CORRUPT_BITNR =3D 1, - QCOW2_INCOMPAT_DIRTY =3D 1 << QCOW2_INCOMPAT_DIRTY_BITNR, - QCOW2_INCOMPAT_CORRUPT =3D 1 << QCOW2_INCOMPAT_CORRUPT_BITNR, + QCOW2_INCOMPAT_DIRTY_BITNR =3D 0, + QCOW2_INCOMPAT_CORRUPT_BITNR =3D 1, + QCOW2_INCOMPAT_COMPRESS_BITNR =3D 2, + QCOW2_INCOMPAT_DIRTY =3D 1 << QCOW2_INCOMPAT_DIRTY_BITNR, + QCOW2_INCOMPAT_CORRUPT =3D 1 << QCOW2_INCOMPAT_CORRUPT_BITNR, + QCOW2_INCOMPAT_COMPRESS =3D 1 << QCOW2_INCOMPAT_COMPRESS_BITNR, =20 QCOW2_INCOMPAT_MASK =3D QCOW2_INCOMPAT_DIRTY - | QCOW2_INCOMPAT_CORRUPT, + | QCOW2_INCOMPAT_CORRUPT + | QCOW2_INCOMPAT_COMPRESS, }; =20 /* Compatible feature bits */ @@ -228,6 +231,12 @@ typedef struct Qcow2Feature { char name[46]; } QEMU_PACKED Qcow2Feature; =20 +typedef struct Qcow2CompressFormatExt { + char name[14]; + uint8_t level; + uint8_t window_size; +} QEMU_PACKED Qcow2CompressFormatExt; + typedef struct Qcow2DiscardRegion { BlockDriverState *bs; uint64_t offset; @@ -307,6 +316,8 @@ typedef struct BDRVQcow2State { Qcow2GetRefcountFunc *get_refcount; Qcow2SetRefcountFunc *set_refcount; =20 + Qcow2Compress compress; + bool discard_passthrough[QCOW2_DISCARD_MAX]; =20 int overlap_check; /* bitmask of Qcow2MetadataOverlap values */ --=20 1.9.1