mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
qemu: Wire up better early error reporting
The previous patches added infrastructure to report better errors from monitor in some cases. This patch finalizes this "feature" by enabling this enhanced error reporting on early phases of VM startup. In these phases the possibility of qemu producing a useful error message is really high compared to running it during the whole life cycle. After the start up is complete, the feature is disabled to provide the usual error messages so that users are not confused by possibly irrelevant messages that may be in the domain log. The original motivation to do this enhancement is to capture errors when using VFIO device passthrough, where qemu reports errors after the monitor is initialized and the existing error catching code couldn't catch this producing a unhelpful message: # virsh start test error: Failed to start domain test error: Unable to read from monitor: Connection reset by peer With this change, the message is changed to: # virsh start test error: Failed to start domain test error: internal error: early end of file from monitor: possible problem: qemu-system-x86_64: -device vfio-pci,host=00:1a.0,id=hostdev0,bus=pci.0,addr=0x5: vfio: error, group 8 is not viable, please ensure all devices within the iommu_group are bound to their vfio bus driver. qemu-system-x86_64: -device vfio-pci,host=00:1a.0,id=hostdev0,bus=pci.0,addr=0x5: vfio: failed to get group 8 qemu-system-x86_64: -device vfio-pci,host=00:1a.0,id=hostdev0,bus=pci.0,addr=0x5: Device 'vfio-pci' could not be initialized
This commit is contained in:
parent
90139a6236
commit
ef29de14c3
@ -1389,7 +1389,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm)
|
qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int logfd)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@ -1415,6 +1415,9 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm)
|
|||||||
&monitorCallbacks,
|
&monitorCallbacks,
|
||||||
driver);
|
driver);
|
||||||
|
|
||||||
|
if (mon)
|
||||||
|
ignore_value(qemuMonitorSetDomainLog(mon, logfd));
|
||||||
|
|
||||||
virObjectLock(vm);
|
virObjectLock(vm);
|
||||||
priv->monStart = 0;
|
priv->monStart = 0;
|
||||||
|
|
||||||
@ -1794,11 +1797,11 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
|
|||||||
virHashTablePtr paths = NULL;
|
virHashTablePtr paths = NULL;
|
||||||
qemuDomainObjPrivatePtr priv;
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
|
||||||
if (!virQEMUCapsUsedQMP(qemuCaps)
|
if (pos != -1 &&
|
||||||
&& pos != -1) {
|
(logfd = qemuDomainOpenLog(driver, vm, pos)) < 0)
|
||||||
if ((logfd = qemuDomainOpenLog(driver, vm, pos)) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (logfd != -1 && !virQEMUCapsUsedQMP(qemuCaps)) {
|
||||||
if (VIR_ALLOC_N(buf, buf_size) < 0)
|
if (VIR_ALLOC_N(buf, buf_size) < 0)
|
||||||
goto closelog;
|
goto closelog;
|
||||||
|
|
||||||
@ -1809,9 +1812,8 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
|
VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
|
||||||
if (qemuConnectMonitor(driver, vm) < 0) {
|
if (qemuConnectMonitor(driver, vm, logfd) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to get the pty path mappings again via the monitor. This is much more
|
/* Try to get the pty path mappings again via the monitor. This is much more
|
||||||
* reliable if it's available.
|
* reliable if it's available.
|
||||||
@ -1838,14 +1840,15 @@ cleanup:
|
|||||||
/* VM is dead, any other error raised in the interim is probably
|
/* VM is dead, any other error raised in the interim is probably
|
||||||
* not as important as the qemu cmdline output */
|
* not as important as the qemu cmdline output */
|
||||||
if (virQEMUCapsUsedQMP(qemuCaps)) {
|
if (virQEMUCapsUsedQMP(qemuCaps)) {
|
||||||
if ((logfd = qemuDomainOpenLog(driver, vm, pos)) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (VIR_ALLOC_N(buf, buf_size) < 0)
|
if (VIR_ALLOC_N(buf, buf_size) < 0)
|
||||||
goto closelog;
|
goto closelog;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
|
/* best effor seek - we need to reset to the original position, so that
|
||||||
|
* a possible read of the fd in the monitor code doesn't influence this
|
||||||
|
* error delivery option */
|
||||||
|
lseek(logfd, pos, SEEK_SET);
|
||||||
qemuProcessReadLog(logfd, buf + len, buf_size - len - 1, 0, true);
|
qemuProcessReadLog(logfd, buf + len, buf_size - len - 1, 0, true);
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("process exited while connecting to monitor: %s"),
|
_("process exited while connecting to monitor: %s"),
|
||||||
@ -3080,7 +3083,7 @@ qemuProcessReconnect(void *opaque)
|
|||||||
virObjectRef(obj);
|
virObjectRef(obj);
|
||||||
|
|
||||||
/* XXX check PID liveliness & EXE path */
|
/* XXX check PID liveliness & EXE path */
|
||||||
if (qemuConnectMonitor(driver, obj) < 0)
|
if (qemuConnectMonitor(driver, obj, -1) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Failure to connect to agent shouldn't be fatal */
|
/* Failure to connect to agent shouldn't be fatal */
|
||||||
@ -4047,6 +4050,9 @@ int qemuProcessStart(virConnectPtr conn,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* unset reporting errors from qemu log */
|
||||||
|
qemuMonitorSetDomainLog(priv->mon, -1);
|
||||||
|
|
||||||
virCommandFree(cmd);
|
virCommandFree(cmd);
|
||||||
VIR_FORCE_CLOSE(logfile);
|
VIR_FORCE_CLOSE(logfile);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
@ -4062,6 +4068,8 @@ cleanup:
|
|||||||
virBitmapFree(nodemask);
|
virBitmapFree(nodemask);
|
||||||
virCommandFree(cmd);
|
virCommandFree(cmd);
|
||||||
VIR_FORCE_CLOSE(logfile);
|
VIR_FORCE_CLOSE(logfile);
|
||||||
|
if (priv->mon)
|
||||||
|
qemuMonitorSetDomainLog(priv->mon, -1);
|
||||||
qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, stop_flags);
|
qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, stop_flags);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user