With this patch, virDomainFSFreeze will pass the mountpoints argument
to qemu guest agent. For example,
virDomainFSFreeze(dom, {"/mnt/vol1", "/mnt/vol2"}, 2, 0)
will issue qemu guest agent command:
{"execute":"guest-fsfreeze-freeze",
"arguments":{"mountpoints":["/mnt/vol1","/mnt/vol2"]}}
Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama(a)hds.com>
Acked-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/qemu/qemu_agent.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
src/qemu/qemu_agent.h | 3 ++-
src/qemu/qemu_driver.c | 16 ++++++----------
tests/qemuagenttest.c | 8 +++++---
4 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 4082331..57c7cc5 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -1235,6 +1235,32 @@ qemuAgentMakeCommand(const char *cmdname,
return NULL;
}
+static virJSONValuePtr
+qemuAgentMakeStringsArray(const char **strings, unsigned int len)
+{
+ size_t i;
+ virJSONValuePtr ret = virJSONValueNewArray(), str;
+
+ if (!ret)
+ return NULL;
+
+ for (i = 0; i < len; i++) {
+ str = virJSONValueNewString(strings[i]);
+ if (!str)
+ goto error;
+
+ if (virJSONValueArrayAppend(ret, str) < 0) {
+ virJSONValueFree(str);
+ goto error;
+ }
+ }
+ return ret;
+
+ error:
+ virJSONValueFree(ret);
+ return NULL;
+}
+
void qemuAgentNotifyEvent(qemuAgentPtr mon,
qemuAgentEvent event)
{
@@ -1287,21 +1313,34 @@ int qemuAgentShutdown(qemuAgentPtr mon,
/*
* qemuAgentFSFreeze:
* @mon: Agent
+ * @mountpoints: Array of mountpoint paths to be frozen, or NULL for all
+ * @nmountpoints: Number of mountpoints to be frozen, or 0 for all
*
* Issue guest-fsfreeze-freeze command to guest agent,
- * which freezes all mounted file systems and returns
+ * which freezes file systems mounted on specified mountpoints
+ * (or all file systems when @mountpoints is NULL), and returns
* number of frozen file systems on success.
*
* Returns: number of file system frozen on success,
* -1 on error.
*/
-int qemuAgentFSFreeze(qemuAgentPtr mon)
+int qemuAgentFSFreeze(qemuAgentPtr mon, const char **mountpoints,
+ unsigned int nmountpoints)
{
int ret = -1;
- virJSONValuePtr cmd;
+ virJSONValuePtr cmd, arg;
virJSONValuePtr reply = NULL;
- cmd = qemuAgentMakeCommand("guest-fsfreeze-freeze", NULL);
+ if (mountpoints && nmountpoints) {
+ arg = qemuAgentMakeStringsArray(mountpoints, nmountpoints);
+ if (!arg)
+ return -1;
+
+ cmd = qemuAgentMakeCommand("guest-fsfreeze-freeze",
+ "a:mountpoints", arg, NULL);
+ } else {
+ cmd = qemuAgentMakeCommand("guest-fsfreeze-freeze", NULL);
+ }
if (!cmd)
return -1;
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index 5fbacdb..58531d5 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -70,7 +70,8 @@ typedef enum {
int qemuAgentShutdown(qemuAgentPtr mon,
qemuAgentShutdownMode mode);
-int qemuAgentFSFreeze(qemuAgentPtr mon);
+int qemuAgentFSFreeze(qemuAgentPtr mon,
+ const char **mountpoints, unsigned int nmountpoints);
int qemuAgentFSThaw(qemuAgentPtr mon);
int qemuAgentSuspend(qemuAgentPtr mon,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3a0334e..e523535 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12065,7 +12065,9 @@ qemuDomainPrepareDiskChainElement(virQEMUDriverPtr driver,
* returned, FSThaw should be called revert the quiesced status. */
static int
qemuDomainSnapshotFSFreeze(virQEMUDriverPtr driver,
- virDomainObjPtr vm)
+ virDomainObjPtr vm,
+ const char **mountpoints,
+ unsigned int nmountpoints)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverConfigPtr cfg;
@@ -12091,7 +12093,7 @@ qemuDomainSnapshotFSFreeze(virQEMUDriverPtr driver,
virObjectUnref(cfg);
qemuDomainObjEnterAgent(vm);
- freezed = qemuAgentFSFreeze(priv->agent);
+ freezed = qemuAgentFSFreeze(priv->agent, mountpoints, nmountpoints);
qemuDomainObjExitAgent(vm);
return freezed < 0 ? -2 : freezed;
}
@@ -13138,7 +13140,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
* The command will fail if the guest is paused or the guest agent
* is not running, or is already quiesced. */
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
- int freeze = qemuDomainSnapshotFSFreeze(driver, vm);
+ int freeze = qemuDomainSnapshotFSFreeze(driver, vm, NULL, 0);
if (freeze < 0) {
/* the helper reported the error */
if (freeze == -2)
@@ -16539,12 +16541,6 @@ qemuDomainFSFreeze(virDomainPtr dom,
virCheckFlags(0, -1);
- if (mountpoints || nmountpoints) {
- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
- _("specifying mountpoints is not supported"));
- return ret;
- }
-
if (!(vm = qemuDomObjFromDomain(dom)))
goto cleanup;
@@ -16560,7 +16556,7 @@ qemuDomainFSFreeze(virDomainPtr dom,
goto endjob;
}
- ret = qemuDomainSnapshotFSFreeze(driver, vm);
+ ret = qemuDomainSnapshotFSFreeze(driver, vm, mountpoints, nmountpoints);
if (ret == -2) {
qemuDomainSnapshotFSThaw(driver, vm, false);
ret = -1;
diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c
index 1131d98..be207e8 100644
--- a/tests/qemuagenttest.c
+++ b/tests/qemuagenttest.c
@@ -36,6 +36,7 @@ testQemuAgentFSFreeze(const void *data)
{
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
+ const char *mountpoints[] = {"/fs1", "/fs2", "/fs3",
"/fs4", "/fs5"};
int ret = -1;
if (!test)
@@ -55,7 +56,8 @@ testQemuAgentFSFreeze(const void *data)
"{ \"return\" : 7 }") < 0)
goto cleanup;
- if ((ret = qemuAgentFSFreeze(qemuMonitorTestGetAgent(test))) < 0)
+ if ((ret = qemuAgentFSFreeze(qemuMonitorTestGetAgent(test),
+ mountpoints, 5)) < 0)
goto cleanup;
if (ret != 5) {
@@ -64,7 +66,7 @@ testQemuAgentFSFreeze(const void *data)
goto cleanup;
}
- if ((ret = qemuAgentFSFreeze(qemuMonitorTestGetAgent(test))) < 0)
+ if ((ret = qemuAgentFSFreeze(qemuMonitorTestGetAgent(test), NULL, 0)) < 0)
goto cleanup;
if (ret != 7) {
@@ -547,7 +549,7 @@ testQemuAgentTimeout(const void *data)
NULL, NULL) < 0)
goto cleanup;
- if (qemuAgentFSFreeze(qemuMonitorTestGetAgent(test)) != -1) {
+ if (qemuAgentFSFreeze(qemuMonitorTestGetAgent(test), NULL, 0) != -1) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
"agent command should have failed");
goto cleanup;