qemu: track quiesced status in qemuDomainSnapshotFSFreeze

Adds 'quiesced' status into qemuDomainObjPrivate that tracks whether
FSFreeze is requested in the domain.

It modifies error code from qemuDomainSnapshotFSFreeze and
qemuDomainSnapshotFSThaw, so that a caller can know whether the command is
actually sent to the guest agent. If the error is caused before sending a
freeze command, a counterpart thaw command shouldn't be sent either, not to
confuse fsfreeze status tracking.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Tomoki Sekiyama 2014-05-01 20:06:01 -04:00 committed by Eric Blake
parent ca3d07fd45
commit b6d4dad11b
3 changed files with 64 additions and 13 deletions

View File

@ -357,6 +357,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
virBufferAddLit(buf, "</devices>\n"); virBufferAddLit(buf, "</devices>\n");
} }
if (priv->quiesced)
virBufferAddLit(buf, "<quiesced/>\n");
return 0; return 0;
} }
@ -518,6 +521,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
} }
VIR_FREE(nodes); VIR_FREE(nodes);
priv->quiesced = virXPathBoolean("boolean(./quiesced)", ctxt) == 1;
return 0; return 0;
error: error:

View File

@ -176,6 +176,8 @@ struct _qemuDomainObjPrivate {
char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */ char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
bool hookRun; /* true if there was a hook run over this domain */ bool hookRun; /* true if there was a hook run over this domain */
bool quiesced; /* true if filesystems are quiesced */
}; };
typedef enum { typedef enum {

View File

@ -12060,32 +12060,62 @@ qemuDomainPrepareDiskChainElement(virQEMUDriverPtr driver,
} }
/* Return -1 if request is not sent to agent due to misconfig, -2 if request
* is sent but failed, and number of frozen filesystems on success. If -2 is
* returned, FSThaw should be called revert the quiesced status. */
static int static int
qemuDomainSnapshotFSFreeze(virDomainObjPtr vm) qemuDomainSnapshotFSFreeze(virQEMUDriverPtr driver,
virDomainObjPtr vm)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverConfigPtr cfg;
int freezed; int freezed;
if (priv->quiesced) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("domain is already quiesced"));
return -1;
}
if (!qemuDomainAgentAvailable(priv, true)) if (!qemuDomainAgentAvailable(priv, true))
return -1; return -1;
priv->quiesced = true;
cfg = virQEMUDriverGetConfig(driver);
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
priv->quiesced = false;
virObjectUnref(cfg);
return -1;
}
virObjectUnref(cfg);
qemuDomainObjEnterAgent(vm); qemuDomainObjEnterAgent(vm);
freezed = qemuAgentFSFreeze(priv->agent); freezed = qemuAgentFSFreeze(priv->agent);
qemuDomainObjExitAgent(vm); qemuDomainObjExitAgent(vm);
return freezed < 0 ? -2 : freezed;
return freezed;
} }
/* Return -1 on error, otherwise number of thawed filesystems. */
static int static int
qemuDomainSnapshotFSThaw(virDomainObjPtr vm, bool report) qemuDomainSnapshotFSThaw(virQEMUDriverPtr driver,
virDomainObjPtr vm,
bool report)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverConfigPtr cfg;
int thawed; int thawed;
virErrorPtr err = NULL; virErrorPtr err = NULL;
if (!qemuDomainAgentAvailable(priv, report)) if (!qemuDomainAgentAvailable(priv, report))
return -1; return -1;
if (!priv->quiesced && report) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("domain is not quiesced"));
return -1;
}
qemuDomainObjEnterAgent(vm); qemuDomainObjEnterAgent(vm);
if (!report) if (!report)
err = virSaveLastError(); err = virSaveLastError();
@ -12095,6 +12125,19 @@ qemuDomainSnapshotFSThaw(virDomainObjPtr vm, bool report)
qemuDomainObjExitAgent(vm); qemuDomainObjExitAgent(vm);
virFreeError(err); virFreeError(err);
if (!report || thawed >= 0) {
priv->quiesced = false;
cfg = virQEMUDriverGetConfig(driver);
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
/* Revert the statuses when we failed to save them. */
priv->quiesced = true;
thawed = -1;
}
virObjectUnref(cfg);
}
return thawed; return thawed;
} }
@ -13091,17 +13134,18 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
goto cleanup; goto cleanup;
/* If quiesce was requested, then issue a freeze command, and a /* If quiesce was requested, then issue a freeze command, and a
* counterpart thaw command, no matter what. The command will * counterpart thaw command when it is actually sent to agent.
* fail if the guest is paused or the guest agent is not * The command will fail if the guest is paused or the guest agent
* running. */ * is not running, or is already quiesced. */
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) { if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
if (qemuDomainSnapshotFSFreeze(vm) < 0) { int freeze = qemuDomainSnapshotFSFreeze(driver, vm);
/* helper reported the error */ if (freeze < 0) {
thaw = -1; /* the helper reported the error */
if (freeze == -2)
thaw = -1; /* the command is sent but agent failed */
goto endjob; goto endjob;
} else {
thaw = 1;
} }
thaw = 1;
} }
/* We need to track what state the guest is in, since taking the /* We need to track what state the guest is in, since taking the
@ -13242,7 +13286,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
goto cleanup; goto cleanup;
} }
if (vm && thaw != 0 && if (vm && thaw != 0 &&
qemuDomainSnapshotFSThaw(vm, thaw > 0) < 0) { qemuDomainSnapshotFSThaw(driver, vm, thaw > 0) < 0) {
/* helper reported the error, if it was needed */ /* helper reported the error, if it was needed */
if (thaw > 0) if (thaw > 0)
ret = -1; ret = -1;