Bug fix for:
https://bugzilla.redhat.com/show_bug.cgi?id=1257844
Attach-device can hotplug a virtio disk device with any address type now,
it need to validate the address type before the attachment.
Attaching a disk device with --config option need to check address type.
Otherwise, the domain cloudn't be started normally. This patch add a basic
check for address type.
Detaching a disk device with --config also need to check disk options,
add qemuCheckDiskConfig() method in qemuDomainDetachDeviceConfig().
Add virDomainDeviceAddressTypeIsValid method in domain_conf to check disk
address type. Address type should match with disk driver, report error
messages if any mismatch.
Signed-off-by: Ruifeng Bian <rbian(a)redhat.com>
---
src/conf/domain_conf.c | 32 ++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 1 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 7 +++++++
src/qemu/qemu_driver.c | 2 ++
src/qemu/qemu_hotplug.c | 22 ++++++++++++++++++++++
6 files changed, 65 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6df1618..f86760b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3200,6 +3200,38 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
return 0;
}
+int virDomainDeviceAddressTypeIsValid(virDomainDiskDefPtr disk)
+{
+ if (disk->info.type) {
+ switch (disk->bus) {
+ case VIR_DOMAIN_DISK_BUS_IDE:
+ case VIR_DOMAIN_DISK_BUS_SCSI:
+ case VIR_DOMAIN_DISK_BUS_SATA:
+ case VIR_DOMAIN_DISK_BUS_FDC:
+ if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
+ return 1;
+ break;
+ case VIR_DOMAIN_DISK_BUS_USB:
+ if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB)
+ return 1;
+ break;
+ case VIR_DOMAIN_DISK_BUS_VIRTIO:
+ if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
+ disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390
&&
+ disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO
&&
+ disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
+ return 1;
+ break;
+ case VIR_DOMAIN_DISK_BUS_XEN:
+ case VIR_DOMAIN_DISK_BUS_UML:
+ case VIR_DOMAIN_DISK_BUS_SD:
+ /* no address type currently, return false if address provided */
+ return 1;
+ }
+ }
+ return 0;
+}
+
virDomainDeviceInfoPtr
virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
{
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f043554..337fe51 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2543,6 +2543,7 @@ virDomainDeviceDefPtr virDomainDeviceDefCopy(virDomainDeviceDefPtr
src,
virDomainXMLOptionPtr xmlopt);
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
int type);
+int virDomainDeviceAddressTypeIsValid(virDomainDiskDefPtr disk);
virDomainDeviceInfoPtr virDomainDeviceGetInfo(virDomainDeviceDefPtr device);
int virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst,
virDomainDeviceInfoPtr src);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5b3da83..6cd5b9e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -229,6 +229,7 @@ virDomainDefPostParse;
virDomainDefSetMemoryInitial;
virDomainDeleteConfig;
virDomainDeviceAddressIsValid;
+virDomainDeviceAddressTypeIsValid;
virDomainDeviceAddressTypeToString;
virDomainDeviceDefCheckUnsupportedMemoryDevice;
virDomainDeviceDefCopy;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 25f57f2..56ba08d 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3606,6 +3606,13 @@ qemuCheckDiskConfig(virDomainDiskDefPtr disk)
goto error;
}
}
+
+ if (virDomainDeviceAddressTypeIsValid(disk)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("disk cannot have an address of type '%s'"),
+ virDomainDeviceAddressTypeToString(disk->info.type));
+ goto error;
+ }
return 0;
error:
return -1;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index fcf86b6..26c1502 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8208,6 +8208,8 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
switch ((virDomainDeviceType) dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
disk = dev->data.disk;
+ if (qemuCheckDiskConfig(disk) < 0)
+ return -1;
if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
virReportError(VIR_ERR_INVALID_ARG,
_("no target device %s"), disk->dst);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index e84a78d..6156243 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -336,6 +336,28 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn,
if (!qemuCheckCCWS390AddressSupport(vm->def, disk->info,
priv->qemuCaps,
disk->dst))
goto cleanup;
+
+ if (qemuDomainMachineIsS390CCW(vm->def) &&
+ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) {
+ if (!virDomainDeviceAddressIsValid(&disk->info,
+ VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("device cannot be attached without a valid CCW
address"));
+ goto cleanup;
+ }
+ } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) {
+ if (!virDomainDeviceAddressIsValid(&disk->info,
+
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390)) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("device cannot be attached without a valid S390
address"));
+ goto cleanup;
+ }
+ } else if (!virDomainDeviceAddressIsValid(&disk->info,
+ VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("device cannot be attached without a valid PCI
address"));
+ goto cleanup;
+ }
}
for (i = 0; i < vm->def->ndisks; i++) {
--
2.4.3