1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

qemu: Avoid excessive calls to qemuDomainObjSaveJob()

As reported by Daniel Berrangé, we have a huge performance regression
for virDomainGetInfo() due to the change which makes virDomainEndJob()
save the XML status file every time it is called. Previous to that
change, 2000 calls to virDomainGetInfo() took ~2.5 seconds. After that
change, 2000 calls to virDomainGetInfo() take 2 *minutes* 45 secs.

We made the change to be able to recover from libvirtd restart in the
middle of a job. However, only destroy and async jobs are taken care of.
Thus it makes more sense to only save domain state XML when these jobs
are started/stopped.
This commit is contained in:
Jiri Denemark 2012-04-06 19:42:34 +02:00
parent 1bd587abe2
commit 31796e2c1c
3 changed files with 27 additions and 3 deletions

View File

@ -183,6 +183,12 @@ qemuDomainObjFreeJob(qemuDomainObjPrivatePtr priv)
ignore_value(virCondDestroy(&priv->job.asyncCond));
}
static bool
qemuDomainTrackJob(enum qemuDomainJob job)
{
return (QEMU_DOMAIN_TRACK_JOBS & JOB_MASK(job)) != 0;
}
static void *qemuDomainObjPrivateAlloc(void)
{
@ -239,6 +245,7 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
{
qemuDomainObjPrivatePtr priv = data;
const char *monitorpath;
enum qemuDomainJob job;
/* priv->monitor_chr is set only for qemu */
if (priv->monConfig) {
@ -284,6 +291,10 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
if (priv->lockState)
virBufferAsprintf(buf, " <lockstate>%s</lockstate>\n", priv->lockState);
job = priv->job.active;
if (!qemuDomainTrackJob(job))
priv->job.active = QEMU_JOB_NONE;
if (priv->job.active || priv->job.asyncJob) {
virBufferAsprintf(buf, " <job type='%s' async='%s'",
qemuDomainJobTypeToString(priv->job.active),
@ -295,6 +306,7 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
}
virBufferAddLit(buf, "/>\n");
}
priv->job.active = job;
if (priv->fakeReboot)
virBufferAsprintf(buf, " <fakereboot/>\n");
@ -766,7 +778,8 @@ retry:
virDomainObjLock(obj);
}
qemuDomainObjSaveJob(driver, obj);
if (qemuDomainTrackJob(job))
qemuDomainObjSaveJob(driver, obj);
return 0;
@ -862,15 +875,17 @@ int qemuDomainObjBeginAsyncJobWithDriver(struct qemud_driver *driver,
int qemuDomainObjEndJob(struct qemud_driver *driver, virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
enum qemuDomainJob job = priv->job.active;
priv->jobs_queued--;
VIR_DEBUG("Stopping job: %s (async=%s)",
qemuDomainJobTypeToString(priv->job.active),
qemuDomainJobTypeToString(job),
qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
qemuDomainObjResetJob(priv);
qemuDomainObjSaveJob(driver, obj);
if (qemuDomainTrackJob(job))
qemuDomainObjSaveJob(driver, obj);
virCondSignal(&priv->job.cond);
return virDomainObjUnref(obj);

View File

@ -53,6 +53,11 @@
JOB_MASK(QEMU_JOB_DESTROY) | \
JOB_MASK(QEMU_JOB_ABORT))
/* Jobs which have to be tracked in domain state XML. */
# define QEMU_DOMAIN_TRACK_JOBS \
(JOB_MASK(QEMU_JOB_DESTROY) | \
JOB_MASK(QEMU_JOB_ASYNC))
/* Only 1 job is allowed at any time
* A job includes *all* monitor commands, even those just querying
* information, not merely actions */

View File

@ -2963,6 +2963,10 @@ qemuProcessRecoverJob(struct qemud_driver *driver,
if (!virDomainObjIsActive(vm))
return -1;
/* In case any special handling is added for job type that has been ignored
* before, QEMU_DOMAIN_TRACK_JOBS (from qemu_domain.h) needs to be updated
* for the job to be properly tracked in domain state XML.
*/
switch (job->active) {
case QEMU_JOB_QUERY:
/* harmless */