virtio-rng: allow multiple RNG devices

qemu supports adding multiple RNG devices. This patch allows libvirt to
support this.
This commit is contained in:
Peter Krempa 2013-02-25 23:31:11 +01:00
parent 99ff49eed1
commit bbddbefa2f
5 changed files with 65 additions and 59 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
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";
/* 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;
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;

View File

@ -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;
}