提交 b606bbb4 编写于 作者: M Michal Privoznik

qemu: Issue rtc-reset-reinjection command after guest-set-time

https://bugzilla.redhat.com/show_bug.cgi?id=1103245

An advice appeared there on the qemu-devel list [1]. When a domain is
suspended and then resumed guest kernel is not aware of this. So we've
introduced virDomainSetTime API that resets the time within guest
using qemu-ga. On the other hand, qemu itself is trying to make RTC
beat faster to catch the difference. But if we don't tell qemu that
guest's time was reset via the other method, both mechanisms are
applied resulting in again wrong guest time. In order to avoid summing
both corrections we need to tell qemu that it should not use the RTC
injection if the guest time is set via guest agent.

1: http://www.mail-archive.com/qemu-devel@nongnu.org/msg236435.htmlSigned-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 970ac2a0
......@@ -265,6 +265,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"numa",
"memory-backend-file",
"usb-audio",
"rtc-reset-reinjection",
);
......@@ -1424,6 +1425,7 @@ struct virQEMUCapsStringFlags virQEMUCapsCommands[] = {
{ "add-fd", QEMU_CAPS_ADD_FD },
{ "nbd-server-start", QEMU_CAPS_NBD_SERVER },
{ "change-backing-file", QEMU_CAPS_CHANGE_BACKING_FILE },
{ "rtc-reset-reinjection", QEMU_CAPS_RTC_RESET_REINJECTION },
};
struct virQEMUCapsStringFlags virQEMUCapsEvents[] = {
......
......@@ -213,6 +213,7 @@ typedef enum {
QEMU_CAPS_NUMA = 171, /* newer -numa handling with disjoint cpu ranges */
QEMU_CAPS_OBJECT_MEMORY_FILE = 172, /* -object memory-backend-file */
QEMU_CAPS_OBJECT_USB_AUDIO = 173, /* usb-audio device support */
QEMU_CAPS_RTC_RESET_REINJECTION = 174, /* rtc-reset-reinjection monitor command */
QEMU_CAPS_LAST, /* this must always be the last item */
} virQEMUCapsFlags;
......
......@@ -16844,6 +16844,13 @@ qemuDomainSetTime(virDomainPtr dom,
priv = vm->privateData;
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION)) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("cannot set time: qemu doesn't support "
"rtc-reset-reinjection command"));
goto cleanup;
}
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
......@@ -16860,6 +16867,16 @@ qemuDomainSetTime(virDomainPtr dom,
rv = qemuAgentSetTime(priv->agent, seconds, nseconds, rtcSync);
qemuDomainObjExitAgent(vm);
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
}
qemuDomainObjEnterMonitor(driver, vm);
rv = qemuMonitorRTCResetReinjection(priv->mon);
qemuDomainObjExitMonitor(driver, vm);
if (rv < 0)
goto endjob;
......
......@@ -4037,3 +4037,36 @@ qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
return qemuMonitorJSONGetGuestCPU(mon, arch, data);
}
/**
* qemuMonitorRTCResetReinjection:
* @mon: Pointer to the monitor
*
* Issue rtc-reset-reinjection command.
* This should be used in cases where guest time is restored via
* guest agent, so RTC injection is not needed (in fact it would
* confuse guest's RTC).
*
* Returns 0 on success
* -1 on error.
*/
int
qemuMonitorRTCResetReinjection(qemuMonitorPtr mon)
{
VIR_DEBUG("mon=%p", mon);
if (!mon) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("monitor must not be NULL"));
return -1;
}
if (!mon->json) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("JSON monitor is required"));
return -1;
}
return qemuMonitorJSONRTCResetReinjection(mon);
}
......@@ -790,6 +790,8 @@ int qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
virArch arch,
virCPUDataPtr *data);
int qemuMonitorRTCResetReinjection(qemuMonitorPtr mon);
/**
* When running two dd process and using <> redirection, we need a
* shell that will not truncate files. These two strings serve that
......
......@@ -5851,3 +5851,24 @@ qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
return -1;
}
}
int
qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon)
{
int ret = -1;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("rtc-reset-reinjection",
NULL)))
return ret;
ret = qemuMonitorJSONCommand(mon, cmd, &reply);
if (ret == 0)
ret = qemuMonitorJSONCheckError(cmd, reply);
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}
......@@ -437,4 +437,6 @@ int qemuMonitorJSONGetDeviceAliases(qemuMonitorPtr mon,
int qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
virArch arch,
virCPUDataPtr *data);
int qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon);
#endif /* QEMU_MONITOR_JSON_H */
......@@ -2279,6 +2279,7 @@ mymain(void)
DO_TEST_SIMPLE("inject-nmi", qemuMonitorJSONInjectNMI);
DO_TEST_SIMPLE("system_wakeup", qemuMonitorJSONSystemWakeup);
DO_TEST_SIMPLE("nbd-server-stop", qemuMonitorJSONNBDServerStop);
DO_TEST_SIMPLE("rtc-reset-reinjection", qemuMonitorJSONRTCResetReinjection);
DO_TEST_GEN(qemuMonitorJSONSetLink);
DO_TEST_GEN(qemuMonitorJSONBlockResize);
DO_TEST_GEN(qemuMonitorJSONSetVNCPassword);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册