---
src/qemu/qemu_domain.c | 1 +
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 42 ++++++++++++++++++++++++++++++++++++++++--
3 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 69d9e6e..e3a668a 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -158,6 +158,7 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
job->phase = 0;
job->mask = DEFAULT_JOB_MASK;
job->start = 0;
+ job->qemu_dump = false;
memset(&job->info, 0, sizeof(job->info));
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index adccfed..f1ab0e6 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -97,6 +97,7 @@ struct qemuDomainJobObj {
int phase; /* Job phase (mainly for migrations) */
unsigned long long mask; /* Jobs allowed during async job */
unsigned long long start; /* When the async job started */
+ bool qemu_dump; /* use qemu dump to do dump */
virDomainJobInfo info; /* Async job progress data */
};
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d503deb..0186d60 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2922,6 +2922,31 @@ cleanup:
return ret;
}
+/* Return 0 on success, -1 on failure, or -2 if not supported. */
+static int qemuDumpToFd(struct qemud_driver *driver, virDomainObjPtr vm,
+ int fd, enum qemuDomainAsyncJob asyncJob)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int ret = -1;
+
+ if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD))
+ return -2;
+
+ if (virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def,
+ fd) < 0)
+ return -1;
+
+ priv->job.qemu_dump = true;
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ ret = qemuMonitorDumpToFd(priv->mon, 0, fd, 0, 0);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+ return ret;
+}
+
static int
doCoreDump(struct qemud_driver *driver,
virDomainObjPtr vm,
@@ -2953,6 +2978,19 @@ doCoreDump(struct qemud_driver *driver,
NULL, NULL)) < 0)
goto cleanup;
+ if (vm->def->nhostdevs > 0) {
+ /*
+ * If the guest uses host devices, migrate command will fail. So we
+ * should use dump command.
+ *
+ * qemu dump does not support fd that is associated with a pipe,
+ * socket, or FIFO. So we should call qemuDumpTpFd() before calling
+ * virFileWrapperFdNew(). */
+ ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP);
+ if (ret != -2)
+ goto cleanup;
+ }
+
if (!(wrapperFd = virFileWrapperFdNew(&fd, path, flags)))
goto cleanup;
@@ -9298,7 +9336,7 @@ static int qemuDomainGetJobInfo(virDomainPtr dom,
priv = vm->privateData;
if (virDomainObjIsActive(vm)) {
- if (priv->job.asyncJob) {
+ if (priv->job.asyncJob && !priv->job.qemu_dump) {
memcpy(info, &priv->job.info, sizeof(*info));
/* Refresh elapsed time again just to ensure it
@@ -9356,7 +9394,7 @@ static int qemuDomainAbortJob(virDomainPtr dom) {
priv = vm->privateData;
- if (!priv->job.asyncJob) {
+ if (!priv->job.asyncJob || priv->job.qemu_dump) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("no job is active on the domain"));
goto endjob;
--
1.7.1