'model' attribute was added to a panic device but only one panic
device is allowed. This patch changes panic device presence
from 'optional' to 'zeroOrMore'.
---
v5: part of the code was moved out from this commit
docs/formatdomain.html.in | 1 +
docs/schemas/domaincommon.rng | 4 ++--
src/conf/domain_conf.c | 53 ++++++++++++++++++++-----------------------
src/conf/domain_conf.h | 4 +++-
src/qemu/qemu_command.c | 50 ++++++++++++++++++++++++----------------
src/qemu/qemu_domain.c | 21 +++++++++++++----
6 files changed, 77 insertions(+), 56 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 32b196d..06aec4b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -6152,6 +6152,7 @@ qemu-kvm -net nic,model=? /dev/null
<pre>
...
<devices>
+ <panic model='hyperv'/>
<panic model='isa'>
<address type='isa' iobase='0x505'/>
</panic>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9d21650..7e7fd58 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4044,9 +4044,9 @@
<optional>
<ref name="nvram"/>
</optional>
- <optional>
+ <zeroOrMore>
<ref name="panic"/>
- </optional>
+ </zeroOrMore>
</interleave>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b8738af..ef322f5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2538,7 +2538,9 @@ void virDomainDefFree(virDomainDefPtr def)
virDomainTPMDefFree(def->tpm);
- virDomainPanicDefFree(def->panic);
+ for (i = 0; i < def->npanics; i++)
+ virDomainPanicDefFree(def->panics[i]);
+ VIR_FREE(def->panics);
VIR_FREE(def->idmap.uidmap);
VIR_FREE(def->idmap.gidmap);
@@ -3617,10 +3619,10 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
if (cb(def, &device, &def->tpm->info, opaque) < 0)
return -1;
}
- if (def->panic) {
- device.type = VIR_DOMAIN_DEVICE_PANIC;
- device.data.panic = def->panic;
- if (cb(def, &device, &def->panic->info, opaque) < 0)
+ device.type = VIR_DOMAIN_DEVICE_PANIC;
+ for (i = 0; i < def->npanics; i++) {
+ device.data.panic = def->panics[i];
+ if (cb(def, &device, &def->panics[i]->info, opaque) < 0)
return -1;
}
@@ -16412,23 +16414,19 @@ virDomainDefParseXML(xmlDocPtr xml,
VIR_FREE(nodes);
/* analysis of the panic devices */
- def->panic = NULL;
if ((n = virXPathNodeSet("./devices/panic", ctxt, &nodes)) < 0)
goto error;
- if (n > 1) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("only a single panic device is supported"));
+ if (n && VIR_ALLOC_N(def->panics, n) < 0)
goto error;
- }
- if (n > 0) {
+ for (i = 0; i < n; i++) {
virDomainPanicDefPtr panic =
- virDomainPanicDefParseXML(nodes[0]);
+ virDomainPanicDefParseXML(nodes[i]);
if (!panic)
goto error;
- def->panic = panic;
- VIR_FREE(nodes);
+ def->panics[def->npanics++] = panic;
}
+ VIR_FREE(nodes);
/* analysis of the shmem devices */
if ((n = virXPathNodeSet("./devices/shmem", ctxt, &nodes)) < 0)
@@ -17641,17 +17639,6 @@ static bool
virDomainPanicDefCheckABIStability(virDomainPanicDefPtr src,
virDomainPanicDefPtr dst)
{
- if (!src && !dst)
- return true;
-
- if (!src || !dst) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Target domain panic 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 panic model '%s' does not match source
'%s'"),
@@ -18138,8 +18125,16 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
if (!virDomainRNGDefCheckABIStability(src->rngs[i], dst->rngs[i]))
goto error;
- if (!virDomainPanicDefCheckABIStability(src->panic, dst->panic))
+ if (src->npanics != dst->npanics) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target domain panic device count %zu "
+ "does not match source %zu"), dst->npanics,
src->npanics);
goto error;
+ }
+
+ for (i = 0; i < src->npanics; i++)
+ if (!virDomainPanicDefCheckABIStability(src->panics[i], dst->panics[i]))
+ goto error;
if (src->nshmems != dst->nshmems) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -22457,9 +22452,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
if (def->nvram)
virDomainNVRAMDefFormat(buf, def->nvram, flags);
- if (def->panic &&
- virDomainPanicDefFormat(buf, def->panic) < 0)
- goto error;
+ for (n = 0; n < def->npanics; n++)
+ if (virDomainPanicDefFormat(buf, def->panics[n]) < 0)
+ goto error;
for (n = 0; n < def->nshmems; n++)
if (virDomainShmemDefFormat(buf, def->shmems[n], flags) < 0)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 11d891f..038d65b 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2316,6 +2316,9 @@ struct _virDomainDef {
size_t nmems;
virDomainMemoryDefPtr *mems;
+ size_t npanics;
+ virDomainPanicDefPtr *panics;
+
/* Only 1 */
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
@@ -2324,7 +2327,6 @@ struct _virDomainDef {
virCPUDefPtr cpu;
virSysinfoDefPtr sysinfo;
virDomainRedirFilterDefPtr redirfilter;
- virDomainPanicDefPtr panic;
void *namespaceData;
virDomainXMLNamespace ns;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index bb6d5fe..5eb8ac0 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7577,14 +7577,16 @@ qemuBuildCpuArgStr(virQEMUDriverPtr driver,
}
}
- if (def->panic &&
- def->panic->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
- if (!have_cpu) {
- virBufferAdd(&buf, default_model, -1);
- have_cpu = true;
- }
+ for (i = 0; i < def->npanics; i++) {
+ if (def->panics[i]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
+ if (!have_cpu) {
+ virBufferAdd(&buf, default_model, -1);
+ have_cpu = true;
+ }
- virBufferAddLit(&buf, ",hv_crash");
+ virBufferAddLit(&buf, ",hv_crash");
+ break;
+ }
}
if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
@@ -11059,8 +11061,8 @@ qemuBuildCommandLine(virConnectPtr conn,
goto error;
}
- if (def->panic) {
- switch ((virDomainPanicModel) def->panic->model) {
+ for (i = 0; i < def->npanics; i++) {
+ switch ((virDomainPanicModel) def->panics[i]->model) {
case VIR_DOMAIN_PANIC_MODEL_HYPERV:
/* Panic with model 'hyperv' is not a device, it should
* be configured in cpu commandline. The address
@@ -11071,7 +11073,7 @@ qemuBuildCommandLine(virConnectPtr conn,
"panic device of model 'hyperv'"));
goto error;
}
- if (def->panic->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ if (def->panics[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
{
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("setting the panic device address is not "
"supported for model 'hyperv'"));
@@ -11084,7 +11086,7 @@ qemuBuildCommandLine(virConnectPtr conn,
/* For pSeries guests, the firmware provides the same
* functionality as the pvpanic device. The address
* cannot be configured by the user */
- if (def->panic->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
{
+ if (def->panics[i]->info.type !=
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("setting the panic device address is not
"
"supported for model
'pseries'"));
@@ -11106,11 +11108,11 @@ qemuBuildCommandLine(virConnectPtr conn,
goto error;
}
- switch (def->panic->info.type) {
+ switch (def->panics[i]->info.type) {
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
virCommandAddArg(cmd, "-device");
virCommandAddArgFormat(cmd, "pvpanic,ioport=%d",
- def->panic->info.addr.isa.iobase);
+ def->panics[i]->info.addr.isa.iobase);
break;
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
@@ -12480,12 +12482,22 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
goto cleanup;
}
} else if (STREQ(tokens[i], "hv_crash")) {
- virDomainPanicDefPtr panic;
- if (VIR_ALLOC(panic) < 0)
- goto cleanup;
-
- panic->model = VIR_DOMAIN_PANIC_MODEL_HYPERV;
- dom->panic = panic;
+ size_t j;
+ for (j = 0; j < dom->npanics; j++) {
+ if (dom->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV)
+ break;
+ }
+
+ if (j == dom->npanics) {
+ virDomainPanicDefPtr panic;
+ if (VIR_ALLOC(panic) < 0 ||
+ VIR_APPEND_ELEMENT_COPY(dom->panics,
+ dom->npanics, panic) < 0) {
+ VIR_FREE(panic);
+ goto cleanup;
+ }
+ panic->model = VIR_DOMAIN_PANIC_MODEL_HYPERV;
+ }
} else if (STRPREFIX(tokens[i], "hv_")) {
const char *token = tokens[i] + 3; /* "hv_" */
const char *feature, *value;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 689abc2..8e6c038 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1178,12 +1178,23 @@ qemuDomainDefPostParse(virDomainDefPtr def,
VIR_DOMAIN_INPUT_BUS_USB) < 0)
goto cleanup;
- if (addPanicDevice && !def->panic) {
- virDomainPanicDefPtr panic;
- if (VIR_ALLOC(panic) < 0)
- goto cleanup;
+ if (addPanicDevice) {
+ size_t j;
+ for (j = 0; j < def->npanics; j++) {
+ if (def->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_DEFAULT ||
+ def->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_PSERIES)
+ break;
+ }
- def->panic = panic;
+ if (j == def->npanics) {
+ virDomainPanicDefPtr panic;
+ if (VIR_ALLOC(panic) < 0 ||
+ VIR_APPEND_ELEMENT_COPY(def->panics,
+ def->npanics, panic) < 0) {
+ VIR_FREE(panic);
+ goto cleanup;
+ }
+ }
}
ret = 0;
--
1.8.3.1