qemu: Separate job related data into a new object

This commit is contained in:
Jiri Denemark 2011-06-06 10:34:33 +02:00
parent 0583825f3c
commit 90a422f071
5 changed files with 192 additions and 147 deletions

View File

@ -79,6 +79,42 @@ void qemuDomainEventQueue(struct qemud_driver *driver,
} }
static int
qemuDomainObjInitJob(qemuDomainObjPrivatePtr priv)
{
memset(&priv->job, 0, sizeof(priv->job));
if (virCondInit(&priv->job.cond) < 0)
return -1;
if (virCondInit(&priv->job.signalCond) < 0) {
ignore_value(virCondDestroy(&priv->job.cond));
return -1;
}
return 0;
}
static void
qemuDomainObjResetJob(qemuDomainObjPrivatePtr priv)
{
struct qemuDomainJobObj *job = &priv->job;
job->active = QEMU_JOB_NONE;
job->start = 0;
memset(&job->info, 0, sizeof(job->info));
job->signals = 0;
memset(&job->signalsData, 0, sizeof(job->signalsData));
}
static void
qemuDomainObjFreeJob(qemuDomainObjPrivatePtr priv)
{
ignore_value(virCondDestroy(&priv->job.cond));
ignore_value(virCondDestroy(&priv->job.signalCond));
}
static void *qemuDomainObjPrivateAlloc(void) static void *qemuDomainObjPrivateAlloc(void)
{ {
qemuDomainObjPrivatePtr priv; qemuDomainObjPrivatePtr priv;
@ -86,19 +122,10 @@ static void *qemuDomainObjPrivateAlloc(void)
if (VIR_ALLOC(priv) < 0) if (VIR_ALLOC(priv) < 0)
return NULL; return NULL;
if (virCondInit(&priv->jobCond) < 0) if (qemuDomainObjInitJob(priv) < 0)
goto initfail; VIR_FREE(priv);
if (virCondInit(&priv->signalCond) < 0) {
ignore_value(virCondDestroy(&priv->jobCond));
goto initfail;
}
return priv; return priv;
initfail:
VIR_FREE(priv);
return NULL;
} }
static void qemuDomainObjPrivateFree(void *data) static void qemuDomainObjPrivateFree(void *data)
@ -109,9 +136,8 @@ static void qemuDomainObjPrivateFree(void *data)
qemuDomainPCIAddressSetFree(priv->pciaddrs); qemuDomainPCIAddressSetFree(priv->pciaddrs);
virDomainChrSourceDefFree(priv->monConfig); virDomainChrSourceDefFree(priv->monConfig);
qemuDomainObjFreeJob(priv);
VIR_FREE(priv->vcpupids); VIR_FREE(priv->vcpupids);
ignore_value(virCondDestroy(&priv->jobCond));
ignore_value(virCondDestroy(&priv->signalCond));
VIR_FREE(priv->lockState); VIR_FREE(priv->lockState);
/* This should never be non-NULL if we get here, but just in case... */ /* This should never be non-NULL if we get here, but just in case... */
@ -473,6 +499,24 @@ void qemuDomainSetNamespaceHooks(virCapsPtr caps)
caps->ns.href = qemuDomainDefNamespaceHref; caps->ns.href = qemuDomainDefNamespaceHref;
} }
void
qemuDomainObjSetJob(virDomainObjPtr obj,
enum qemuDomainJob job)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
priv->job.active = job;
}
void
qemuDomainObjDiscardJob(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
qemuDomainObjResetJob(priv);
qemuDomainObjSetJob(obj, QEMU_JOB_NONE);
}
/* /*
* obj must be locked before calling, qemud_driver must NOT be locked * obj must be locked before calling, qemud_driver must NOT be locked
* *
@ -498,8 +542,8 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj)
virDomainObjRef(obj); virDomainObjRef(obj);
while (priv->jobActive) { while (priv->job.active) {
if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { if (virCondWaitUntil(&priv->job.cond, &obj->lock, then) < 0) {
/* Safe to ignore value since ref count was incremented above */ /* Safe to ignore value since ref count was incremented above */
ignore_value(virDomainObjUnref(obj)); ignore_value(virDomainObjUnref(obj));
if (errno == ETIMEDOUT) if (errno == ETIMEDOUT)
@ -511,11 +555,9 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj)
return -1; return -1;
} }
} }
priv->jobActive = QEMU_JOB_UNSPECIFIED; qemuDomainObjResetJob(priv);
priv->jobSignals = 0; qemuDomainObjSetJob(obj, QEMU_JOB_UNSPECIFIED);
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData)); priv->job.start = now;
priv->jobStart = now;
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
return 0; return 0;
} }
@ -540,8 +582,8 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
virDomainObjRef(obj); virDomainObjRef(obj);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
while (priv->jobActive) { while (priv->job.active) {
if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { if (virCondWaitUntil(&priv->job.cond, &obj->lock, then) < 0) {
if (errno == ETIMEDOUT) if (errno == ETIMEDOUT)
qemuReportError(VIR_ERR_OPERATION_TIMEOUT, qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
"%s", _("cannot acquire state change lock")); "%s", _("cannot acquire state change lock"));
@ -556,11 +598,9 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
return -1; return -1;
} }
} }
priv->jobActive = QEMU_JOB_UNSPECIFIED; qemuDomainObjResetJob(priv);
priv->jobSignals = 0; qemuDomainObjSetJob(obj, QEMU_JOB_UNSPECIFIED);
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData)); priv->job.start = now;
priv->jobStart = now;
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
virDomainObjUnlock(obj); virDomainObjUnlock(obj);
qemuDriverLock(driver); qemuDriverLock(driver);
@ -582,17 +622,13 @@ int qemuDomainObjEndJob(virDomainObjPtr obj)
{ {
qemuDomainObjPrivatePtr priv = obj->privateData; qemuDomainObjPrivatePtr priv = obj->privateData;
priv->jobActive = QEMU_JOB_NONE; qemuDomainObjResetJob(priv);
priv->jobSignals = 0; qemuDomainObjSetJob(obj, QEMU_JOB_NONE);
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData)); virCondSignal(&priv->job.cond);
priv->jobStart = 0;
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
virCondSignal(&priv->jobCond);
return virDomainObjUnref(obj); return virDomainObjUnref(obj);
} }
/* /*
* obj must be locked before calling, qemud_driver must be unlocked * obj must be locked before calling, qemud_driver must be unlocked
* *

View File

@ -68,19 +68,26 @@ struct qemuDomainJobSignalsData {
int *infoRetCode; /* Return code for the blkinfo calls */ int *infoRetCode; /* Return code for the blkinfo calls */
}; };
struct qemuDomainJobObj {
virCond cond; /* Use in conjunction with main virDomainObjPtr lock */
virCond signalCond; /* Use to coordinate the safe queries during migration */
enum qemuDomainJob active; /* Currently running job */
unsigned long long start; /* When the job started */
virDomainJobInfo info; /* Progress data */
unsigned int signals; /* Signals for running job */
struct qemuDomainJobSignalsData signalsData; /* Signal specific data */
};
typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet; typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet;
typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr; typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr;
typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate; typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr; typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
struct _qemuDomainObjPrivate { struct _qemuDomainObjPrivate {
virCond jobCond; /* Use in conjunction with main virDomainObjPtr lock */ struct qemuDomainJobObj job;
virCond signalCond; /* Use to coordinate the safe queries during migration */
enum qemuDomainJob jobActive; /* Currently running job */
unsigned int jobSignals; /* Signals for running job */
struct qemuDomainJobSignalsData jobSignalsData; /* Signal specific data */
virDomainJobInfo jobInfo;
unsigned long long jobStart;
qemuMonitorPtr mon; qemuMonitorPtr mon;
virDomainChrSourceDefPtr monConfig; virDomainChrSourceDefPtr monConfig;
@ -121,6 +128,10 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
int qemuDomainObjEndJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; int qemuDomainObjEndJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
void qemuDomainObjSetJob(virDomainObjPtr obj, enum qemuDomainJob job);
void qemuDomainObjDiscardJob(virDomainObjPtr obj);
void qemuDomainObjEnterMonitor(virDomainObjPtr obj); void qemuDomainObjEnterMonitor(virDomainObjPtr obj);
void qemuDomainObjExitMonitor(virDomainObjPtr obj); void qemuDomainObjExitMonitor(virDomainObjPtr obj);
void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver,

View File

@ -1348,11 +1348,11 @@ static int qemudDomainSuspend(virDomainPtr dom) {
priv = vm->privateData; priv = vm->privateData;
if (priv->jobActive == QEMU_JOB_MIGRATION_OUT) { if (priv->job.active == QEMU_JOB_MIGRATION_OUT) {
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) { if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
VIR_DEBUG("Requesting domain pause on %s", VIR_DEBUG("Requesting domain pause on %s",
vm->def->name); vm->def->name);
priv->jobSignals |= QEMU_JOB_SIGNAL_SUSPEND; priv->job.signals |= QEMU_JOB_SIGNAL_SUSPEND;
} }
ret = 0; ret = 0;
goto cleanup; goto cleanup;
@ -1883,7 +1883,7 @@ static int qemudDomainGetInfo(virDomainPtr dom,
if ((vm->def->memballoon != NULL) && if ((vm->def->memballoon != NULL) &&
(vm->def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_NONE)) { (vm->def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_NONE)) {
info->memory = vm->def->mem.max_balloon; info->memory = vm->def->mem.max_balloon;
} else if (!priv->jobActive) { } else if (!priv->job.active) {
if (qemuDomainObjBeginJob(vm) < 0) if (qemuDomainObjBeginJob(vm) < 0)
goto cleanup; goto cleanup;
if (!virDomainObjIsActive(vm)) if (!virDomainObjIsActive(vm))
@ -1990,12 +1990,12 @@ qemuDomainGetControlInfo(virDomainPtr dom,
if (priv->monError) { if (priv->monError) {
info->state = VIR_DOMAIN_CONTROL_ERROR; info->state = VIR_DOMAIN_CONTROL_ERROR;
} else if (priv->jobActive) { } else if (priv->job.active) {
if (!priv->monStart) { if (!priv->monStart) {
info->state = VIR_DOMAIN_CONTROL_JOB; info->state = VIR_DOMAIN_CONTROL_JOB;
if (virTimeMs(&info->stateTime) < 0) if (virTimeMs(&info->stateTime) < 0)
goto cleanup; goto cleanup;
info->stateTime -= priv->jobStart; info->stateTime -= priv->job.start;
} else { } else {
info->state = VIR_DOMAIN_CONTROL_OCCUPIED; info->state = VIR_DOMAIN_CONTROL_OCCUPIED;
if (virTimeMs(&info->stateTime) < 0) if (virTimeMs(&info->stateTime) < 0)
@ -2130,10 +2130,10 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup; goto cleanup;
priv->jobActive = QEMU_JOB_SAVE; qemuDomainObjSetJob(vm, QEMU_JOB_SAVE);
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); memset(&priv->job.info, 0, sizeof(priv->job.info));
priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
/* Pause */ /* Pause */
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
@ -2623,7 +2623,7 @@ static int qemudDomainCoreDump(virDomainPtr dom,
goto endjob; goto endjob;
} }
priv->jobActive = QEMU_JOB_DUMP; qemuDomainObjSetJob(vm, QEMU_JOB_DUMP);
/* Migrate will always stop the VM, so the resume condition is /* Migrate will always stop the VM, so the resume condition is
independent of whether the stop command is issued. */ independent of whether the stop command is issued. */
@ -3855,7 +3855,7 @@ static char *qemuDomainGetXMLDesc(virDomainPtr dom,
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
/* Don't delay if someone's using the monitor, just use /* Don't delay if someone's using the monitor, just use
* existing most recent data instead */ * existing most recent data instead */
if (!priv->jobActive) { if (!priv->job.active) {
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup; goto cleanup;
@ -6023,19 +6023,19 @@ qemudDomainBlockStats (virDomainPtr dom,
} }
priv = vm->privateData; priv = vm->privateData;
if ((priv->jobActive == QEMU_JOB_MIGRATION_OUT) if ((priv->job.active == QEMU_JOB_MIGRATION_OUT)
|| (priv->jobActive == QEMU_JOB_SAVE)) { || (priv->job.active == QEMU_JOB_SAVE)) {
virDomainObjRef(vm); virDomainObjRef(vm);
while (priv->jobSignals & QEMU_JOB_SIGNAL_BLKSTAT) while (priv->job.signals & QEMU_JOB_SIGNAL_BLKSTAT)
ignore_value(virCondWait(&priv->signalCond, &vm->lock)); ignore_value(virCondWait(&priv->job.signalCond, &vm->lock));
priv->jobSignalsData.statDevName = disk->info.alias; priv->job.signalsData.statDevName = disk->info.alias;
priv->jobSignalsData.blockStat = stats; priv->job.signalsData.blockStat = stats;
priv->jobSignalsData.statRetCode = &ret; priv->job.signalsData.statRetCode = &ret;
priv->jobSignals |= QEMU_JOB_SIGNAL_BLKSTAT; priv->job.signals |= QEMU_JOB_SIGNAL_BLKSTAT;
while (priv->jobSignals & QEMU_JOB_SIGNAL_BLKSTAT) while (priv->job.signals & QEMU_JOB_SIGNAL_BLKSTAT)
ignore_value(virCondWait(&priv->signalCond, &vm->lock)); ignore_value(virCondWait(&priv->job.signalCond, &vm->lock));
if (virDomainObjUnref(vm) == 0) if (virDomainObjUnref(vm) == 0)
vm = NULL; vm = NULL;
@ -6470,19 +6470,19 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
virDomainObjIsActive(vm)) { virDomainObjIsActive(vm)) {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
if ((priv->jobActive == QEMU_JOB_MIGRATION_OUT) if ((priv->job.active == QEMU_JOB_MIGRATION_OUT)
|| (priv->jobActive == QEMU_JOB_SAVE)) { || (priv->job.active == QEMU_JOB_SAVE)) {
virDomainObjRef(vm); virDomainObjRef(vm);
while (priv->jobSignals & QEMU_JOB_SIGNAL_BLKINFO) while (priv->job.signals & QEMU_JOB_SIGNAL_BLKINFO)
ignore_value(virCondWait(&priv->signalCond, &vm->lock)); ignore_value(virCondWait(&priv->job.signalCond, &vm->lock));
priv->jobSignalsData.infoDevName = disk->info.alias; priv->job.signalsData.infoDevName = disk->info.alias;
priv->jobSignalsData.blockInfo = info; priv->job.signalsData.blockInfo = info;
priv->jobSignalsData.infoRetCode = &ret; priv->job.signalsData.infoRetCode = &ret;
priv->jobSignals |= QEMU_JOB_SIGNAL_BLKINFO; priv->job.signals |= QEMU_JOB_SIGNAL_BLKINFO;
while (priv->jobSignals & QEMU_JOB_SIGNAL_BLKINFO) while (priv->job.signals & QEMU_JOB_SIGNAL_BLKINFO)
ignore_value(virCondWait(&priv->signalCond, &vm->lock)); ignore_value(virCondWait(&priv->job.signalCond, &vm->lock));
if (virDomainObjUnref(vm) == 0) if (virDomainObjUnref(vm) == 0)
vm = NULL; vm = NULL;
@ -7310,8 +7310,8 @@ static int qemuDomainGetJobInfo(virDomainPtr dom,
priv = vm->privateData; priv = vm->privateData;
if (virDomainObjIsActive(vm)) { if (virDomainObjIsActive(vm)) {
if (priv->jobActive) { if (priv->job.active) {
memcpy(info, &priv->jobInfo, sizeof(*info)); memcpy(info, &priv->job.info, sizeof(*info));
/* Refresh elapsed time again just to ensure it /* Refresh elapsed time again just to ensure it
* is fully updated. This is primarily for benefit * is fully updated. This is primarily for benefit
@ -7320,7 +7320,7 @@ static int qemuDomainGetJobInfo(virDomainPtr dom,
*/ */
if (virTimeMs(&info->timeElapsed) < 0) if (virTimeMs(&info->timeElapsed) < 0)
goto cleanup; goto cleanup;
info->timeElapsed -= priv->jobStart; info->timeElapsed -= priv->job.start;
} else { } else {
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
info->type = VIR_DOMAIN_JOB_NONE; info->type = VIR_DOMAIN_JOB_NONE;
@ -7360,9 +7360,9 @@ static int qemuDomainAbortJob(virDomainPtr dom) {
priv = vm->privateData; priv = vm->privateData;
if (virDomainObjIsActive(vm)) { if (virDomainObjIsActive(vm)) {
if (priv->jobActive) { if (priv->job.active) {
VIR_DEBUG("Requesting cancellation of job on vm %s", vm->def->name); VIR_DEBUG("Requesting cancellation of job on vm %s", vm->def->name);
priv->jobSignals |= QEMU_JOB_SIGNAL_CANCEL; priv->job.signals |= QEMU_JOB_SIGNAL_CANCEL;
} else { } else {
qemuReportError(VIR_ERR_OPERATION_INVALID, qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("no job is active on the domain")); "%s", _("no job is active on the domain"));
@ -7414,15 +7414,15 @@ qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
priv = vm->privateData; priv = vm->privateData;
if (priv->jobActive != QEMU_JOB_MIGRATION_OUT) { if (priv->job.active != QEMU_JOB_MIGRATION_OUT) {
qemuReportError(VIR_ERR_OPERATION_INVALID, qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not being migrated")); "%s", _("domain is not being migrated"));
goto cleanup; goto cleanup;
} }
VIR_DEBUG("Requesting migration downtime change to %llums", downtime); VIR_DEBUG("Requesting migration downtime change to %llums", downtime);
priv->jobSignalsData.migrateDowntime = downtime; priv->job.signalsData.migrateDowntime = downtime;
priv->jobSignals |= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME; priv->job.signals |= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME;
ret = 0; ret = 0;
cleanup: cleanup:
@ -7463,15 +7463,15 @@ qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
priv = vm->privateData; priv = vm->privateData;
if (priv->jobActive != QEMU_JOB_MIGRATION_OUT) { if (priv->job.active != QEMU_JOB_MIGRATION_OUT) {
qemuReportError(VIR_ERR_OPERATION_INVALID, qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not being migrated")); "%s", _("domain is not being migrated"));
goto cleanup; goto cleanup;
} }
VIR_DEBUG("Requesting migration speed change to %luMbs", bandwidth); VIR_DEBUG("Requesting migration speed change to %luMbs", bandwidth);
priv->jobSignalsData.migrateBandwidth = bandwidth; priv->job.signalsData.migrateBandwidth = bandwidth;
priv->jobSignals |= QEMU_JOB_SIGNAL_MIGRATE_SPEED; priv->job.signals |= QEMU_JOB_SIGNAL_MIGRATE_SPEED;
ret = 0; ret = 0;
cleanup: cleanup:

View File

@ -742,12 +742,12 @@ qemuMigrationProcessJobSignals(struct qemud_driver *driver,
qemuReportError(VIR_ERR_INTERNAL_ERROR, _("%s: %s"), qemuReportError(VIR_ERR_INTERNAL_ERROR, _("%s: %s"),
job, _("guest unexpectedly quit")); job, _("guest unexpectedly quit"));
if (cleanup) if (cleanup)
priv->jobSignals = 0; priv->job.signals = 0;
return -1; return -1;
} }
if (priv->jobSignals & QEMU_JOB_SIGNAL_CANCEL) { if (priv->job.signals & QEMU_JOB_SIGNAL_CANCEL) {
priv->jobSignals ^= QEMU_JOB_SIGNAL_CANCEL; priv->job.signals ^= QEMU_JOB_SIGNAL_CANCEL;
VIR_DEBUG("Cancelling job at client request"); VIR_DEBUG("Cancelling job at client request");
qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorMigrateCancel(priv->mon); ret = qemuMonitorMigrateCancel(priv->mon);
@ -755,58 +755,58 @@ qemuMigrationProcessJobSignals(struct qemud_driver *driver,
if (ret < 0) { if (ret < 0) {
VIR_WARN("Unable to cancel job"); VIR_WARN("Unable to cancel job");
} }
} else if (priv->jobSignals & QEMU_JOB_SIGNAL_SUSPEND) { } else if (priv->job.signals & QEMU_JOB_SIGNAL_SUSPEND) {
priv->jobSignals ^= QEMU_JOB_SIGNAL_SUSPEND; priv->job.signals ^= QEMU_JOB_SIGNAL_SUSPEND;
VIR_DEBUG("Pausing domain for non-live migration"); VIR_DEBUG("Pausing domain for non-live migration");
if (qemuMigrationSetOffline(driver, vm) < 0) if (qemuMigrationSetOffline(driver, vm) < 0)
VIR_WARN("Unable to pause domain"); VIR_WARN("Unable to pause domain");
} else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME) { } else if (priv->job.signals & QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME) {
unsigned long long ms = priv->jobSignalsData.migrateDowntime; unsigned long long ms = priv->job.signalsData.migrateDowntime;
priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME; priv->job.signals ^= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME;
priv->jobSignalsData.migrateDowntime = 0; priv->job.signalsData.migrateDowntime = 0;
VIR_DEBUG("Setting migration downtime to %llums", ms); VIR_DEBUG("Setting migration downtime to %llums", ms);
qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorSetMigrationDowntime(priv->mon, ms); ret = qemuMonitorSetMigrationDowntime(priv->mon, ms);
qemuDomainObjExitMonitorWithDriver(driver, vm); qemuDomainObjExitMonitorWithDriver(driver, vm);
if (ret < 0) if (ret < 0)
VIR_WARN("Unable to set migration downtime"); VIR_WARN("Unable to set migration downtime");
} else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) { } else if (priv->job.signals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) {
unsigned long bandwidth = priv->jobSignalsData.migrateBandwidth; unsigned long bandwidth = priv->job.signalsData.migrateBandwidth;
priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_SPEED; priv->job.signals ^= QEMU_JOB_SIGNAL_MIGRATE_SPEED;
priv->jobSignalsData.migrateBandwidth = 0; priv->job.signalsData.migrateBandwidth = 0;
VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth); VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth);
qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth); ret = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth);
qemuDomainObjExitMonitorWithDriver(driver, vm); qemuDomainObjExitMonitorWithDriver(driver, vm);
if (ret < 0) if (ret < 0)
VIR_WARN("Unable to set migration speed"); VIR_WARN("Unable to set migration speed");
} else if (priv->jobSignals & QEMU_JOB_SIGNAL_BLKSTAT) { } else if (priv->job.signals & QEMU_JOB_SIGNAL_BLKSTAT) {
qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorGetBlockStatsInfo(priv->mon, ret = qemuMonitorGetBlockStatsInfo(priv->mon,
priv->jobSignalsData.statDevName, priv->job.signalsData.statDevName,
&priv->jobSignalsData.blockStat->rd_req, &priv->job.signalsData.blockStat->rd_req,
&priv->jobSignalsData.blockStat->rd_bytes, &priv->job.signalsData.blockStat->rd_bytes,
&priv->jobSignalsData.blockStat->wr_req, &priv->job.signalsData.blockStat->wr_req,
&priv->jobSignalsData.blockStat->wr_bytes, &priv->job.signalsData.blockStat->wr_bytes,
&priv->jobSignalsData.blockStat->errs); &priv->job.signalsData.blockStat->errs);
qemuDomainObjExitMonitorWithDriver(driver, vm); qemuDomainObjExitMonitorWithDriver(driver, vm);
*priv->jobSignalsData.statRetCode = ret; *priv->job.signalsData.statRetCode = ret;
priv->jobSignals ^= QEMU_JOB_SIGNAL_BLKSTAT; priv->job.signals ^= QEMU_JOB_SIGNAL_BLKSTAT;
if (ret < 0) if (ret < 0)
VIR_WARN("Unable to get block statistics"); VIR_WARN("Unable to get block statistics");
} else if (priv->jobSignals & QEMU_JOB_SIGNAL_BLKINFO) { } else if (priv->job.signals & QEMU_JOB_SIGNAL_BLKINFO) {
qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorGetBlockExtent(priv->mon, ret = qemuMonitorGetBlockExtent(priv->mon,
priv->jobSignalsData.infoDevName, priv->job.signalsData.infoDevName,
&priv->jobSignalsData.blockInfo->allocation); &priv->job.signalsData.blockInfo->allocation);
qemuDomainObjExitMonitorWithDriver(driver, vm); qemuDomainObjExitMonitorWithDriver(driver, vm);
*priv->jobSignalsData.infoRetCode = ret; *priv->job.signalsData.infoRetCode = ret;
priv->jobSignals ^= QEMU_JOB_SIGNAL_BLKINFO; priv->job.signals ^= QEMU_JOB_SIGNAL_BLKINFO;
if (ret < 0) if (ret < 0)
VIR_WARN("Unable to get block information"); VIR_WARN("Unable to get block information");
@ -844,44 +844,44 @@ qemuMigrationUpdateJobStatus(struct qemud_driver *driver,
&memTotal); &memTotal);
qemuDomainObjExitMonitorWithDriver(driver, vm); qemuDomainObjExitMonitorWithDriver(driver, vm);
if (ret < 0 || virTimeMs(&priv->jobInfo.timeElapsed) < 0) { if (ret < 0 || virTimeMs(&priv->job.info.timeElapsed) < 0) {
priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
return -1; return -1;
} }
priv->jobInfo.timeElapsed -= priv->jobStart; priv->job.info.timeElapsed -= priv->job.start;
switch (status) { switch (status) {
case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
priv->jobInfo.type = VIR_DOMAIN_JOB_NONE; priv->job.info.type = VIR_DOMAIN_JOB_NONE;
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
_("%s: %s"), job, _("is not active")); _("%s: %s"), job, _("is not active"));
break; break;
case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE: case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
priv->jobInfo.dataTotal = memTotal; priv->job.info.dataTotal = memTotal;
priv->jobInfo.dataRemaining = memRemaining; priv->job.info.dataRemaining = memRemaining;
priv->jobInfo.dataProcessed = memProcessed; priv->job.info.dataProcessed = memProcessed;
priv->jobInfo.memTotal = memTotal; priv->job.info.memTotal = memTotal;
priv->jobInfo.memRemaining = memRemaining; priv->job.info.memRemaining = memRemaining;
priv->jobInfo.memProcessed = memProcessed; priv->job.info.memProcessed = memProcessed;
ret = 0; ret = 0;
break; break;
case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED: case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
priv->jobInfo.type = VIR_DOMAIN_JOB_COMPLETED; priv->job.info.type = VIR_DOMAIN_JOB_COMPLETED;
ret = 0; ret = 0;
break; break;
case QEMU_MONITOR_MIGRATION_STATUS_ERROR: case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
_("%s: %s"), job, _("unexpectedly failed")); _("%s: %s"), job, _("unexpectedly failed"));
break; break;
case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED: case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED:
priv->jobInfo.type = VIR_DOMAIN_JOB_CANCELLED; priv->job.info.type = VIR_DOMAIN_JOB_CANCELLED;
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
_("%s: %s"), job, _("canceled by client")); _("%s: %s"), job, _("canceled by client"));
break; break;
@ -897,7 +897,7 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm)
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
const char *job; const char *job;
switch (priv->jobActive) { switch (priv->job.active) {
case QEMU_JOB_MIGRATION_OUT: case QEMU_JOB_MIGRATION_OUT:
job = _("migration job"); job = _("migration job");
break; break;
@ -911,17 +911,17 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm)
job = _("job"); job = _("job");
} }
priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
while (priv->jobInfo.type == VIR_DOMAIN_JOB_UNBOUNDED) { while (priv->job.info.type == VIR_DOMAIN_JOB_UNBOUNDED) {
/* Poll every 50ms for progress & to allow cancellation */ /* Poll every 50ms for progress & to allow cancellation */
struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull }; struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
while (priv->jobSignals) { while (priv->job.signals) {
if (qemuMigrationProcessJobSignals(driver, vm, job, false) < 0) if (qemuMigrationProcessJobSignals(driver, vm, job, false) < 0)
goto cleanup; goto cleanup;
} }
virCondSignal(&priv->signalCond); virCondSignal(&priv->job.signalCond);
if (qemuMigrationUpdateJobStatus(driver, vm, job) < 0) if (qemuMigrationUpdateJobStatus(driver, vm, job) < 0)
goto cleanup; goto cleanup;
@ -937,12 +937,12 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm)
} }
cleanup: cleanup:
while (priv->jobSignals) { while (priv->job.signals) {
qemuMigrationProcessJobSignals(driver, vm, job, true); qemuMigrationProcessJobSignals(driver, vm, job, true);
} }
virCondBroadcast(&priv->signalCond); virCondBroadcast(&priv->job.signalCond);
if (priv->jobInfo.type == VIR_DOMAIN_JOB_COMPLETED) if (priv->job.info.type == VIR_DOMAIN_JOB_COMPLETED)
return 0; return 0;
else else
return -1; return -1;
@ -1112,7 +1112,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver,
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup; goto cleanup;
priv->jobActive = QEMU_JOB_MIGRATION_IN; qemuDomainObjSetJob(vm, QEMU_JOB_MIGRATION_IN);
/* Domain starts inactive, even if the domain XML had an id field. */ /* Domain starts inactive, even if the domain XML had an id field. */
vm->def->id = -1; vm->def->id = -1;
@ -1185,9 +1185,9 @@ endjob:
*/ */
if (vm && if (vm &&
virDomainObjIsActive(vm)) { virDomainObjIsActive(vm)) {
priv->jobActive = QEMU_JOB_MIGRATION_IN; qemuDomainObjSetJob(vm, QEMU_JOB_MIGRATION_IN);
priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
priv->jobStart = now; priv->job.start = now;
} }
cleanup: cleanup:
@ -1348,7 +1348,7 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver,
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup; goto cleanup;
priv->jobActive = QEMU_JOB_MIGRATION_IN; qemuDomainObjSetJob(vm, QEMU_JOB_MIGRATION_IN);
/* Domain starts inactive, even if the domain XML had an id field. */ /* Domain starts inactive, even if the domain XML had an id field. */
vm->def->id = -1; vm->def->id = -1;
@ -1407,9 +1407,9 @@ endjob:
*/ */
if (vm && if (vm &&
virDomainObjIsActive(vm)) { virDomainObjIsActive(vm)) {
priv->jobActive = QEMU_JOB_MIGRATION_IN; qemuDomainObjSetJob(vm, QEMU_JOB_MIGRATION_IN);
priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
priv->jobStart = now; priv->job.start = now;
} }
cleanup: cleanup:
@ -2289,7 +2289,7 @@ int qemuMigrationPerform(struct qemud_driver *driver,
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup; goto cleanup;
priv->jobActive = QEMU_JOB_MIGRATION_OUT; qemuDomainObjSetJob(vm, QEMU_JOB_MIGRATION_OUT);
if (!virDomainObjIsActive(vm)) { if (!virDomainObjIsActive(vm)) {
qemuReportError(VIR_ERR_OPERATION_INVALID, qemuReportError(VIR_ERR_OPERATION_INVALID,
@ -2303,8 +2303,8 @@ int qemuMigrationPerform(struct qemud_driver *driver,
goto endjob; goto endjob;
} }
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); memset(&priv->job.info, 0, sizeof(priv->job.info));
priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING; resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
@ -2453,13 +2453,12 @@ qemuMigrationFinish(struct qemud_driver *driver,
virErrorPtr orig_err = NULL; virErrorPtr orig_err = NULL;
priv = vm->privateData; priv = vm->privateData;
if (priv->jobActive != QEMU_JOB_MIGRATION_IN) { if (priv->job.active != QEMU_JOB_MIGRATION_IN) {
qemuReportError(VIR_ERR_NO_DOMAIN, qemuReportError(VIR_ERR_NO_DOMAIN,
_("domain '%s' is not processing incoming migration"), vm->def->name); _("domain '%s' is not processing incoming migration"), vm->def->name);
goto cleanup; goto cleanup;
} }
priv->jobActive = QEMU_JOB_NONE; qemuDomainObjDiscardJob(vm);
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, 0))) if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, 0)))
goto cleanup; goto cleanup;

View File

@ -3205,11 +3205,10 @@ static void qemuProcessAutoDestroyDom(void *payload,
} }
priv = dom->privateData; priv = dom->privateData;
if (priv->jobActive == QEMU_JOB_MIGRATION_IN) { if (priv->job.active == QEMU_JOB_MIGRATION_IN) {
VIR_DEBUG("vm=%s has incoming migration active, cancelling", VIR_DEBUG("vm=%s has incoming migration active, cancelling",
dom->def->name); dom->def->name);
priv->jobActive = QEMU_JOB_NONE; qemuDomainObjDiscardJob(dom);
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
} }
if (qemuDomainObjBeginJobWithDriver(data->driver, dom) < 0) if (qemuDomainObjBeginJobWithDriver(data->driver, dom) < 0)