From nobody Sun Feb 8 21:11:38 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) client-ip=207.211.31.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by mx.zohomail.com with SMTPS id 1580481274559495.125794824383; Fri, 31 Jan 2020 06:34:34 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-107-IK6Ky2u2Ml2HRAb8R4NIuA-1; Fri, 31 Jan 2020 09:34:26 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 712A41005502; Fri, 31 Jan 2020 14:34:16 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 498305C54A; Fri, 31 Jan 2020 14:34:16 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 011D985CEF; Fri, 31 Jan 2020 14:34:15 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00VEVqHF019844 for ; Fri, 31 Jan 2020 09:31:52 -0500 Received: by smtp.corp.redhat.com (Postfix) id C09A087B06; Fri, 31 Jan 2020 14:31:52 +0000 (UTC) Received: from angien.redhat.com (unknown [10.43.2.48]) by smtp.corp.redhat.com (Postfix) with ESMTP id ED24786C4B; Fri, 31 Jan 2020 14:31:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1580481273; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=s/dtFE9fUOnfiS9I686iJdeR/QMGQmputcduTtarx9I=; b=GkJhEGWtwCe1lFq9QfhBll5x7IAykOajmDEww+aLLRYWc/tnDVnVl4VkWsWTPm/2I1DnYh cviAqholmhrhMzN9JdRY591V6J1oIzgB9lsTTAWzcOReP567yEXNf/YzAlGearViPRjcbS Z/IGzFzmf/mKNFJPq97lpbAgD1FHVh8= From: Peter Krempa To: libvir-list@redhat.com Subject: [PATCH 15/19] qemu: block: Add validator for bitmap chains accross backing chains Date: Fri, 31 Jan 2020 15:31:19 +0100 Message-Id: <1d5ffbb3610ee8bfe001455fc5f444fcdd4a46e4.1580480483.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: Peter Krempa X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-MC-Unique: IK6Ky2u2Ml2HRAb8R4NIuA-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Add a validator which checks that a bitmap spanning multiple backing chain members doesn't look broken. The current rules are that no intermediate birmaps are missing (unfortunately it's hard to know whether the topmost or bottommost bitmap is missing) and none of the components is inconsistent. We can obviously improve it over time. The validator is also tested against the existing bitmap data we have for the backup merging test as well as some of the existing broken bitmap synthetic test cases. Signed-off-by: Peter Krempa Reviewed-by: J=C3=A1n Tomko --- src/qemu/qemu_block.c | 41 +++++++++++++++++++++++++ src/qemu/qemu_block.h | 5 ++++ tests/qemublocktest.c | 70 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 03f029368e..b19290e677 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -2687,3 +2687,44 @@ qemuBlockGetNamedNodeData(virDomainObjPtr vm, return g_steal_pointer(&blockNamedNodeData); } + + +/** + * qemuBlockBitmapChainIsValid: + * + * Validates that the backing chain of @src contains proper consistent bit= map + * data for a chain of bitmaps named @bitmapname. + * + * A valid chain: + * 1) bitmaps of same name are in a consecutive subset of images without g= ap + * 2) don't have any inconsistent bitmaps + */ +bool +qemuBlockBitmapChainIsValid(virStorageSourcePtr src, + const char *bitmapname, + virHashTablePtr blockNamedNodeData) +{ + qemuBlockNamedNodeDataBitmapPtr bitmap; + virStorageSourcePtr n; + bool chain_started =3D false; + bool chain_ended =3D false; + + for (n =3D src; n; n =3D n->backingStore) { + if (!(bitmap =3D qemuBlockNamedNodeDataGetBitmapByName(blockNamedN= odeData, n, bitmapname))) { + if (chain_started) + chain_ended =3D true; + + continue; + } + + if (chain_ended) + return false; + + chain_started =3D true; + + if (bitmap->inconsistent) + return false; + } + + return chain_started; +} diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index 68646cbf2e..cf51b9bf4e 100644 --- a/src/qemu/qemu_block.h +++ b/src/qemu/qemu_block.h @@ -212,3 +212,8 @@ qemuBlockNamedNodeDataGetBitmapByName(virHashTablePtr b= lockNamedNodeData, virHashTablePtr qemuBlockGetNamedNodeData(virDomainObjPtr vm, qemuDomainAsyncJob asyncJob); + +bool +qemuBlockBitmapChainIsValid(virStorageSourcePtr src, + const char *bitmapname, + virHashTablePtr blockNamedNodeData); diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index cd61334b4a..133372908a 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -768,6 +768,41 @@ testQemuCheckpointDeleteMerge(const void *opaque) } +struct testQemuBlockBitmapValidateData { + const char *name; + const char *bitmapname; + virStorageSourcePtr chain; + bool expect; +}; + +static int +testQemuBlockBitmapValidate(const void *opaque) +{ + const struct testQemuBlockBitmapValidateData *data =3D opaque; + g_autoptr(virJSONValue) nodedatajson =3D NULL; + g_autoptr(virHashTable) nodedata =3D NULL; + bool actual; + + if (!(nodedatajson =3D virTestLoadFileJSON(bitmapDetectPrefix, data->n= ame, + ".json", NULL))) + return -1; + + if (!(nodedata =3D qemuMonitorJSONBlockGetNamedNodeDataJSON(nodedatajs= on))) { + VIR_TEST_VERBOSE("failed to load nodedata JSON\n"); + return -1; + } + + actual =3D qemuBlockBitmapChainIsValid(data->chain, data->bitmapname, = nodedata); + + if (actual !=3D data->expect) { + VIR_TEST_VERBOSE("expected rv:'%d' actual rv:'%d'\n", data->expect= , actual); + return -1; + } + + return 0; +} + + static int mymain(void) { @@ -778,6 +813,7 @@ mymain(void) struct testQemuImageCreateData imagecreatedata; struct testQemuBackupIncrementalBitmapCalculateData backupbitmapcalcda= ta; struct testQemuCheckpointDeleteMergeData checkpointdeletedata; + struct testQemuBlockBitmapValidateData blockbitmapvalidatedata; char *capslatest_x86_64 =3D NULL; virQEMUCapsPtr caps_x86_64 =3D NULL; g_autoptr(virStorageSource) bitmapSourceChain =3D NULL; @@ -1045,7 +1081,41 @@ mymain(void) TEST_CHECKPOINT_DELETE_MERGE("snapshots-synthetic-checkpoint-intermedi= ate3", "d", "c", "snapshots-synthetic-checkpoint"); TEST_CHECKPOINT_DELETE_MERGE("snapshots-synthetic-checkpoint-current",= "current", "d", "snapshots-synthetic-checkpoint"); +#define TEST_BITMAP_VALIDATE(testname, bitmap, rc) \ + do { \ + blockbitmapvalidatedata.name =3D testname; \ + blockbitmapvalidatedata.chain =3D bitmapSourceChain; \ + blockbitmapvalidatedata.bitmapname =3D bitmap; \ + blockbitmapvalidatedata.expect =3D rc; \ + if (virTestRun("bitmap validate " testname " " bitmap, \ + testQemuBlockBitmapValidate, \ + &blockbitmapvalidatedata) < 0) \ + ret =3D -1; \ + } while (0) + TEST_BITMAP_VALIDATE("basic", "a", true); + TEST_BITMAP_VALIDATE("basic", "b", true); + TEST_BITMAP_VALIDATE("basic", "c", true); + TEST_BITMAP_VALIDATE("basic", "d", true); + TEST_BITMAP_VALIDATE("basic", "current", true); + + TEST_BITMAP_VALIDATE("snapshots", "a", true); + TEST_BITMAP_VALIDATE("snapshots", "b", true); + TEST_BITMAP_VALIDATE("snapshots", "c", true); + TEST_BITMAP_VALIDATE("snapshots", "d", true); + TEST_BITMAP_VALIDATE("snapshots", "current", true); + + TEST_BITMAP_VALIDATE("synthetic", "a", false); + TEST_BITMAP_VALIDATE("synthetic", "b", true); + TEST_BITMAP_VALIDATE("synthetic", "c", true); + TEST_BITMAP_VALIDATE("synthetic", "d", true); + TEST_BITMAP_VALIDATE("synthetic", "current", true); + + TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "a", true); + TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "b", true); + TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "c", true); + TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "d", true); + TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "current", true= ); cleanup: virHashFree(diskxmljsondata.schema); qemuTestDriverFree(&driver); --=20 2.24.1