mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-08-25 13:50:09 +03:00
qemu: block: Add code to detect node names when necessary
Detect the node names when setting block threshold and when reconnecting or when they are cleared when a block job finishes. This operation will become a no-op once we fully support node names.
This commit is contained in:
@ -278,3 +278,105 @@ qemuBlockNodeNameGetBackingChain(virJSONValuePtr json)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
qemuBlockDiskClearDetectedNodes(virDomainDiskDefPtr disk)
|
||||||
|
{
|
||||||
|
virStorageSourcePtr next = disk->src;
|
||||||
|
|
||||||
|
while (next) {
|
||||||
|
VIR_FREE(next->nodeformat);
|
||||||
|
VIR_FREE(next->nodebacking);
|
||||||
|
|
||||||
|
next = next->backingStore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuBlockDiskDetectNodes(virDomainDiskDefPtr disk,
|
||||||
|
const char *parentnode,
|
||||||
|
virHashTablePtr table)
|
||||||
|
{
|
||||||
|
qemuBlockNodeNameBackingChainDataPtr entry = NULL;
|
||||||
|
virStorageSourcePtr src = disk->src;
|
||||||
|
|
||||||
|
/* don't attempt the detection if the top level already has node names */
|
||||||
|
if (!parentnode || src->nodeformat || src->nodebacking)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (src && parentnode) {
|
||||||
|
if (!(entry = virHashLookup(table, parentnode)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (src->nodeformat || src->nodebacking) {
|
||||||
|
if (STRNEQ_NULLABLE(src->nodeformat, entry->nodeformat) ||
|
||||||
|
STRNEQ_NULLABLE(src->nodebacking, entry->nodestorage))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (VIR_STRDUP(src->nodeformat, entry->nodeformat) < 0 ||
|
||||||
|
VIR_STRDUP(src->nodebacking, entry->nodestorage) < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
parentnode = entry->nodebacking;
|
||||||
|
src = src->backingStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
qemuBlockDiskClearDetectedNodes(disk);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm)
|
||||||
|
{
|
||||||
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virHashTablePtr disktable = NULL;
|
||||||
|
virHashTablePtr nodenametable = NULL;
|
||||||
|
virJSONValuePtr data = NULL;
|
||||||
|
virDomainDiskDefPtr disk;
|
||||||
|
struct qemuDomainDiskInfo *info;
|
||||||
|
size_t i;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_NAMED_BLOCK_NODES))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
|
|
||||||
|
disktable = qemuMonitorGetBlockInfo(qemuDomainGetMonitor(vm));
|
||||||
|
data = qemuMonitorQueryNamedBlockNodes(qemuDomainGetMonitor(vm));
|
||||||
|
|
||||||
|
if (qemuDomainObjExitMonitor(driver, vm) < 0 || !data || !disktable)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(nodenametable = qemuBlockNodeNameGetBackingChain(data)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < vm->def->ndisks; i++) {
|
||||||
|
disk = vm->def->disks[i];
|
||||||
|
|
||||||
|
if (!(info = virHashLookup(disktable, disk->info.alias)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (qemuBlockDiskDetectNodes(disk, info->nodename, nodenametable) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virJSONValueFree(data);
|
||||||
|
virHashFree(nodenametable);
|
||||||
|
virHashFree(disktable);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -44,4 +44,8 @@ struct qemuBlockNodeNameBackingChainData {
|
|||||||
virHashTablePtr
|
virHashTablePtr
|
||||||
qemuBlockNodeNameGetBackingChain(virJSONValuePtr data);
|
qemuBlockNodeNameGetBackingChain(virJSONValuePtr data);
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm);
|
||||||
|
|
||||||
#endif /* __QEMU_BLOCK_H__ */
|
#endif /* __QEMU_BLOCK_H__ */
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include "qemu_blockjob.h"
|
#include "qemu_blockjob.h"
|
||||||
|
#include "qemu_block.h"
|
||||||
#include "qemu_domain.h"
|
#include "qemu_domain.h"
|
||||||
|
|
||||||
#include "conf/domain_conf.h"
|
#include "conf/domain_conf.h"
|
||||||
@ -166,6 +167,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
|
|||||||
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
||||||
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
|
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
|
||||||
true, true));
|
true, true));
|
||||||
|
ignore_value(qemuBlockNodeNamesDetect(driver, vm));
|
||||||
diskPriv->blockjob = false;
|
diskPriv->blockjob = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "qemu_driver.h"
|
#include "qemu_driver.h"
|
||||||
#include "qemu_agent.h"
|
#include "qemu_agent.h"
|
||||||
#include "qemu_alias.h"
|
#include "qemu_alias.h"
|
||||||
|
#include "qemu_block.h"
|
||||||
#include "qemu_conf.h"
|
#include "qemu_conf.h"
|
||||||
#include "qemu_capabilities.h"
|
#include "qemu_capabilities.h"
|
||||||
#include "qemu_command.h"
|
#include "qemu_command.h"
|
||||||
@ -20354,6 +20355,10 @@ qemuDomainSetBlockThreshold(virDomainPtr dom,
|
|||||||
if (!(src = qemuDomainGetStorageSourceByDevstr(dev, vm->def)))
|
if (!(src = qemuDomainGetStorageSourceByDevstr(dev, vm->def)))
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
|
if (!src->nodebacking &&
|
||||||
|
qemuBlockNodeNamesDetect(driver, vm) < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
if (!src->nodebacking) {
|
if (!src->nodebacking) {
|
||||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||||
_("threshold currently can't be set for block device '%s'"),
|
_("threshold currently can't be set for block device '%s'"),
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "qemu_process.h"
|
#include "qemu_process.h"
|
||||||
#include "qemu_processpriv.h"
|
#include "qemu_processpriv.h"
|
||||||
#include "qemu_alias.h"
|
#include "qemu_alias.h"
|
||||||
|
#include "qemu_block.h"
|
||||||
#include "qemu_domain.h"
|
#include "qemu_domain.h"
|
||||||
#include "qemu_domain_address.h"
|
#include "qemu_domain_address.h"
|
||||||
#include "qemu_cgroup.h"
|
#include "qemu_cgroup.h"
|
||||||
@ -3486,6 +3487,9 @@ qemuProcessReconnect(void *opaque)
|
|||||||
if (qemuProcessRefreshDisks(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
|
if (qemuProcessRefreshDisks(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (qemuBlockNodeNamesDetect(driver, obj) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (qemuRefreshVirtioChannelState(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
|
if (qemuRefreshVirtioChannelState(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user