mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
qemu: Wait for migration events on domain condition
Since we already support the MIGRATION event, we just need to make sure the domain condition is signalled whenever a p2p connection drops or the domain is paused due to IO error and we can avoid waking up every 50 ms to check whether something happened. Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
parent
6d2edb6a42
commit
3409f5bc4e
@ -199,6 +199,9 @@ struct _qemuDomainObjPrivate {
|
|||||||
/* Bitmaps below hold data from the auto NUMA feature */
|
/* Bitmaps below hold data from the auto NUMA feature */
|
||||||
virBitmapPtr autoNodeset;
|
virBitmapPtr autoNodeset;
|
||||||
virBitmapPtr autoCpuset;
|
virBitmapPtr autoCpuset;
|
||||||
|
|
||||||
|
bool signalIOError; /* true if the domain condition should be signalled on
|
||||||
|
I/O error */
|
||||||
};
|
};
|
||||||
|
|
||||||
# define QEMU_DOMAIN_DISK_PRIVATE(disk) \
|
# define QEMU_DOMAIN_DISK_PRIVATE(disk) \
|
||||||
|
@ -2661,20 +2661,28 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver,
|
|||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
qemuDomainJobInfoPtr jobInfo = priv->job.current;
|
qemuDomainJobInfoPtr jobInfo = priv->job.current;
|
||||||
|
bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
jobInfo->type = VIR_DOMAIN_JOB_UNBOUNDED;
|
jobInfo->type = VIR_DOMAIN_JOB_UNBOUNDED;
|
||||||
while ((rv = qemuMigrationCompleted(driver, vm, asyncJob, dconn,
|
while ((rv = qemuMigrationCompleted(driver, vm, asyncJob, dconn,
|
||||||
abort_on_error, storage)) != 1) {
|
abort_on_error, storage)) != 1) {
|
||||||
/* Poll every 50ms for progress & to allow cancellation */
|
|
||||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
|
|
||||||
|
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
virObjectUnlock(vm);
|
if (events) {
|
||||||
nanosleep(&ts, NULL);
|
if (virDomainObjWait(vm) < 0) {
|
||||||
virObjectLock(vm);
|
jobInfo->type = VIR_DOMAIN_JOB_FAILED;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Poll every 50ms for progress & to allow cancellation */
|
||||||
|
struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
|
||||||
|
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
|
virObjectLock(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qemuDomainJobInfoUpdateDowntime(jobInfo);
|
qemuDomainJobInfoUpdateDowntime(jobInfo);
|
||||||
@ -4148,6 +4156,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
|
|||||||
virErrorPtr orig_err = NULL;
|
virErrorPtr orig_err = NULL;
|
||||||
unsigned int cookieFlags = 0;
|
unsigned int cookieFlags = 0;
|
||||||
bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
|
bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
|
||||||
|
bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
|
VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
|
||||||
@ -4178,6 +4187,9 @@ qemuMigrationRun(virQEMUDriverPtr driver,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (events)
|
||||||
|
priv->signalIOError = abort_on_error;
|
||||||
|
|
||||||
mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
|
mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
|
||||||
cookieFlags | QEMU_MIGRATION_COOKIE_GRAPHICS);
|
cookieFlags | QEMU_MIGRATION_COOKIE_GRAPHICS);
|
||||||
if (!mig)
|
if (!mig)
|
||||||
@ -4387,6 +4399,9 @@ qemuMigrationRun(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
qemuMigrationCookieFree(mig);
|
qemuMigrationCookieFree(mig);
|
||||||
|
|
||||||
|
if (events)
|
||||||
|
priv->signalIOError = false;
|
||||||
|
|
||||||
if (orig_err) {
|
if (orig_err) {
|
||||||
virSetError(orig_err);
|
virSetError(orig_err);
|
||||||
virFreeError(orig_err);
|
virFreeError(orig_err);
|
||||||
@ -5029,6 +5044,18 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
qemuMigrationConnectionClosed(virConnectPtr conn,
|
||||||
|
int reason,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
virDomainObjPtr vm = opaque;
|
||||||
|
|
||||||
|
VIR_DEBUG("conn=%p, reason=%d, vm=%s", conn, reason, vm->def->name);
|
||||||
|
virDomainObjBroadcast(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int virConnectCredType[] = {
|
static int virConnectCredType[] = {
|
||||||
VIR_CRED_AUTHNAME,
|
VIR_CRED_AUTHNAME,
|
||||||
VIR_CRED_PASSPHRASE,
|
VIR_CRED_PASSPHRASE,
|
||||||
@ -5104,6 +5131,11 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
|
|||||||
cfg->keepAliveCount) < 0)
|
cfg->keepAliveCount) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virConnectRegisterCloseCallback(dconn, qemuMigrationConnectionClosed,
|
||||||
|
vm, NULL) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
qemuDomainObjEnterRemote(vm);
|
qemuDomainObjEnterRemote(vm);
|
||||||
p2p = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
|
p2p = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
|
||||||
VIR_DRV_FEATURE_MIGRATION_P2P);
|
VIR_DRV_FEATURE_MIGRATION_P2P);
|
||||||
@ -5169,6 +5201,7 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
|
|||||||
cleanup:
|
cleanup:
|
||||||
orig_err = virSaveLastError();
|
orig_err = virSaveLastError();
|
||||||
qemuDomainObjEnterRemote(vm);
|
qemuDomainObjEnterRemote(vm);
|
||||||
|
virConnectUnregisterCloseCallback(dconn, qemuMigrationConnectionClosed);
|
||||||
virObjectUnref(dconn);
|
virObjectUnref(dconn);
|
||||||
qemuDomainObjExitRemote(vm);
|
qemuDomainObjExitRemote(vm);
|
||||||
if (orig_err) {
|
if (orig_err) {
|
||||||
|
@ -952,6 +952,9 @@ qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
VIR_DEBUG("Transitioned guest %s to paused state due to IO error", vm->def->name);
|
VIR_DEBUG("Transitioned guest %s to paused state due to IO error", vm->def->name);
|
||||||
|
|
||||||
|
if (priv->signalIOError)
|
||||||
|
virDomainObjBroadcast(vm);
|
||||||
|
|
||||||
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_IOERROR);
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_IOERROR);
|
||||||
lifecycleEvent = virDomainEventLifecycleNewFromObj(vm,
|
lifecycleEvent = virDomainEventLifecycleNewFromObj(vm,
|
||||||
VIR_DOMAIN_EVENT_SUSPENDED,
|
VIR_DOMAIN_EVENT_SUSPENDED,
|
||||||
|
Loading…
Reference in New Issue
Block a user