mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 06:50:22 +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:
parent
2780bcd9f8
commit
0feebab2c4
@ -278,3 +278,105 @@ qemuBlockNodeNameGetBackingChain(virJSONValuePtr json)
|
||||
|
||||
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
|
||||
qemuBlockNodeNameGetBackingChain(virJSONValuePtr data);
|
||||
|
||||
int
|
||||
qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm);
|
||||
|
||||
#endif /* __QEMU_BLOCK_H__ */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "internal.h"
|
||||
|
||||
#include "qemu_blockjob.h"
|
||||
#include "qemu_block.h"
|
||||
#include "qemu_domain.h"
|
||||
|
||||
#include "conf/domain_conf.h"
|
||||
@ -166,6 +167,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
|
||||
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
||||
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
|
||||
true, true));
|
||||
ignore_value(qemuBlockNodeNamesDetect(driver, vm));
|
||||
diskPriv->blockjob = false;
|
||||
break;
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "qemu_driver.h"
|
||||
#include "qemu_agent.h"
|
||||
#include "qemu_alias.h"
|
||||
#include "qemu_block.h"
|
||||
#include "qemu_conf.h"
|
||||
#include "qemu_capabilities.h"
|
||||
#include "qemu_command.h"
|
||||
@ -20354,6 +20355,10 @@ qemuDomainSetBlockThreshold(virDomainPtr dom,
|
||||
if (!(src = qemuDomainGetStorageSourceByDevstr(dev, vm->def)))
|
||||
goto endjob;
|
||||
|
||||
if (!src->nodebacking &&
|
||||
qemuBlockNodeNamesDetect(driver, vm) < 0)
|
||||
goto endjob;
|
||||
|
||||
if (!src->nodebacking) {
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||
_("threshold currently can't be set for block device '%s'"),
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "qemu_process.h"
|
||||
#include "qemu_processpriv.h"
|
||||
#include "qemu_alias.h"
|
||||
#include "qemu_block.h"
|
||||
#include "qemu_domain.h"
|
||||
#include "qemu_domain_address.h"
|
||||
#include "qemu_cgroup.h"
|
||||
@ -3486,6 +3487,9 @@ qemuProcessReconnect(void *opaque)
|
||||
if (qemuProcessRefreshDisks(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
|
||||
goto error;
|
||||
|
||||
if (qemuBlockNodeNamesDetect(driver, obj) < 0)
|
||||
goto error;
|
||||
|
||||
if (qemuRefreshVirtioChannelState(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
|
||||
goto error;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user