提交 41c7e5c2 编写于 作者: P Peter Krempa

qemu: block: Add validator for bitmap chains accross backing chains

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: NPeter Krempa <pkrempa@redhat.com>
Reviewed-by: NJán Tomko <jtomko@redhat.com>
上级 ccd4228a
......@@ -2687,3 +2687,44 @@ qemuBlockGetNamedNodeData(virDomainObjPtr vm,
return g_steal_pointer(&blockNamedNodeData);
}
/**
* qemuBlockBitmapChainIsValid:
*
* Validates that the backing chain of @src contains proper consistent bitmap
* data for a chain of bitmaps named @bitmapname.
*
* A valid chain:
* 1) bitmaps of same name are in a consecutive subset of images without gap
* 2) don't have any inconsistent bitmaps
*/
bool
qemuBlockBitmapChainIsValid(virStorageSourcePtr src,
const char *bitmapname,
virHashTablePtr blockNamedNodeData)
{
qemuBlockNamedNodeDataBitmapPtr bitmap;
virStorageSourcePtr n;
bool chain_started = false;
bool chain_ended = false;
for (n = src; n; n = n->backingStore) {
if (!(bitmap = qemuBlockNamedNodeDataGetBitmapByName(blockNamedNodeData, n, bitmapname))) {
if (chain_started)
chain_ended = true;
continue;
}
if (chain_ended)
return false;
chain_started = true;
if (bitmap->inconsistent)
return false;
}
return chain_started;
}
......@@ -212,3 +212,8 @@ qemuBlockNamedNodeDataGetBitmapByName(virHashTablePtr blockNamedNodeData,
virHashTablePtr
qemuBlockGetNamedNodeData(virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob);
bool
qemuBlockBitmapChainIsValid(virStorageSourcePtr src,
const char *bitmapname,
virHashTablePtr blockNamedNodeData);
......@@ -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 = opaque;
g_autoptr(virJSONValue) nodedatajson = NULL;
g_autoptr(virHashTable) nodedata = NULL;
bool actual;
if (!(nodedatajson = virTestLoadFileJSON(bitmapDetectPrefix, data->name,
".json", NULL)))
return -1;
if (!(nodedata = qemuMonitorJSONBlockGetNamedNodeDataJSON(nodedatajson))) {
VIR_TEST_VERBOSE("failed to load nodedata JSON\n");
return -1;
}
actual = qemuBlockBitmapChainIsValid(data->chain, data->bitmapname, nodedata);
if (actual != 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 backupbitmapcalcdata;
struct testQemuCheckpointDeleteMergeData checkpointdeletedata;
struct testQemuBlockBitmapValidateData blockbitmapvalidatedata;
char *capslatest_x86_64 = NULL;
virQEMUCapsPtr caps_x86_64 = NULL;
g_autoptr(virStorageSource) bitmapSourceChain = NULL;
......@@ -1045,7 +1081,41 @@ mymain(void)
TEST_CHECKPOINT_DELETE_MERGE("snapshots-synthetic-checkpoint-intermediate3", "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 = testname; \
blockbitmapvalidatedata.chain = bitmapSourceChain; \
blockbitmapvalidatedata.bitmapname = bitmap; \
blockbitmapvalidatedata.expect = rc; \
if (virTestRun("bitmap validate " testname " " bitmap, \
testQemuBlockBitmapValidate, \
&blockbitmapvalidatedata) < 0) \
ret = -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册