[libvirt] [PATCH v6 1/5] migration: qemu: add option to select compression methods

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Thu Apr 14 10:33:48 UTC 2016


Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
---
 include/libvirt/libvirt-domain.h |   9 ++
 src/qemu/qemu_driver.c           |  60 +++++++++++---
 src/qemu/qemu_migration.c        | 173 +++++++++++++++++++++++++++++++++------
 src/qemu/qemu_migration.h        |  27 ++++++
 src/qemu/qemu_monitor.c          |   2 +-
 src/qemu/qemu_monitor.h          |   1 +
 6 files changed, 234 insertions(+), 38 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 8220ab0..cc8f7de 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -787,6 +787,15 @@ typedef enum {
  */
 # define VIR_MIGRATE_PARAM_DISKS_PORT    "disks_port"
 
+/**
+ * VIR_MIGRATE_PARAM_COMPRESSION:
+ *
+ * virDomainMigrate* params multiple field: name of the method used to
+ * compress migration traffic. The parameter may be specified multiple times
+ * if more than one method should be used.
+ */
+# define VIR_MIGRATE_PARAM_COMPRESSION    "compression"
+
 /* Domain migration. */
 virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn,
                                unsigned long flags, const char *dname,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index eaabe58..44e8aa0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12087,6 +12087,7 @@ qemuDomainMigratePrepare2(virConnectPtr dconn,
     virQEMUDriverPtr driver = dconn->privateData;
     virDomainDefPtr def = NULL;
     char *origname = NULL;
+    qemuMigrationCompressionPtr compression = NULL;
     int ret = -1;
 
     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
@@ -12101,6 +12102,9 @@ qemuDomainMigratePrepare2(virConnectPtr dconn,
         goto cleanup;
     }
 
+    if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+        goto cleanup;
+
     if (virLockManagerPluginUsesState(driver->lockManager)) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Cannot use migrate v2 protocol with lock manager %s"),
@@ -12121,9 +12125,11 @@ qemuDomainMigratePrepare2(virConnectPtr dconn,
     ret = qemuMigrationPrepareDirect(driver, dconn,
                                      NULL, 0, NULL, NULL, /* No cookies */
                                      uri_in, uri_out,
-                                     &def, origname, NULL, 0, NULL, 0, flags);
+                                     &def, origname, NULL, 0, NULL, 0,
+                                     compression, flags);
 
  cleanup:
+    VIR_FREE(compression);
     VIR_FREE(origname);
     virDomainDefFree(def);
     return ret;
@@ -12144,6 +12150,7 @@ qemuDomainMigratePerform(virDomainPtr dom,
     virDomainObjPtr vm;
     int ret = -1;
     const char *dconnuri = NULL;
+    qemuMigrationCompressionPtr compression = NULL;
 
     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
 
@@ -12154,6 +12161,9 @@ qemuDomainMigratePerform(virDomainPtr dom,
         goto cleanup;
     }
 
+    if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+        goto cleanup;
+
     if (!(vm = qemuDomObjFromDomain(dom)))
         goto cleanup;
 
@@ -12175,11 +12185,12 @@ qemuDomainMigratePerform(virDomainPtr dom,
      */
     ret = qemuMigrationPerform(driver, dom->conn, vm,
                                NULL, dconnuri, uri, NULL, NULL, 0, NULL, 0,
-                               cookie, cookielen,
+                               compression, cookie, cookielen,
                                NULL, NULL, /* No output cookies in v2 */
                                flags, dname, resource, false);
 
  cleanup:
+    VIR_FREE(compression);
     return ret;
 }
 
@@ -12323,6 +12334,7 @@ qemuDomainMigratePrepare3(virConnectPtr dconn,
     virQEMUDriverPtr driver = dconn->privateData;
     virDomainDefPtr def = NULL;
     char *origname = NULL;
+    qemuMigrationCompressionPtr compression = NULL;
     int ret = -1;
 
     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
@@ -12337,6 +12349,9 @@ qemuDomainMigratePrepare3(virConnectPtr dconn,
         goto cleanup;
     }
 
+    if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+        goto cleanup;
+
     if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname, &origname)))
         goto cleanup;
 
@@ -12347,9 +12362,11 @@ qemuDomainMigratePrepare3(virConnectPtr dconn,
                                      cookiein, cookieinlen,
                                      cookieout, cookieoutlen,
                                      uri_in, uri_out,
-                                     &def, origname, NULL, 0, NULL, 0, flags);
+                                     &def, origname, NULL, 0, NULL, 0,
+                                     compression, flags);
 
  cleanup:
+    VIR_FREE(compression);
     VIR_FREE(origname);
     virDomainDefFree(def);
     return ret;
@@ -12377,6 +12394,7 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
     int nmigrate_disks;
     const char **migrate_disks = NULL;
     char *origname = NULL;
+    qemuMigrationCompressionPtr compression = NULL;
     int ret = -1;
 
     virCheckFlagsGoto(QEMU_MIGRATION_FLAGS, cleanup);
@@ -12407,6 +12425,9 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
     if (nmigrate_disks < 0)
         goto cleanup;
 
+    if (!(compression = qemuMigrationCompressionParse(params, nparams, flags)))
+        goto cleanup;
+
     if (flags & VIR_MIGRATE_TUNNELLED) {
         /* this is a logical error; we never should have gotten here with
          * VIR_MIGRATE_TUNNELLED set
@@ -12428,10 +12449,11 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
                                      cookieout, cookieoutlen,
                                      uri_in, uri_out,
                                      &def, origname, listenAddress,
-                                     nmigrate_disks, migrate_disks,
-                                     nbdPort, flags);
+                                     nmigrate_disks, migrate_disks, nbdPort,
+                                     compression, flags);
 
  cleanup:
+    VIR_FREE(compression);
     VIR_FREE(migrate_disks);
     VIR_FREE(origname);
     virDomainDefFree(def);
@@ -12551,22 +12573,32 @@ qemuDomainMigratePerform3(virDomainPtr dom,
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    qemuMigrationCompressionPtr compression = NULL;
+    int ret = -1;
 
     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
 
     if (!(vm = qemuDomObjFromDomain(dom)))
         return -1;
 
+    if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+        return -1;
+
     if (virDomainMigratePerform3EnsureACL(dom->conn, vm->def) < 0) {
         virDomainObjEndAPI(&vm);
-        return -1;
+        goto cleanup;
     }
 
-    return qemuMigrationPerform(driver, dom->conn, vm, xmlin,
-                                dconnuri, uri, NULL, NULL, 0, NULL, 0,
-                                cookiein, cookieinlen,
-                                cookieout, cookieoutlen,
-                                flags, dname, resource, true);
+    ret = qemuMigrationPerform(driver, dom->conn, vm, xmlin,
+                               dconnuri, uri, NULL, NULL, 0, NULL, 0,
+                               compression,
+                               cookiein, cookieinlen,
+                               cookieout, cookieoutlen,
+                               flags, dname, resource, true);
+
+ cleanup:
+    VIR_FREE(compression);
+    return ret;
 }
 
 static int
@@ -12591,6 +12623,7 @@ qemuDomainMigratePerform3Params(virDomainPtr dom,
     const char **migrate_disks = NULL;
     unsigned long long bandwidth = 0;
     int nbdPort = 0;
+    qemuMigrationCompressionPtr compression = NULL;
     int ret = -1;
 
     virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
@@ -12627,6 +12660,9 @@ qemuDomainMigratePerform3Params(virDomainPtr dom,
     if (nmigrate_disks < 0)
         goto cleanup;
 
+    if (!(compression = qemuMigrationCompressionParse(params, nparams, flags)))
+        goto cleanup;
+
     if (!(vm = qemuDomObjFromDomain(dom)))
         goto cleanup;
 
@@ -12638,9 +12674,11 @@ qemuDomainMigratePerform3Params(virDomainPtr dom,
     ret = qemuMigrationPerform(driver, dom->conn, vm, dom_xml,
                                dconnuri, uri, graphicsuri, listenAddress,
                                nmigrate_disks, migrate_disks, nbdPort,
+                               compression,
                                cookiein, cookieinlen, cookieout, cookieoutlen,
                                flags, dname, bandwidth, true);
  cleanup:
+    VIR_FREE(compression);
     VIR_FREE(migrate_disks);
     return ret;
 }
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index e72c874..8fe0f0d 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -79,6 +79,11 @@ VIR_ENUM_IMPL(qemuMigrationJobPhase, QEMU_MIGRATION_PHASE_LAST,
               "finish3",
 );
 
+VIR_ENUM_IMPL(qemuMigrationCompressMethod, QEMU_MIGRATION_COMPRESS_LAST,
+              "xbzrle",
+              "mt",
+);
+
 enum qemuMigrationCookieFlags {
     QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
     QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
@@ -3414,6 +3419,29 @@ qemuMigrationPrepareIncoming(virDomainObjPtr vm,
 }
 
 static int
+qemuMigrationSetCompression(virQEMUDriverPtr driver,
+                            virDomainObjPtr vm,
+                            qemuDomainAsyncJob job,
+                            qemuMigrationCompressionPtr compression)
+{
+    if (qemuMigrationSetOption(driver, vm,
+                               QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
+                               compression->methods &
+                                   (1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE),
+                               job) < 0)
+        return -1;
+
+    if (qemuMigrationSetOption(driver, vm,
+                               QEMU_MONITOR_MIGRATION_CAPS_COMPRESS,
+                               compression->methods &
+                                   (1ULL << QEMU_MIGRATION_COMPRESS_MULTITHREAD),
+                               job) < 0)
+        return -1;
+
+    return 0;
+}
+
+static int
 qemuMigrationPrepareAny(virQEMUDriverPtr driver,
                         virConnectPtr dconn,
                         const char *cookiein,
@@ -3430,6 +3458,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
                         size_t nmigrate_disks,
                         const char **migrate_disks,
                         int nbdPort,
+                        qemuMigrationCompressionPtr compression,
                         unsigned long flags)
 {
     virDomainObjPtr vm = NULL;
@@ -3627,10 +3656,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
         dataFD[1] = -1; /* 'st' owns the FD now & will close it */
     }
 
-    if (qemuMigrationSetOption(driver, vm,
-                               QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
-                               flags & VIR_MIGRATE_COMPRESSED,
-                               QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
+    if (qemuMigrationSetCompression(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN,
+                                    compression) < 0)
         goto stopjob;
 
     if (STREQ_NULLABLE(protocol, "rdma") &&
@@ -3768,6 +3795,7 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
                            const char *origname,
                            unsigned long flags)
 {
+    qemuMigrationCompressionPtr compression = NULL;
     int ret;
 
     VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
@@ -3782,9 +3810,14 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
         return -1;
     }
 
+    if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+        return -1;
+
     ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
                                   cookieout, cookieoutlen, def, origname,
-                                  st, NULL, 0, false, NULL, 0, NULL, 0, flags);
+                                  st, NULL, 0, false, NULL, 0, NULL, 0,
+                                  compression, flags);
+    VIR_FREE(compression);
     return ret;
 }
 
@@ -3827,6 +3860,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
                            size_t nmigrate_disks,
                            const char **migrate_disks,
                            int nbdPort,
+                           qemuMigrationCompressionPtr compression,
                            unsigned long flags)
 {
     unsigned short port = 0;
@@ -3949,7 +3983,8 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
                                   cookieout, cookieoutlen, def, origname,
                                   NULL, uri ? uri->scheme : "tcp",
                                   port, autoPort, listenAddress,
-                                  nmigrate_disks, migrate_disks, nbdPort, flags);
+                                  nmigrate_disks, migrate_disks, nbdPort,
+                                  compression, flags);
  cleanup:
     virURIFree(uri);
     VIR_FREE(hostname);
@@ -4457,7 +4492,8 @@ qemuMigrationRun(virQEMUDriverPtr driver,
                  virConnectPtr dconn,
                  const char *graphicsuri,
                  size_t nmigrate_disks,
-                 const char **migrate_disks)
+                 const char **migrate_disks,
+                 qemuMigrationCompressionPtr compression)
 {
     int ret = -1;
     unsigned int migrate_flags = QEMU_MONITOR_MIGRATE_BACKGROUND;
@@ -4541,10 +4577,8 @@ qemuMigrationRun(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
-    if (qemuMigrationSetOption(driver, vm,
-                               QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
-                               flags & VIR_MIGRATE_COMPRESSED,
-                               QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
+    if (qemuMigrationSetCompression(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
+                                    compression) < 0)
         goto cleanup;
 
     if (qemuMigrationSetOption(driver, vm,
@@ -4785,7 +4819,8 @@ static int doNativeMigrate(virQEMUDriverPtr driver,
                            virConnectPtr dconn,
                            const char *graphicsuri,
                            size_t nmigrate_disks,
-                           const char **migrate_disks)
+                           const char **migrate_disks,
+                           qemuMigrationCompressionPtr compression)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virURIPtr uribits = NULL;
@@ -4835,7 +4870,8 @@ static int doNativeMigrate(virQEMUDriverPtr driver,
 
     ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
                            cookieoutlen, flags, resource, &spec, dconn,
-                           graphicsuri, nmigrate_disks, migrate_disks);
+                           graphicsuri, nmigrate_disks, migrate_disks,
+                           compression);
 
     if (spec.destType == MIGRATION_DEST_FD)
         VIR_FORCE_CLOSE(spec.dest.fd.qemu);
@@ -4859,7 +4895,8 @@ static int doTunnelMigrate(virQEMUDriverPtr driver,
                            virConnectPtr dconn,
                            const char *graphicsuri,
                            size_t nmigrate_disks,
-                           const char **migrate_disks)
+                           const char **migrate_disks,
+                           qemuMigrationCompressionPtr compression)
 {
     virNetSocketPtr sock = NULL;
     int ret = -1;
@@ -4896,7 +4933,8 @@ static int doTunnelMigrate(virQEMUDriverPtr driver,
 
     ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
                            cookieoutlen, flags, resource, &spec, dconn,
-                           graphicsuri, nmigrate_disks, migrate_disks);
+                           graphicsuri, nmigrate_disks, migrate_disks,
+                           compression);
 
  cleanup:
     if (spec.destType == MIGRATION_DEST_FD) {
@@ -4934,6 +4972,7 @@ static int doPeer2PeerMigrate2(virQEMUDriverPtr driver,
     bool cancelled;
     virStreamPtr st = NULL;
     unsigned long destflags;
+    qemuMigrationCompressionPtr compression = NULL;
 
     VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, vm=%p, dconnuri=%s, "
               "flags=%lx, dname=%s, resource=%lu",
@@ -4955,6 +4994,9 @@ static int doPeer2PeerMigrate2(virQEMUDriverPtr driver,
     destflags = flags & ~(VIR_MIGRATE_ABORT_ON_ERROR |
                           VIR_MIGRATE_AUTO_CONVERGE);
 
+    if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+        goto cleanup;
+
     VIR_DEBUG("Prepare2 %p", dconn);
     if (flags & VIR_MIGRATE_TUNNELLED) {
         /*
@@ -5007,12 +5049,12 @@ static int doPeer2PeerMigrate2(virQEMUDriverPtr driver,
         ret = doTunnelMigrate(driver, vm, st,
                               NULL, 0, NULL, NULL,
                               flags, resource, dconn,
-                              NULL, 0, NULL);
+                              NULL, 0, NULL, compression);
     else
         ret = doNativeMigrate(driver, vm, uri_out,
                               cookie, cookielen,
                               NULL, NULL, /* No out cookie with v2 migration */
-                              flags, resource, dconn, NULL, 0, NULL);
+                              flags, resource, dconn, NULL, 0, NULL, compression);
 
     /* Perform failed. Make sure Finish doesn't overwrite the error */
     if (ret < 0)
@@ -5054,6 +5096,7 @@ static int doPeer2PeerMigrate2(virQEMUDriverPtr driver,
     }
     VIR_FREE(uri_out);
     VIR_FREE(cookie);
+    VIR_FREE(compression);
 
     return ret;
 }
@@ -5077,6 +5120,7 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
                     size_t nmigrate_disks,
                     const char **migrate_disks,
                     int nbdPort,
+                    qemuMigrationCompressionPtr compression,
                     unsigned long long bandwidth,
                     bool useParams,
                     unsigned long flags)
@@ -5159,6 +5203,10 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
                                  VIR_MIGRATE_PARAM_DISKS_PORT,
                                  nbdPort) < 0)
             goto cleanup;
+
+        if (qemuMigrationCompressionDump(compression, &params, &nparams,
+                                         &maxparams, &flags) < 0)
+            goto cleanup;
     }
 
     if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
@@ -5244,13 +5292,13 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
                               cookiein, cookieinlen,
                               &cookieout, &cookieoutlen,
                               flags, bandwidth, dconn, graphicsuri,
-                              nmigrate_disks, migrate_disks);
+                              nmigrate_disks, migrate_disks, compression);
     } else {
         ret = doNativeMigrate(driver, vm, uri,
                               cookiein, cookieinlen,
                               &cookieout, &cookieoutlen,
                               flags, bandwidth, dconn, graphicsuri,
-                              nmigrate_disks, migrate_disks);
+                              nmigrate_disks, migrate_disks, compression);
     }
 
     /* Perform failed. Make sure Finish doesn't overwrite the error */
@@ -5426,6 +5474,7 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
                               size_t nmigrate_disks,
                               const char **migrate_disks,
                               int nbdPort,
+                              qemuMigrationCompressionPtr compression,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource,
@@ -5549,7 +5598,7 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
         ret = doPeer2PeerMigrate3(driver, sconn, dconn, dconnuri, vm, xmlin,
                                   dname, uri, graphicsuri, listenAddress,
                                   nmigrate_disks, migrate_disks, nbdPort,
-                                  resource, useParams, flags);
+                                  compression, resource, useParams, flags);
     } else {
         ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm,
                                   dconnuri, flags, dname, resource);
@@ -5587,6 +5636,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
                         size_t nmigrate_disks,
                         const char **migrate_disks,
                         int nbdPort,
+                        qemuMigrationCompressionPtr compression,
                         const char *cookiein,
                         int cookieinlen,
                         char **cookieout,
@@ -5623,12 +5673,13 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
         ret = doPeer2PeerMigrate(driver, conn, vm, xmlin,
                                  dconnuri, uri, graphicsuri, listenAddress,
                                  nmigrate_disks, migrate_disks, nbdPort,
-                                 flags, dname, resource, &v3proto);
+                                 compression, flags, dname, resource, &v3proto);
     } else {
         qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2);
         ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
                               cookieout, cookieoutlen,
-                              flags, resource, NULL, NULL, 0, NULL);
+                              flags, resource, NULL, NULL, 0, NULL,
+                              compression);
     }
     if (ret < 0)
         goto endjob;
@@ -5689,6 +5740,7 @@ qemuMigrationPerformPhase(virQEMUDriverPtr driver,
                           const char *graphicsuri,
                           size_t nmigrate_disks,
                           const char **migrate_disks,
+                          qemuMigrationCompressionPtr compression,
                           const char *cookiein,
                           int cookieinlen,
                           char **cookieout,
@@ -5714,7 +5766,7 @@ qemuMigrationPerformPhase(virQEMUDriverPtr driver,
     ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
                           cookieout, cookieoutlen,
                           flags, resource, NULL, graphicsuri,
-                          nmigrate_disks, migrate_disks);
+                          nmigrate_disks, migrate_disks, compression);
 
     if (ret < 0) {
         if (qemuMigrationRestoreDomainState(conn, vm)) {
@@ -5757,6 +5809,7 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
                      size_t nmigrate_disks,
                      const char **migrate_disks,
                      int nbdPort,
+                     qemuMigrationCompressionPtr compression,
                      const char *cookiein,
                      int cookieinlen,
                      char **cookieout,
@@ -5787,7 +5840,7 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
         return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri, uri,
                                        graphicsuri, listenAddress,
                                        nmigrate_disks, migrate_disks, nbdPort,
-                                       cookiein, cookieinlen,
+                                       compression, cookiein, cookieinlen,
                                        cookieout, cookieoutlen,
                                        flags, dname, resource, v3proto);
     } else {
@@ -5801,14 +5854,14 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
             return qemuMigrationPerformPhase(driver, conn, vm, uri,
                                              graphicsuri,
                                              nmigrate_disks, migrate_disks,
-                                             cookiein, cookieinlen,
+                                             compression, cookiein, cookieinlen,
                                              cookieout, cookieoutlen,
                                              flags, resource);
         } else {
             return qemuMigrationPerformJob(driver, conn, vm, xmlin, NULL,
                                            uri, graphicsuri, listenAddress,
                                            nmigrate_disks, migrate_disks, nbdPort,
-                                           cookiein, cookieinlen,
+                                           compression, cookiein, cookieinlen,
                                            cookieout, cookieoutlen, flags,
                                            dname, resource, v3proto);
         }
@@ -6558,3 +6611,71 @@ qemuMigrationErrorReport(virQEMUDriverPtr driver,
     virSetError(err);
     virFreeError(err);
 }
+
+/* don't ever pass NULL params with non zero nparams */
+qemuMigrationCompressionPtr
+qemuMigrationCompressionParse(virTypedParameterPtr params, int nparams,
+                              unsigned long flags)
+{
+    size_t i;
+    qemuMigrationCompressionPtr compression = NULL;
+
+    if (VIR_ALLOC(compression) < 0)
+        return NULL;
+
+    for (i = 0; i < nparams; i++) {
+        int method;
+
+        if (STRNEQ(params[i].field, VIR_MIGRATE_PARAM_COMPRESSION))
+            continue;
+
+        if ((method = qemuMigrationCompressMethodTypeFromString(params[i].value.s)) < 0) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("Unsupported compression method '%s'"),
+                           params[i].value.s);
+            goto error;
+        }
+
+        if (compression->methods & (1ULL << method)) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("Compression method '%s' is specified twice"),
+                           params[i].value.s);
+            goto error;
+        }
+
+        compression->methods |= 1ULL << method;
+    }
+
+    if (!compression->methods && (flags & VIR_MIGRATE_COMPRESSED))
+        compression->methods = 1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE;
+
+    return compression;
+
+ error:
+    VIR_FREE(compression);
+    return NULL;
+}
+
+int
+qemuMigrationCompressionDump(qemuMigrationCompressionPtr compression,
+                             virTypedParameterPtr *params,
+                             int *nparams, int *maxparams,
+                             unsigned long *flags)
+{
+    size_t i;
+
+    if (compression->methods == 1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE) {
+        *flags |= VIR_MIGRATE_COMPRESSED;
+        return 0;
+    }
+
+    for (i = QEMU_MIGRATION_COMPRESS_XBZRLE; i < QEMU_MIGRATION_COMPRESS_LAST; ++i) {
+        if ((compression->methods & (1ULL << i)) &&
+            virTypedParamsAddString(params, nparams, maxparams,
+                                    VIR_MIGRATE_PARAM_COMPRESSION,
+                                    qemuMigrationCompressMethodTypeToString(i)) < 0)
+            return -1;
+    }
+
+    return 0;
+}
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index a927bea..cb51ca5 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -25,6 +25,9 @@
 # include "qemu_conf.h"
 # include "qemu_domain.h"
 
+typedef struct _qemuMigrationCompression qemuMigrationCompression;
+typedef qemuMigrationCompression *qemuMigrationCompressionPtr;
+
 /* All supported qemu migration flags.  */
 # define QEMU_MIGRATION_FLAGS                   \
     (VIR_MIGRATE_LIVE |                         \
@@ -55,6 +58,8 @@
     VIR_MIGRATE_PARAM_MIGRATE_DISKS,    VIR_TYPED_PARAM_STRING |  \
                                         VIR_TYPED_PARAM_MULTIPLE, \
     VIR_MIGRATE_PARAM_DISKS_PORT,       VIR_TYPED_PARAM_INT,      \
+    VIR_MIGRATE_PARAM_COMPRESSION,      VIR_TYPED_PARAM_STRING |  \
+                                        VIR_TYPED_PARAM_MULTIPLE, \
     NULL
 
 
@@ -74,6 +79,26 @@ typedef enum {
 } qemuMigrationJobPhase;
 VIR_ENUM_DECL(qemuMigrationJobPhase)
 
+typedef enum {
+    QEMU_MIGRATION_COMPRESS_XBZRLE = 0,
+    QEMU_MIGRATION_COMPRESS_MULTITHREAD,
+
+    QEMU_MIGRATION_COMPRESS_LAST
+} qemuMigrationCompressMethod;
+VIR_ENUM_DECL(qemuMigrationCompressMethod)
+
+struct _qemuMigrationCompression {
+    unsigned long long methods;
+};
+
+qemuMigrationCompressionPtr
+qemuMigrationCompressionParse(virTypedParameterPtr params, int nparams,
+                              unsigned long flags);
+int qemuMigrationCompressionDump(qemuMigrationCompressionPtr compression,
+                                 virTypedParameterPtr *params,
+                                 int *nparams, int *maxparams,
+                                 unsigned long *flags);
+
 int qemuMigrationJobStart(virQEMUDriverPtr driver,
                           virDomainObjPtr vm,
                           qemuDomainAsyncJob job)
@@ -137,6 +162,7 @@ int qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
                                size_t nmigrate_disks,
                                const char **migrate_disks,
                                int nbdPort,
+                               qemuMigrationCompressionPtr compression,
                                unsigned long flags);
 
 int qemuMigrationPerform(virQEMUDriverPtr driver,
@@ -150,6 +176,7 @@ int qemuMigrationPerform(virQEMUDriverPtr driver,
                          size_t nmigrate_disks,
                          const char **migrate_disks,
                          int nbdPort,
+                         qemuMigrationCompressionPtr compression,
                          const char *cookiein,
                          int cookieinlen,
                          char **cookieout,
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b7e4fa9..ac9befa 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -168,7 +168,7 @@ VIR_ENUM_IMPL(qemuMonitorMigrationStatus,
 VIR_ENUM_IMPL(qemuMonitorMigrationCaps,
               QEMU_MONITOR_MIGRATION_CAPS_LAST,
               "xbzrle", "auto-converge", "rdma-pin-all", "events",
-              "postcopy-ram")
+              "postcopy-ram", "compress")
 
 VIR_ENUM_IMPL(qemuMonitorVMStatus,
               QEMU_MONITOR_VM_STATUS_LAST,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index bb74917..78efcd7 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -551,6 +551,7 @@ typedef enum {
     QEMU_MONITOR_MIGRATION_CAPS_RDMA_PIN_ALL,
     QEMU_MONITOR_MIGRATION_CAPS_EVENTS,
     QEMU_MONITOR_MIGRATION_CAPS_POSTCOPY,
+    QEMU_MONITOR_MIGRATION_CAPS_COMPRESS,
 
     QEMU_MONITOR_MIGRATION_CAPS_LAST
 } qemuMonitorMigrationCaps;
-- 
1.8.3.1




More information about the libvir-list mailing list