qemu supports adding multiple RNG devices. This patch allows libvirt to
support this.
---
src/conf/domain_audit.c | 4 ++--
src/conf/domain_conf.c | 58 ++++++++++++++++++++++++-------------------------
src/conf/domain_conf.h | 4 +++-
src/qemu/qemu_cgroup.c | 33 ++++++++++++++--------------
src/qemu/qemu_command.c | 29 ++++++++++++++-----------
5 files changed, 67 insertions(+), 61 deletions(-)
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index 3ad58b0..2d1b1fb 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -874,8 +874,8 @@ virDomainAuditStart(virDomainObjPtr vm, const char *reason, bool
success)
for (i = 0; i < vm->def->nsmartcards; i++)
virDomainAuditSmartcard(vm, vm->def->smartcards[i], "start",
true);
- if (vm->def->rng)
- virDomainAuditRNG(vm, NULL, vm->def->rng, "start", true);
+ for (i = 0; i < vm->def->nrngs; i++)
+ virDomainAuditRNG(vm, NULL, vm->def->rngs[i], "start", true);
if (vm->def->tpm)
virDomainAuditTPM(vm, vm->def->tpm, "start", true);
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 1b43a26..9c3cd8a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2057,7 +2057,9 @@ void virDomainDefFree(virDomainDefPtr def)
virDomainRedirdevDefFree(def->redirdevs[i]);
VIR_FREE(def->redirdevs);
- virDomainRNGDefFree(def->rng);
+ for (i = 0; i < def->nrngs; i++)
+ virDomainRNGDefFree(def->rngs[i]);
+ VIR_FREE(def->rngs);
virDomainTPMDefFree(def->tpm);
@@ -2745,10 +2747,10 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
if (cb(def, &device, &def->memballoon->info, opaque) < 0)
return -1;
}
- if (def->rng) {
- device.type = VIR_DOMAIN_DEVICE_RNG;
- device.data.rng = def->rng;
- if (cb(def, &device, &def->rng->info, opaque) < 0)
+ device.type = VIR_DOMAIN_DEVICE_RNG;
+ for (i = 0; i < def->nrngs; i++) {
+ device.data.rng = def->rngs[i];
+ if (cb(def, &device, &def->rngs[i]->info, opaque) < 0)
return -1;
}
if (def->nvram) {
@@ -12821,20 +12823,19 @@ virDomainDefParseXML(xmlDocPtr xml,
VIR_FREE(nodes);
}
- /* Parse the RNG device */
+ /* Parse the RNG devices */
if ((n = virXPathNodeSet("./devices/rng", ctxt, &nodes)) < 0)
goto error;
-
- if (n > 1) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("only a single RNG device is supported"));
+ if (n && VIR_ALLOC_N(def->rngs, n) < 0)
goto error;
- }
-
- if (n > 0) {
- if (!(def->rng = virDomainRNGDefParseXML(nodes[0], ctxt, flags)))
+ for (i = 0; i < n; i++) {
+ virDomainRNGDefPtr rng = virDomainRNGDefParseXML(nodes[i],
+ ctxt,
+ flags);
+ if (!rng)
goto error;
- VIR_FREE(nodes);
+
+ def->rngs[def->nrngs++] = rng;
}
VIR_FREE(nodes);
@@ -13864,17 +13865,6 @@ static bool
virDomainRNGDefCheckABIStability(virDomainRNGDefPtr src,
virDomainRNGDefPtr dst)
{
- if (!src && !dst)
- return true;
-
- if (!src || !dst) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Target domain RNG device count '%d' "
- "does not match source count '%d'"),
- src ? 1 : 0, dst ? 1 : 0);
- return false;
- }
-
if (src->model != dst->model) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target RNG model '%s' does not match source
'%s'"),
@@ -14439,8 +14429,16 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
dst->memballoon))
goto error;
- if (!virDomainRNGDefCheckABIStability(src->rng, dst->rng))
+ if (src->nrngs != dst->nrngs) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target domain RNG device count %zu "
+ "does not match source %zu"), dst->nrngs,
src->nrngs);
goto error;
+ }
+
+ for (i = 0; i < src->nrngs; i++)
+ if (!virDomainRNGDefCheckABIStability(src->rngs[i], dst->rngs[i]))
+ goto error;
if (!virDomainPanicCheckABIStability(src->panic, dst->panic))
goto error;
@@ -18020,8 +18018,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
if (def->memballoon)
virDomainMemballoonDefFormat(buf, def->memballoon, flags);
- if (def->rng)
- virDomainRNGDefFormat(buf, def->rng, flags);
+ for (n = 0; n < def->nrngs; n++) {
+ if (virDomainRNGDefFormat(buf, def->rngs[n], flags))
+ goto error;
+ }
if (def->nvram)
virDomainNVRAMDefFormat(buf, def->nvram, flags);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 55292e1..b988b17 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1981,6 +1981,9 @@ struct _virDomainDef {
size_t nseclabels;
virSecurityLabelDefPtr *seclabels;
+ size_t nrngs;
+ virDomainRNGDefPtr *rngs;
+
/* Only 1 */
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
@@ -1989,7 +1992,6 @@ struct _virDomainDef {
virCPUDefPtr cpu;
virSysinfoDefPtr sysinfo;
virDomainRedirFilterDefPtr redirfilter;
- virDomainRNGDefPtr rng;
virDomainPanicDefPtr panic;
void *namespaceData;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index f649d66..419be9a 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -584,22 +584,23 @@ qemuSetupDevicesCgroup(virQEMUDriverPtr driver,
goto cleanup;
}
- if (vm->def->rng &&
- (vm->def->rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM)) {
- VIR_DEBUG("Setting Cgroup ACL for RNG device");
- const char *rngpath = vm->def->rng->source.file;
-
- /* fix path when using the default */
- if (!rngpath)
- rngpath = "/dev/random";
-
- rv = virCgroupAllowDevicePath(priv->cgroup, rngpath,
- VIR_CGROUP_DEVICE_RW);
- virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
- rngpath, "rw", rv == 0);
- if (rv < 0 &&
- !virLastErrorIsSystemErrno(ENOENT))
- goto cleanup;
+ for (i = 0; i < vm->def->nrngs; i++) {
+ if (vm->def->rngs[i]->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM) {
+ VIR_DEBUG("Setting Cgroup ACL for RNG device");
+ const char *rngpath = vm->def->rngs[i]->source.file;
+
+ /* fix path when using the default */
+ if (!rngpath)
+ rngpath = "/dev/random";
+
+ rv = virCgroupAllowDevicePath(priv->cgroup, rngpath,
+ VIR_CGROUP_DEVICE_RW);
+ virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
+ rngpath, "rw", rv == 0);
+ if (rv < 0 &&
+ !virLastErrorIsSystemErrno(ENOENT))
+ goto cleanup;
+ }
}
ret = 0;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index c5e86b4..7f9357c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1050,8 +1050,8 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr
qemuCaps)
if (virAsprintf(&def->memballoon->info.alias, "balloon%d", 0)
< 0)
return -1;
}
- if (def->rng) {
- if (virAsprintf(&def->rng->info.alias, "rng%d", 0) < 0)
+ for (i = 0; i < def->nrngs; i++) {
+ if (virAsprintf(&def->rngs[i]->info.alias, "rng%zu", i) <
0)
return -1;
}
if (def->tpm) {
@@ -1102,10 +1102,11 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
def->memballoon->info.type = type;
- if (def->rng &&
- def->rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO &&
- def->rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
- def->rng->info.type = type;
+ for (i = 0; i < def->nrngs; i++) {
+ if (def->rngs[i]->model == VIR_DOMAIN_RNG_MODEL_VIRTIO &&
+ def->rngs[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ def->rngs[i]->info.type = type;
+ }
}
@@ -2232,11 +2233,13 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
}
/* VirtIO RNG */
- if (def->rng &&
- def->rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO &&
- def->rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ for (i = 0; i < def->nrngs; i++) {
+ if (def->rngs[i]->model != VIR_DOMAIN_RNG_MODEL_VIRTIO ||
+ def->rngs[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ continue;
+
if (virDomainPCIAddressReserveNextSlot(addrs,
- &def->rng->info, flags) < 0)
+ &def->rngs[i]->info, flags) <
0)
goto error;
}
@@ -9163,13 +9166,13 @@ qemuBuildCommandLine(virConnectPtr conn,
}
}
- if (def->rng) {
+ for (i = 0; i < def->nrngs; i++) {
/* add the RNG source backend */
- if (qemuBuildRNGBackendArgs(cmd, def->rng, qemuCaps) < 0)
+ if (qemuBuildRNGBackendArgs(cmd, def->rngs[i], qemuCaps) < 0)
goto error;
/* add the device */
- if (qemuBuildRNGDeviceArgs(cmd, def, def->rng, qemuCaps) < 0)
+ if (qemuBuildRNGDeviceArgs(cmd, def, def->rngs[i], qemuCaps) < 0)
goto error;
}
--
2.0.0