From f762f87534e6b6cecd4d7551b6f0282f0eac44b4 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Thu, 24 Mar 2022 15:50:27 +0100 Subject: [PATCH] qemu: Implement qemuDomainFDAssociate Implement passing and storage of FDs for the qemu driver. The FD tuples are g_object instances stored in a per-domain hash table and are automatically removed once the connection is closed. In the future we can consider supporting also to not tie the lifetime of the passed FDs bound to the connection. Signed-off-by: Peter Krempa Reviewed-by: Pavel Hrdina --- src/qemu/qemu_domain.c | 2 ++ src/qemu/qemu_domain.h | 3 ++ src/qemu/qemu_driver.c | 67 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 7be431dd19..2d8ff652b0 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1869,6 +1869,7 @@ qemuDomainObjPrivateFree(void *data) qemuDomainMasterKeyFree(priv); g_clear_pointer(&priv->blockjobs, g_hash_table_unref); + g_clear_pointer(&priv->fds, g_hash_table_unref); /* This should never be non-NULL if we get here, but just in case... */ if (priv->eventThread) { @@ -1896,6 +1897,7 @@ qemuDomainObjPrivateAlloc(void *opaque) return NULL; priv->blockjobs = virHashNew(virObjectUnref); + priv->fds = virHashNew(g_object_unref); /* agent commands block by default, user can choose different behavior */ priv->agentTimeout = VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_BLOCK; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 4b0593d5db..69b7e7da5d 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -253,6 +253,9 @@ struct _qemuDomainObjPrivate { pid_t schedCoreChildFD; GSList *threadContextAliases; /* List of IDs of thread-context objects */ + + /* named file descriptor groups associated with the VM */ + GHashTable *fds; }; #define QEMU_DOMAIN_PRIVATE(vm) \ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d9f7ce234e..0a98551f8a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20379,6 +20379,72 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, } +static void +qemuDomainFDHashCloseConnect(virDomainObj *vm, + virConnectPtr conn) +{ + qemuDomainObjPrivate *priv = QEMU_DOMAIN_PRIVATE(vm); + virStorageSourceFDTuple *data; + GHashTableIter htitr; + + if (!priv->fds) + return; + + g_hash_table_iter_init(&htitr, priv->fds); + + while (g_hash_table_iter_next(&htitr, NULL, (void **) &data)) { + if (data->conn == conn) + g_hash_table_iter_remove(&htitr); + } +} + + +static int +qemuDomainFDAssociate(virDomainPtr domain, + const char *name, + unsigned int nfds, + int *fds, + unsigned int flags) +{ + virDomainObj *vm = NULL; + qemuDomainObjPrivate *priv; + virStorageSourceFDTuple *new; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_RESTORE | + VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_WRITABLE, -1); + + if (nfds == 0) + return 0; + + if (!(vm = qemuDomainObjFromDomain(domain))) + return -1; + + if (virDomainFdAssociateEnsureACL(domain->conn, vm->def)) + goto cleanup; + + priv = vm->privateData; + + new = virStorageSourceFDTupleNew(); + new->fds = fds; + new->nfds = nfds; + new->conn = domain->conn; + + new->writable = flags & VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_WRITABLE; + new->tryRestoreLabel = flags & VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_RESTORE; + + virCloseCallbacksDomainAdd(vm, domain->conn, qemuDomainFDHashCloseConnect); + + g_hash_table_insert(priv->fds, g_strdup(name), new); + + ret = 0; + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + static virHypervisorDriver qemuHypervisorDriver = { .name = QEMU_DRIVER_NAME, .connectURIProbe = qemuConnectURIProbe, @@ -20627,6 +20693,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */ .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */ .domainSetLaunchSecurityState = qemuDomainSetLaunchSecurityState, /* 8.0.0 */ + .domainFDAssociate = qemuDomainFDAssociate, /* 9.0.0 */ };