Go through disks of guest, if one disk doesn't exist or its backing
chain is broken, with 'optional' startupPolicy, for CDROM and Floppy
we only discard its source path definition in xml, for disks we drop
it from disk list and free it.
Originally, for these disks without startupPolicy attribute, libvirt
ignore the presence checking, this patch make startupPolicy 'mandatory'
as default.
---
include/libvirt/libvirt.h.in | 1 +
src/qemu/qemu_domain.c | 119 ++++++++++++++++++++++++++-----------------
src/qemu/qemu_process.c | 7 ---
3 files changed, 74 insertions(+), 53 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index b791125..5459eb4 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -4699,6 +4699,7 @@ typedef void (*virConnectDomainEventBlockJobCallback)(virConnectPtr
conn,
*/
typedef enum {
VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START = 0, /* oldSrcPath is set */
+ VIR_DOMAIN_EVENT_HARDDISK_DROP_MISSING_ON_START = 1,
#ifdef VIR_ENUM_SENTINELS
VIR_DOMAIN_EVENT_DISK_CHANGE_LAST
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 8d79066..d54d477 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2006,75 +2006,102 @@ cleanup:
virObjectUnref(cfg);
}
+static int
+qemuDomainCheckRemoveOptionalDisk(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainDiskDefPtr disk)
+{
+ char uuid[VIR_UUID_STRING_BUFLEN];
+ virDomainEventPtr event = NULL;
+ virDomainDiskDefPtr del_disk = NULL;
+
+ virUUIDFormat(vm->def->uuid, uuid);
+
+ VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s')
"
+ "due to inaccessible source '%s'",
+ disk->dst, vm->def->name, uuid, disk->src);
+
+ if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
+ disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+
+ event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
+ disk->info.alias,
+
VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
+
+ VIR_FREE(disk->src);
+ } else {
+ event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
+ disk->info.alias,
+
VIR_DOMAIN_EVENT_HARDDISK_DROP_MISSING_ON_START);
+
+ if (!(del_disk = virDomainDiskRemoveByName(vm->def, disk->src))) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("no source device %s"), disk->src);
+ return -1;
+ }
+ virDomainDiskDefFree(del_disk);
+ }
+
+ if (event)
+ qemuDomainEventQueue(driver, event);
+
+ return 0;
+}
+
int
qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
virDomainObjPtr vm,
bool cold_boot)
{
int ret = -1;
- int i;
+ size_t i;
virDomainDiskDefPtr disk;
- char uuid[VIR_UUID_STRING_BUFLEN];
- virDomainEventPtr event = NULL;
- virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
-
- virUUIDFormat(vm->def->uuid, uuid);
-
- for (i = 0; i < vm->def->ndisks; i++) {
- disk = vm->def->disks[i];
+ size_t count = vm->def->ndisks;
+ size_t nextdisk = 0;
- if (!disk->startupPolicy || !disk->src)
- continue;
+ for (i = 0; i < count; i++) {
+ disk = vm->def->disks[nextdisk];
- if (virFileAccessibleAs(disk->src, F_OK,
- cfg->user,
- cfg->group) >= 0) {
- /* disk accessible */
+ if (qemuDomainDetermineDiskChain(driver, disk, false) == 0) {
+ nextdisk++;
continue;
}
switch ((enum virDomainStartupPolicy) disk->startupPolicy) {
- case VIR_DOMAIN_STARTUP_POLICY_OPTIONAL:
- break;
+ case VIR_DOMAIN_STARTUP_POLICY_OPTIONAL:
+ break;
- case VIR_DOMAIN_STARTUP_POLICY_MANDATORY:
- virReportSystemError(errno,
- _("cannot access file '%s'"),
- disk->src);
- goto cleanup;
- break;
-
- case VIR_DOMAIN_STARTUP_POLICY_REQUISITE:
- if (cold_boot) {
- virReportSystemError(errno,
- _("cannot access file '%s'"),
- disk->src);
- goto cleanup;
- }
- break;
+ case VIR_DOMAIN_STARTUP_POLICY_REQUISITE:
+ if (cold_boot) {
+ goto error;
+ }
+ break;
+
+ case VIR_DOMAIN_STARTUP_POLICY_MANDATORY:
+ case VIR_DOMAIN_STARTUP_POLICY_DEFAULT:
+ goto error;
- case VIR_DOMAIN_STARTUP_POLICY_DEFAULT:
- case VIR_DOMAIN_STARTUP_POLICY_LAST:
- /* this should never happen */
- break;
+ case VIR_DOMAIN_STARTUP_POLICY_LAST:
+ /* this should never happen */
+ break;
}
- VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID
'%s') "
- "due to inaccessible source '%s'",
- disk->dst, vm->def->name, uuid, disk->src);
+ virResetLastError();
- event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
disk->info.alias,
-
VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
- if (event)
- qemuDomainEventQueue(driver, event);
+ /* For cdrom or floppy, we only remove its source definition,
+ * so, the nextdisk need to point to next disk in next loop.
+ */
+ if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
+ disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
+ nextdisk++;
- VIR_FREE(disk->src);
+ if (qemuDomainCheckRemoveOptionalDisk(driver, vm, disk) < 0)
+ goto error;
}
ret = 0;
-cleanup:
- virObjectUnref(cfg);
+error:
return ret;
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ac5ffcf..4672f7f 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3543,17 +3543,10 @@ int qemuProcessStart(virConnectPtr conn,
if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
goto cleanup;
- VIR_DEBUG("Checking for CDROM and floppy presence");
if (qemuDomainCheckDiskPresence(driver, vm,
flags & VIR_QEMU_PROCESS_START_COLD) < 0)
goto cleanup;
- for (i = 0; i < vm->def->ndisks; i++) {
- if (qemuDomainDetermineDiskChain(driver, vm->def->disks[i],
- false) < 0)
- goto cleanup;
- }
-
/* Get the advisory nodeset from numad if 'placement' of
* either <vcpu> or <numatune> is 'auto'.
*/
--
1.8.1.4