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 <pkrempa(a)redhat.com>
Reviewed-by: Pavel Hrdina <phrdina(a)redhat.com>
---
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 5c05032ce3..33a9145cc9 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1845,6 +1845,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) {
@@ -1872,6 +1873,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 2f027fad87..1cba3fa394 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 f4bd081f3c..e86ebd8330 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20643,6 +20643,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,
@@ -20891,6 +20957,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
.domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */
.domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
.domainSetLaunchSecurityState = qemuDomainSetLaunchSecurityState, /* 8.0.0 */
+ .domainFDAssociate = qemuDomainFDAssociate, /* 9.0.0 */
};
--
2.38.1