提交 0175dc6e 编写于 作者: P Peter Krempa

qemu: block: Refactor node name detection code

Remove the complex and unreliable code which inferred the node name
hierarchy only from data returned by 'query-named-block-nodes'. It turns
out that query-blockstats contain the full hierarchy of nodes as
perceived by qemu so the inference code is not necessary.

In query blockstats, the 'parent' object corresponds to the storage
behind a storage volume and 'backing' corresponds to the lower level of
backing chain. Since all have node names this data can be really easily
used to detect node names.

In addition to the code refactoring the one remaining test case needed
to be fixed along.
Reviewed-by: NEric Blake <eblake@redhat.com>
上级 c61d1693
...@@ -48,20 +48,15 @@ qemuBlockNamedNodesArrayToHash(size_t pos ATTRIBUTE_UNUSED, ...@@ -48,20 +48,15 @@ qemuBlockNamedNodesArrayToHash(size_t pos ATTRIBUTE_UNUSED,
static void static void
qemuBlockNodeNameBackingChainDataFree(qemuBlockNodeNameBackingChainDataPtr data) qemuBlockNodeNameBackingChainDataFree(qemuBlockNodeNameBackingChainDataPtr data)
{ {
size_t i;
if (!data) if (!data)
return; return;
for (i = 0; i < data->nelems; i++)
virJSONValueFree(data->elems[i]);
VIR_FREE(data->nodeformat); VIR_FREE(data->nodeformat);
VIR_FREE(data->nodestorage); VIR_FREE(data->nodestorage);
VIR_FREE(data->nodebacking);
VIR_FREE(data->qemufilename); VIR_FREE(data->qemufilename);
VIR_FREE(data->backingstore);
qemuBlockNodeNameBackingChainDataFree(data->backing);
VIR_FREE(data); VIR_FREE(data);
} }
...@@ -75,55 +70,10 @@ qemuBlockNodeNameBackingChainDataHashEntryFree(void *opaque, ...@@ -75,55 +70,10 @@ qemuBlockNodeNameBackingChainDataHashEntryFree(void *opaque,
} }
struct qemuBlockNodeNameGetBackingChainData { /* list of driver names of layers that qemu automatically adds into the
virHashTablePtr table; * backing chain */
qemuBlockNodeNameBackingChainDataPtr *entries; static const char *qemuBlockDriversBlockjob[] = {
size_t nentries; "mirror_top", "commit_top", NULL };
};
static int
qemuBlockNodeNameDetectProcessByFilename(size_t pos ATTRIBUTE_UNUSED,
virJSONValuePtr item,
void *opaque)
{
struct qemuBlockNodeNameGetBackingChainData *data = opaque;
qemuBlockNodeNameBackingChainDataPtr entry;
const char *file;
if (!(file = virJSONValueObjectGetString(item, "file")))
return 1;
if (!(entry = virHashLookup(data->table, file))) {
if (VIR_ALLOC(entry) < 0)
return -1;
if (VIR_APPEND_ELEMENT_COPY(data->entries, data->nentries, entry) < 0) {
VIR_FREE(entry);
return -1;
}
if (VIR_STRDUP(entry->qemufilename, file) < 0)
return -1;
if (virHashAddEntry(data->table, file, entry) < 0)
return -1;
}
if (VIR_APPEND_ELEMENT(entry->elems, entry->nelems, item) < 0)
return -1;
return 0;
}
static const char *qemuBlockDriversFormat[] = {
"qcow2", "raw", "qcow", "luks", "qed", "bochs", "cloop", "dmg", "parallels",
"vdi", "vhdx", "vmdk", "vpc", "vvfat", NULL};
static const char *qemuBlockDriversStorage[] = {
"file", "iscsi", "nbd", "host_cdrom", "host_device", "ftp", "ftps",
"gluster", "http", "https", "nfs", "rbd", "sheepdog", "ssh", "tftp", NULL};
static bool static bool
qemuBlockDriverMatch(const char *drvname, qemuBlockDriverMatch(const char *drvname,
...@@ -140,86 +90,110 @@ qemuBlockDriverMatch(const char *drvname, ...@@ -140,86 +90,110 @@ qemuBlockDriverMatch(const char *drvname,
} }
struct qemuBlockNodeNameGetBackingChainData {
virHashTablePtr nodenamestable;
virHashTablePtr disks;
};
static int static int
qemuBlockNodeNameDetectProcessExtract(qemuBlockNodeNameBackingChainDataPtr data) qemuBlockNodeNameGetBackingChainBacking(virJSONValuePtr next,
virHashTablePtr nodenamestable,
qemuBlockNodeNameBackingChainDataPtr *nodenamedata)
{ {
const char *drv; qemuBlockNodeNameBackingChainDataPtr data = NULL;
const char *nodename; qemuBlockNodeNameBackingChainDataPtr backingdata = NULL;
const char *backingstore; virJSONValuePtr backing = virJSONValueObjectGetObject(next, "backing");
size_t i; virJSONValuePtr parent = virJSONValueObjectGetObject(next, "parent");
virJSONValuePtr parentnodedata;
virJSONValuePtr nodedata;
const char *nodename = virJSONValueObjectGetString(next, "node-name");
const char *drvname;
const char *parentnodename = NULL;
const char *filename = NULL;
int ret = -1;
/* Since the only way to construct the backing chain is to look up the files if (!nodename)
* by file name, if two disks share a backing image we can't know which node
* belongs to which backing chain. Refuse to detect such chains. */
if (data->nelems > 2)
return 0; return 0;
for (i = 0; i < data->nelems; i++) { if ((nodedata = virHashLookup(nodenamestable, nodename)) &&
drv = virJSONValueObjectGetString(data->elems[i], "drv"); (drvname = virJSONValueObjectGetString(nodedata, "drv"))) {
nodename = virJSONValueObjectGetString(data->elems[i], "node-name");
backingstore = virJSONValueObjectGetString(data->elems[i], "backing_file");
if (!drv || !nodename)
continue;
if (qemuBlockDriverMatch(drv, qemuBlockDriversFormat)) {
if (data->nodeformat)
continue;
if (VIR_STRDUP(data->nodeformat, nodename) < 0)
return -1;
/* extract the backing store file name for the protocol layer */
if (VIR_STRDUP(data->backingstore, backingstore) < 0)
return -1;
} else if (qemuBlockDriverMatch(drv, qemuBlockDriversStorage)) {
if (data->nodestorage)
continue;
if (VIR_STRDUP(data->nodestorage, nodename) < 0) /* qemu 2.9 reports layers in the backing chain which don't correspond
return -1; * to files. skip them */
if (qemuBlockDriverMatch(drvname, qemuBlockDriversBlockjob)) {
if (backing) {
return qemuBlockNodeNameGetBackingChainBacking(backing,
nodenamestable,
nodenamedata);
} else {
return 0;
}
} }
} }
return 0; if (parent &&
} (parentnodename = virJSONValueObjectGetString(parent, "node-name"))) {
if ((parentnodedata = virHashLookup(nodenamestable, parentnodename)))
filename = virJSONValueObjectGetString(parentnodedata, "file");
}
if (VIR_ALLOC(data) < 0)
goto cleanup;
static int if (VIR_STRDUP(data->nodeformat, nodename) < 0 ||
qemuBlockNodeNameDetectProcessLinkBacking(qemuBlockNodeNameBackingChainDataPtr data, VIR_STRDUP(data->nodestorage, parentnodename) < 0 ||
virHashTablePtr table) VIR_STRDUP(data->qemufilename, filename) < 0)
{ goto cleanup;
qemuBlockNodeNameBackingChainDataPtr backing;
if (!data->backingstore) if (backing &&
return 0; qemuBlockNodeNameGetBackingChainBacking(backing, nodenamestable,
&backingdata) < 0)
goto cleanup;
if (!(backing = virHashLookup(table, data->backingstore))) VIR_STEAL_PTR(data->backing, backingdata);
return 0; VIR_STEAL_PTR(*nodenamedata, data);
if (VIR_STRDUP(data->nodebacking, backing->nodeformat) < 0) ret = 0;
return -1;
return 0; cleanup:
qemuBlockNodeNameBackingChainDataFree(data);
return ret;
} }
static void static int
qemuBlockNodeNameGetBackingChainDataClearLookup(qemuBlockNodeNameBackingChainDataPtr data) qemuBlockNodeNameGetBackingChainDisk(size_t pos ATTRIBUTE_UNUSED,
virJSONValuePtr item,
void *opaque)
{ {
size_t i; struct qemuBlockNodeNameGetBackingChainData *data = opaque;
const char *device = virJSONValueObjectGetString(item, "device");
qemuBlockNodeNameBackingChainDataPtr devicedata = NULL;
int ret = -1;
if (qemuBlockNodeNameGetBackingChainBacking(item, data->nodenamestable,
&devicedata) < 0)
goto cleanup;
if (devicedata &&
virHashAddEntry(data->disks, device, devicedata) < 0)
goto cleanup;
for (i = 0; i < data->nelems; i++) devicedata = NULL;
virJSONValueFree(data->elems[i]); ret = 1; /* we don't really want to steal @item */
VIR_FREE(data->elems); cleanup:
data->nelems = 0; qemuBlockNodeNameBackingChainDataFree(devicedata);
return ret;
} }
/** /**
* qemuBlockNodeNameGetBackingChain: * qemuBlockNodeNameGetBackingChain:
* @json: JSON array of data returned from 'query-named-block-nodes' * @namednodes: JSON array of data returned from 'query-named-block-nodes'
* @blockstats: JSON array of data returned from 'query-blockstats'
* *
* Tries to reconstruct the backing chain from @json to allow detection of * Tries to reconstruct the backing chain from @json to allow detection of
* node names that were auto-assigned by qemu. This is a best-effort operation * node names that were auto-assigned by qemu. This is a best-effort operation
...@@ -230,69 +204,40 @@ qemuBlockNodeNameGetBackingChainDataClearLookup(qemuBlockNodeNameBackingChainDat ...@@ -230,69 +204,40 @@ qemuBlockNodeNameGetBackingChainDataClearLookup(qemuBlockNodeNameBackingChainDat
* Returns a hash table on success and NULL on failure. * Returns a hash table on success and NULL on failure.
*/ */
virHashTablePtr virHashTablePtr
qemuBlockNodeNameGetBackingChain(virJSONValuePtr json) qemuBlockNodeNameGetBackingChain(virJSONValuePtr namednodes,
virJSONValuePtr blockstats)
{ {
struct qemuBlockNodeNameGetBackingChainData data; struct qemuBlockNodeNameGetBackingChainData data;
virHashTablePtr nodetable = NULL; virHashTablePtr namednodestable = NULL;
virHashTablePtr disks = NULL;
virHashTablePtr ret = NULL; virHashTablePtr ret = NULL;
size_t i;
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
/* hash table keeps the entries accessible by the 'file' in qemu */ if (!(namednodestable = virHashCreate(50, virJSONValueHashFree)))
if (!(data.table = virHashCreate(50, NULL)))
goto cleanup;
/* first group the named entries by the 'file' field */
if (virJSONValueArrayForeachSteal(json,
qemuBlockNodeNameDetectProcessByFilename,
&data) < 0)
goto cleanup;
/* extract the node names for the format and storage layer */
for (i = 0; i < data.nentries; i++) {
if (qemuBlockNodeNameDetectProcessExtract(data.entries[i]) < 0)
goto cleanup; goto cleanup;
}
/* extract the node name for the backing file */ if (virJSONValueArrayForeachSteal(namednodes,
for (i = 0; i < data.nentries; i++) { qemuBlockNamedNodesArrayToHash,
if (qemuBlockNodeNameDetectProcessLinkBacking(data.entries[i], namednodestable) < 0)
data.table) < 0)
goto cleanup; goto cleanup;
}
/* clear JSON data necessary only for the lookup procedure */
for (i = 0; i < data.nentries; i++)
qemuBlockNodeNameGetBackingChainDataClearLookup(data.entries[i]);
/* create hash table hashed by the format node name */ if (!(disks = virHashCreate(50, qemuBlockNodeNameBackingChainDataHashEntryFree)))
if (!(nodetable = virHashCreate(50,
qemuBlockNodeNameBackingChainDataHashEntryFree)))
goto cleanup; goto cleanup;
/* fill the entries */ data.nodenamestable = namednodestable;
for (i = 0; i < data.nentries; i++) { data.disks = disks;
if (!data.entries[i]->nodeformat)
continue;
if (virHashAddEntry(nodetable, data.entries[i]->nodeformat, if (virJSONValueArrayForeachSteal(blockstats,
data.entries[i]) < 0) qemuBlockNodeNameGetBackingChainDisk,
&data) < 0)
goto cleanup; goto cleanup;
/* hash table steals the entry and then frees it by itself */ VIR_STEAL_PTR(ret, disks);
data.entries[i] = NULL;
}
VIR_STEAL_PTR(ret, nodetable);
cleanup: cleanup:
virHashFree(data.table); virHashFree(namednodestable);
virHashFree(nodetable); virHashFree(disks);
for (i = 0; i < data.nentries; i++)
qemuBlockNodeNameBackingChainDataFree(data.entries[i]);
VIR_FREE(data.entries);
return ret; return ret;
} }
...@@ -314,20 +259,19 @@ qemuBlockDiskClearDetectedNodes(virDomainDiskDefPtr disk) ...@@ -314,20 +259,19 @@ qemuBlockDiskClearDetectedNodes(virDomainDiskDefPtr disk)
static int static int
qemuBlockDiskDetectNodes(virDomainDiskDefPtr disk, qemuBlockDiskDetectNodes(virDomainDiskDefPtr disk,
const char *parentnode, virHashTablePtr disktable)
virHashTablePtr table)
{ {
qemuBlockNodeNameBackingChainDataPtr entry = NULL; qemuBlockNodeNameBackingChainDataPtr entry = NULL;
virStorageSourcePtr src = disk->src; virStorageSourcePtr src = disk->src;
/* don't attempt the detection if the top level already has node names */ if (!(entry = virHashLookup(disktable, disk->info.alias)))
if (!parentnode || src->nodeformat || src->nodestorage)
return 0; return 0;
while (src && parentnode) { /* don't attempt the detection if the top level already has node names */
if (!(entry = virHashLookup(table, parentnode))) if (src->nodeformat || src->nodestorage)
break; return 0;
while (src && entry) {
if (src->nodeformat || src->nodestorage) { if (src->nodeformat || src->nodestorage) {
if (STRNEQ_NULLABLE(src->nodeformat, entry->nodeformat) || if (STRNEQ_NULLABLE(src->nodeformat, entry->nodeformat) ||
STRNEQ_NULLABLE(src->nodestorage, entry->nodestorage)) STRNEQ_NULLABLE(src->nodestorage, entry->nodestorage))
...@@ -340,7 +284,7 @@ qemuBlockDiskDetectNodes(virDomainDiskDefPtr disk, ...@@ -340,7 +284,7 @@ qemuBlockDiskDetectNodes(virDomainDiskDefPtr disk,
goto error; goto error;
} }
parentnode = entry->nodebacking; entry = entry->backing;
src = src->backingStore; src = src->backingStore;
} }
...@@ -359,10 +303,9 @@ qemuBlockNodeNamesDetect(virQEMUDriverPtr driver, ...@@ -359,10 +303,9 @@ qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virHashTablePtr disktable = NULL; virHashTablePtr disktable = NULL;
virHashTablePtr nodenametable = NULL;
virJSONValuePtr data = NULL; virJSONValuePtr data = NULL;
virJSONValuePtr blockstats = NULL;
virDomainDiskDefPtr disk; virDomainDiskDefPtr disk;
struct qemuDomainDiskInfo *info;
size_t i; size_t i;
int ret = -1; int ret = -1;
...@@ -372,22 +315,19 @@ qemuBlockNodeNamesDetect(virQEMUDriverPtr driver, ...@@ -372,22 +315,19 @@ qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1; return -1;
disktable = qemuMonitorGetBlockInfo(qemuDomainGetMonitor(vm));
data = qemuMonitorQueryNamedBlockNodes(qemuDomainGetMonitor(vm)); data = qemuMonitorQueryNamedBlockNodes(qemuDomainGetMonitor(vm));
blockstats = qemuMonitorQueryBlockstats(qemuDomainGetMonitor(vm));
if (qemuDomainObjExitMonitor(driver, vm) < 0 || !data || !disktable) if (qemuDomainObjExitMonitor(driver, vm) < 0 || !data || !blockstats)
goto cleanup; goto cleanup;
if (!(nodenametable = qemuBlockNodeNameGetBackingChain(data))) if (!(disktable = qemuBlockNodeNameGetBackingChain(data, blockstats)))
goto cleanup; goto cleanup;
for (i = 0; i < vm->def->ndisks; i++) { for (i = 0; i < vm->def->ndisks; i++) {
disk = vm->def->disks[i]; disk = vm->def->disks[i];
if (!(info = virHashLookup(disktable, disk->info.alias))) if (qemuBlockDiskDetectNodes(disk, disktable) < 0)
continue;
if (qemuBlockDiskDetectNodes(disk, info->nodename, nodenametable) < 0)
goto cleanup; goto cleanup;
} }
...@@ -395,7 +335,7 @@ qemuBlockNodeNamesDetect(virQEMUDriverPtr driver, ...@@ -395,7 +335,7 @@ qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
cleanup: cleanup:
virJSONValueFree(data); virJSONValueFree(data);
virHashFree(nodenametable); virJSONValueFree(blockstats);
virHashFree(disktable); virHashFree(disktable);
return ret; return ret;
......
...@@ -31,19 +31,15 @@ typedef struct qemuBlockNodeNameBackingChainData qemuBlockNodeNameBackingChainDa ...@@ -31,19 +31,15 @@ typedef struct qemuBlockNodeNameBackingChainData qemuBlockNodeNameBackingChainDa
typedef qemuBlockNodeNameBackingChainData *qemuBlockNodeNameBackingChainDataPtr; typedef qemuBlockNodeNameBackingChainData *qemuBlockNodeNameBackingChainDataPtr;
struct qemuBlockNodeNameBackingChainData { struct qemuBlockNodeNameBackingChainData {
char *qemufilename; /* name of the image from qemu */ char *qemufilename; /* name of the image from qemu */
char *backingstore;
char *nodeformat; /* node name of the format layer */ char *nodeformat; /* node name of the format layer */
char *nodestorage; /* node name of the storage backing the format node */ char *nodestorage; /* node name of the storage backing the format node */
char *nodebacking; /* node name of the backing file format layer */ qemuBlockNodeNameBackingChainDataPtr backing;
/* data necessary for detection of the node names from qemu */
virJSONValuePtr *elems;
size_t nelems;
}; };
virHashTablePtr virHashTablePtr
qemuBlockNodeNameGetBackingChain(virJSONValuePtr data); qemuBlockNodeNameGetBackingChain(virJSONValuePtr namednodesdata,
virJSONValuePtr blockstats);
int int
qemuBlockNodeNamesDetect(virQEMUDriverPtr driver, qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
......
[
{
"device": "drive-virtio-disk0",
"parent": {
"stats": {
"flush_total_time_ns": 0,
"wr_highest_offset": 32899072,
"wr_total_time_ns": 0,
"failed_wr_operations": 0,
"failed_rd_operations": 0,
"wr_merged": 0,
"wr_bytes": 0,
"timed_stats": [
],
"failed_flush_operations": 0,
"account_invalid": false,
"rd_total_time_ns": 0,
"flush_operations": 0,
"wr_operations": 0,
"rd_merged": 0,
"rd_bytes": 0,
"invalid_flush_operations": 0,
"account_failed": false,
"rd_operations": 0,
"invalid_wr_operations": 0,
"invalid_rd_operations": 0
},
"node-name": "#block033"
},
"stats": {
"flush_total_time_ns": 452246313,
"wr_highest_offset": 8072282112,
"wr_total_time_ns": 4803102521,
"failed_wr_operations": 0,
"failed_rd_operations": 0,
"wr_merged": 8,
"wr_bytes": 6517248,
"timed_stats": [
],
"failed_flush_operations": 0,
"account_invalid": true,
"rd_total_time_ns": 11065169148,
"flush_operations": 10,
"wr_operations": 129,
"rd_merged": 77,
"rd_bytes": 76399104,
"invalid_flush_operations": 0,
"account_failed": true,
"idle_time_ns": 22663656304,
"rd_operations": 4038,
"invalid_wr_operations": 0,
"invalid_rd_operations": 0
},
"backing": {
"parent": {
"stats": {
"flush_total_time_ns": 0,
"wr_highest_offset": 0,
"wr_total_time_ns": 0,
"failed_wr_operations": 0,
"failed_rd_operations": 0,
"wr_merged": 0,
"wr_bytes": 0,
"timed_stats": [
],
"failed_flush_operations": 0,
"account_invalid": false,
"rd_total_time_ns": 0,
"flush_operations": 0,
"wr_operations": 0,
"rd_merged": 0,
"rd_bytes": 0,
"invalid_flush_operations": 0,
"account_failed": false,
"rd_operations": 0,
"invalid_wr_operations": 0,
"invalid_rd_operations": 0
},
"node-name": "#block220"
},
"stats": {
"flush_total_time_ns": 0,
"wr_highest_offset": 0,
"wr_total_time_ns": 0,
"failed_wr_operations": 0,
"failed_rd_operations": 0,
"wr_merged": 0,
"wr_bytes": 0,
"timed_stats": [
],
"failed_flush_operations": 0,
"account_invalid": false,
"rd_total_time_ns": 0,
"flush_operations": 0,
"wr_operations": 0,
"rd_merged": 0,
"rd_bytes": 0,
"invalid_flush_operations": 0,
"account_failed": false,
"rd_operations": 0,
"invalid_wr_operations": 0,
"invalid_rd_operations": 0
},
"backing": {
"parent": {
"stats": {
"flush_total_time_ns": 0,
"wr_highest_offset": 0,
"wr_total_time_ns": 0,
"failed_wr_operations": 0,
"failed_rd_operations": 0,
"wr_merged": 0,
"wr_bytes": 0,
"timed_stats": [
],
"failed_flush_operations": 0,
"account_invalid": false,
"rd_total_time_ns": 0,
"flush_operations": 0,
"wr_operations": 0,
"rd_merged": 0,
"rd_bytes": 0,
"invalid_flush_operations": 0,
"account_failed": false,
"rd_operations": 0,
"invalid_wr_operations": 0,
"invalid_rd_operations": 0
},
"node-name": "#block481"
},
"stats": {
"flush_total_time_ns": 0,
"wr_highest_offset": 0,
"wr_total_time_ns": 0,
"failed_wr_operations": 0,
"failed_rd_operations": 0,
"wr_merged": 0,
"wr_bytes": 0,
"timed_stats": [
],
"failed_flush_operations": 0,
"account_invalid": false,
"rd_total_time_ns": 0,
"flush_operations": 0,
"wr_operations": 0,
"rd_merged": 0,
"rd_bytes": 0,
"invalid_flush_operations": 0,
"account_failed": false,
"rd_operations": 0,
"invalid_wr_operations": 0,
"invalid_rd_operations": 0
},
"node-name": "#block558"
},
"node-name": "#block306"
},
"node-name": "#block187"
}
]
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
}, },
"iops_wr": 0, "iops_wr": 0,
"ro": true, "ro": true,
"node-name": "#block567", "node-name": "#block558",
"backing_file_depth": 0, "backing_file_depth": 0,
"drv": "qcow2", "drv": "qcow2",
"iops": 0, "iops": 0,
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
}, },
"iops_wr": 0, "iops_wr": 0,
"ro": true, "ro": true,
"node-name": "#block424", "node-name": "#block481",
"backing_file_depth": 0, "backing_file_depth": 0,
"drv": "file", "drv": "file",
"iops": 0, "iops": 0,
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
}, },
"iops_wr": 0, "iops_wr": 0,
"ro": true, "ro": true,
"node-name": "#block331", "node-name": "#block306",
"backing_file_depth": 1, "backing_file_depth": 1,
"drv": "qcow2", "drv": "qcow2",
"iops": 0, "iops": 0,
...@@ -139,7 +139,7 @@ ...@@ -139,7 +139,7 @@
}, },
"iops_wr": 0, "iops_wr": 0,
"ro": true, "ro": true,
"node-name": "#block281", "node-name": "#block220",
"backing_file_depth": 0, "backing_file_depth": 0,
"drv": "file", "drv": "file",
"iops": 0, "iops": 0,
...@@ -202,7 +202,7 @@ ...@@ -202,7 +202,7 @@
"filename": "/var/lib/libvirt/images/rhel7.3.1483545313", "filename": "/var/lib/libvirt/images/rhel7.3.1483545313",
"cluster-size": 65536, "cluster-size": 65536,
"format": "qcow2", "format": "qcow2",
"actual-size": 32968704, "actual-size": 33165312,
"format-specific": { "format-specific": {
"type": "qcow2", "type": "qcow2",
"data": { "data": {
...@@ -218,7 +218,7 @@ ...@@ -218,7 +218,7 @@
}, },
"iops_wr": 0, "iops_wr": 0,
"ro": false, "ro": false,
"node-name": "#block118", "node-name": "#block187",
"backing_file_depth": 2, "backing_file_depth": 2,
"drv": "qcow2", "drv": "qcow2",
"iops": 0, "iops": 0,
...@@ -240,15 +240,15 @@ ...@@ -240,15 +240,15 @@
"iops_rd": 0, "iops_rd": 0,
"detect_zeroes": "off", "detect_zeroes": "off",
"image": { "image": {
"virtual-size": 33030144, "virtual-size": 33226752,
"filename": "/var/lib/libvirt/images/rhel7.3.1483545313", "filename": "/var/lib/libvirt/images/rhel7.3.1483545313",
"format": "file", "format": "file",
"actual-size": 32968704, "actual-size": 33165312,
"dirty-flag": false "dirty-flag": false
}, },
"iops_wr": 0, "iops_wr": 0,
"ro": false, "ro": false,
"node-name": "#block078", "node-name": "#block033",
"backing_file_depth": 0, "backing_file_depth": 0,
"drv": "file", "drv": "file",
"iops": 0, "iops": 0,
......
filename : '/var/lib/libvirt/images/rhel7.3.1483545313' filename : '/var/lib/libvirt/images/rhel7.3.1483545313'
format node : '#block118' format node : '#block187'
storage node: '#block078' storage node: '#block033'
filename : '/var/lib/libvirt/images/rhel7.3.1483536402' filename : '/var/lib/libvirt/images/rhel7.3.1483536402'
format node : '#block331' format node : '#block306'
storage node: '#block281' storage node: '#block220'
filename : '/var/lib/libvirt/images/rhel7.3.qcow2' filename : '/var/lib/libvirt/images/rhel7.3.qcow2'
format node : '#block567' format node : '#block558'
storage node: '#block424' storage node: '#block481'
...@@ -2704,18 +2704,17 @@ struct testBlockNodeNameDetectData { ...@@ -2704,18 +2704,17 @@ struct testBlockNodeNameDetectData {
static void static void
testBlockNodeNameDetectFormat(virBufferPtr buf, testBlockNodeNameDetectFormat(virBufferPtr buf,
const char *basenode, const char *diskalias,
virHashTablePtr nodedata) virHashTablePtr nodedata)
{ {
qemuBlockNodeNameBackingChainDataPtr entry = NULL; qemuBlockNodeNameBackingChainDataPtr entry = NULL;
const char *node = basenode;
virBufferSetIndent(buf, 0); virBufferSetIndent(buf, 0);
while (node) { if (!(entry = virHashLookup(nodedata, diskalias)))
if (!(entry = virHashLookup(nodedata, node))) return;
break;
while (entry) {
virBufferAsprintf(buf, "filename : '%s'\n", entry->qemufilename); virBufferAsprintf(buf, "filename : '%s'\n", entry->qemufilename);
virBufferAsprintf(buf, "format node : '%s'\n", virBufferAsprintf(buf, "format node : '%s'\n",
NULLSTR(entry->nodeformat)); NULLSTR(entry->nodeformat));
...@@ -2724,7 +2723,7 @@ testBlockNodeNameDetectFormat(virBufferPtr buf, ...@@ -2724,7 +2723,7 @@ testBlockNodeNameDetectFormat(virBufferPtr buf,
virBufferAdjustIndent(buf, 2); virBufferAdjustIndent(buf, 2);
node = entry->nodebacking; entry = entry->backing;
} }
virBufferSetIndent(buf, 0); virBufferSetIndent(buf, 0);
...@@ -2742,6 +2741,7 @@ testBlockNodeNameDetect(const void *opaque) ...@@ -2742,6 +2741,7 @@ testBlockNodeNameDetect(const void *opaque)
char **nodenames = NULL; char **nodenames = NULL;
char **next; char **next;
virJSONValuePtr namedNodesJson = NULL; virJSONValuePtr namedNodesJson = NULL;
virJSONValuePtr blockstatsJson = NULL;
virHashTablePtr nodedata = NULL; virHashTablePtr nodedata = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
int ret = -1; int ret = -1;
...@@ -2757,7 +2757,12 @@ testBlockNodeNameDetect(const void *opaque) ...@@ -2757,7 +2757,12 @@ testBlockNodeNameDetect(const void *opaque)
"-named-nodes.json", NULL))) "-named-nodes.json", NULL)))
goto cleanup; goto cleanup;
if (!(nodedata = qemuBlockNodeNameGetBackingChain(namedNodesJson))) if (!(blockstatsJson = virTestLoadFileJSON(pathprefix, data->name,
"-blockstats.json", NULL)))
goto cleanup;
if (!(nodedata = qemuBlockNodeNameGetBackingChain(namedNodesJson,
blockstatsJson)))
goto cleanup; goto cleanup;
for (next = nodenames; *next; next++) for (next = nodenames; *next; next++)
...@@ -2781,6 +2786,7 @@ testBlockNodeNameDetect(const void *opaque) ...@@ -2781,6 +2786,7 @@ testBlockNodeNameDetect(const void *opaque)
virHashFree(nodedata); virHashFree(nodedata);
virStringListFree(nodenames); virStringListFree(nodenames);
virJSONValueFree(namedNodesJson); virJSONValueFree(namedNodesJson);
virJSONValueFree(blockstatsJson);
return ret; return ret;
} }
...@@ -2929,7 +2935,7 @@ mymain(void) ...@@ -2929,7 +2935,7 @@ mymain(void)
ret = -1; \ ret = -1; \
} while (0) } while (0)
DO_TEST_BLOCK_NODE_DETECT("basic", "#block118"); DO_TEST_BLOCK_NODE_DETECT("basic", "drive-virtio-disk0");
/* DO_TEST_BLOCK_NODE_DETECT("same-backing", "#block170,#block574"); */ /* DO_TEST_BLOCK_NODE_DETECT("same-backing", "#block170,#block574"); */
/* DO_TEST_BLOCK_NODE_DETECT("relative", "#block153,#block1177"); */ /* DO_TEST_BLOCK_NODE_DETECT("relative", "#block153,#block1177"); */
/* DO_TEST_BLOCK_NODE_DETECT("gluster", "#block1008"); */ /* DO_TEST_BLOCK_NODE_DETECT("gluster", "#block1008"); */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册