From ef43884e86784fcb115684f2138a1c7993df9dce Mon Sep 17 00:00:00 2001
From: fanmingzhan <fanmingzhan@h-partners.com>
Date: Mon, 24 Nov 2025 12:58:16 +0000
Subject: [PATCH 7/7] =?UTF-8?q?!7=20ham=20migration:=20=20delete=20virDoma?=
 =?UTF-8?q?inQemuMonitorCommandAsync=20and=20add=20meson=20config=20*=20ha?=
 =?UTF-8?q?m=20migration:=20clean=20code=20modify=20*=20Merge=20remote-tra?=
 =?UTF-8?q?cking=20branch=20'origin/libvirt-9.10.0=5Fori=5Ffinal'=20into?=
 =?UTF-8?q?=20li=E2=80=A6=20*=20Revert=20"ham=20migration:=20delete=20qemu?=
 =?UTF-8?q?DomainSendQemuMonitorCommandAsync"=20*=20Revert=20"ham=20migrat?=
 =?UTF-8?q?ion:=20delete=20qemuDomainSendQemuMonitorCommandAsync"=20*=20!6?=
 =?UTF-8?q?=20ham=20migration:=20delete=20qemuDomainSendQemuMonitorCommand?=
 =?UTF-8?q?Async?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 include/libvirt/libvirt-domain.h    |  7 +++-
 include/libvirt/libvirt-qemu.h      |  3 --
 libvirt.spec.in                     |  9 ++++
 meson.build                         |  4 ++
 meson_options.txt                   |  1 +
 src/conf/domain_conf.c              |  4 ++
 src/conf/domain_conf.h              |  4 +-
 src/driver-hypervisor.h             |  7 ----
 src/libvirt-qemu.c                  | 64 -----------------------------
 src/libvirt_hammigrate.syms         | 11 +++++
 src/libvirt_private.syms            |  8 ----
 src/libvirt_qemu.syms               |  5 ---
 src/meson.build                     |  6 +++
 src/qemu/meson.build                |  6 ++-
 src/qemu/qemu_driver.c              | 51 ++++++++---------------
 src/qemu/qemu_ham.c                 |  6 +--
 src/qemu/qemu_ham.h                 |  2 +-
 src/qemu/qemu_migration.c           | 17 +++++++-
 src/qemu/qemu_migration.h           |  9 +++-
 src/qemu/qemu_migration_params.c    |  4 ++
 src/qemu/qemu_migration_params.h    |  4 +-
 src/qemu_protocol-structs           |  9 ----
 src/remote/qemu_protocol.x          | 19 +--------
 src/remote/remote_daemon.c          |  8 +++-
 src/remote/remote_daemon_config.c   |  6 ++-
 src/remote/remote_daemon_config.h   |  3 +-
 src/remote/remote_daemon_dispatch.c | 32 ---------------
 src/remote/remote_driver.c          | 25 -----------
 src/util/meson.build                |  5 ++-
 src/util/virham.c                   |  9 ++--
 tools/virsh-domain.c                |  9 +++-
 31 files changed, 128 insertions(+), 229 deletions(-)
 create mode 100644 src/libvirt_hammigrate.syms

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index a6f97e0b5f..b4f31f72ae 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1115,12 +1115,13 @@ typedef enum {
      * Since: 9.10.0
      */
     VIR_MIGRATE_ONECOPY = (1 << 22),
-
+#ifdef WITH_HAM_MIGRATE
     /* Support ham migration by LDST.
      *
      * Since: 9.10.0
      */
-    VIR_MIGRATE_LDST = (1 << 27),
+    VIR_MIGRATE_LDST = (1 << 23),
+#endif
 } virDomainMigrateFlags;
 
 
@@ -4209,8 +4210,10 @@ typedef enum {
      * suspended and it can later be resumed using virDomainMigrate* APIs with
      * VIR_MIGRATE_POSTCOPY_RESUME flag. (Since: 8.5.0) */
     VIR_DOMAIN_ABORT_JOB_POSTCOPY = 1 << 0,
+#ifdef WITH_HAM_MIGRATE
     /* Interrupt ham migration. (Since: 9.10.0) */
     VIR_DOMAIN_ABORT_JOB_HAM = 1 << 1,
+#endif
 } virDomainAbortJobFlagsValues;
 
 int virDomainAbortJobFlags(virDomainPtr dom,
diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h
index cd847933b2..a26498ab89 100644
--- a/include/libvirt/libvirt-qemu.h
+++ b/include/libvirt/libvirt-qemu.h
@@ -51,9 +51,6 @@ int virDomainQemuMonitorCommandWithFiles(virDomainPtr domain,
                                          char **result,
                                          unsigned int flags);
 
-int virDomainQemuMonitorCommandAsync(virDomainPtr domain, const char *cmd,
-                                     char **result, int asyncJob);
-
 virDomainPtr virDomainQemuAttach(virConnectPtr domain,
                                  unsigned int pid_value,
                                  unsigned int flags);
diff --git a/libvirt.spec.in b/libvirt.spec.in
index f3fdedfde4..c8a7c4993d 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -32,6 +32,7 @@
 
 # The hypervisor drivers that run in libvirtd
 %define with_qemu          0%{!?_without_qemu:1}
+%define with_ham_migrate   0%{!?_without_ham_migrate:%{with_qemu:1}}
 %define with_lxc           0%{!?_without_lxc:1}
 %define with_libxl         0%{!?_without_libxl:1}
 %define with_vbox          0%{!?_without_vbox:1}
@@ -1134,6 +1135,12 @@ exit 1
     %define arg_qemu -Ddriver_qemu=disabled
 %endif
 
+%if %{with_ham_migrate}
+    %define arg_ham_migrate -Dqemu_ham_migrate=enabled
+%else
+    %define arg_ham_migrate -Dqemu_ham_migrate=disabled
+%endif
+
 %if %{with_openvz}
     %define arg_openvz -Ddriver_openvz=enabled
 %else
@@ -1284,6 +1291,7 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec)
            -Drunstatedir=%{_rundir} \
            -Dinitconfdir=%{_sysconfdir}/sysconfig \
            %{?arg_qemu} \
+           %{?arg_ham_migrate} \
            %{?arg_openvz} \
            %{?arg_lxc} \
            %{?arg_vbox} \
@@ -1408,6 +1416,7 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec)
   -Dpciaccess=disabled \
   -Dpm_utils=disabled \
   -Dpolkit=disabled \
+  -Dqemu_ham_migrate=disabled \
   -Dreadline=disabled \
   -Drpath=disabled \
   -Dsanlock=disabled \
diff --git a/meson.build b/meson.build
index 1a8f234f7d..33ef49014f 100644
--- a/meson.build
+++ b/meson.build
@@ -1630,6 +1630,10 @@ if not get_option('driver_qemu').disabled()
   if use_qemu
     conf.set('WITH_QEMU', 1)
 
+    if get_option('qemu_ham_migrate').enabled()
+      conf.set('WITH_HAM_MIGRATE', 1)
+    endif
+
     conf.set('WITH_CLIENT_QEMU', 0)
     qemu_moddir = get_option('qemu_moddir')
     if qemu_moddir == ''
diff --git a/meson_options.txt b/meson_options.txt
index a0928102bf..52cf596977 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -60,6 +60,7 @@ option('ch_group', type: 'string', value: '', description: 'groupname to run Clo
 option('driver_network', type: 'feature', value: 'auto', description: 'virtual network driver')
 option('driver_openvz', type: 'feature', value: 'auto', description: 'OpenVZ driver')
 option('driver_qemu', type: 'feature', value: 'auto', description: 'QEMU/KVM driver')
+option('qemu_ham_migrate', type: 'feature', value: 'auto', description: 'QEMU ham migrate')
 option('qemu_user', type: 'string', value: '', description: 'username to run QEMU system instance as')
 option('qemu_group', type: 'string', value: '', description: 'groupname to run QEMU system instance as')
 option('qemu_moddir', type: 'string', value: '', description: 'set the directory where QEMU modules are located')
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d0071aaf20..6dba478900 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4106,7 +4106,9 @@ static void virDomainObjDispose(void *obj)
 
     VIR_DEBUG("obj=%p", dom);
     virCondDestroy(&dom->cond);
+#ifdef WITH_HAM_MIGRATE
     virCondDestroy(&dom->hamCond);
+#endif
     virDomainDefFree(dom->def);
     virDomainDefFree(dom->newDef);
 
@@ -4137,11 +4139,13 @@ virDomainObjNew(virDomainXMLOption *xmlopt)
         goto error;
     }
 
+#ifdef WITH_HAM_MIGRATE
     if (virCondInit(&domain->hamCond) < 0) {
         virReportSystemError(errno, "%s",
                              _("failed to initialize domain ham condition"));
         goto error;
     }
+#endif
 
     if (xmlopt->privateData.alloc) {
         domain->privateData = (xmlopt->privateData.alloc)(xmlopt->config.priv);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index bf82a2f481..2b40515e77 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3250,8 +3250,10 @@ struct _virDomainStateReason {
 struct _virDomainObj {
     virObjectLockable parent;
     virCond cond;
-    virCond hamCond;
 
+#ifdef WITH_HAM_MIGRATE
+    virCond hamCond;
+#endif
     virDomainJobObj *job;
 
     pid_t pid; /* 0 for no PID, avoid negative values like -1 */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index cc2c771337..619a091ffa 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -900,12 +900,6 @@ typedef int
                                            char **result,
                                            unsigned int flags);
 
-typedef int
-(*virDrvDomainQemuMonitorCommandAsync)(virDomainPtr domain,
-                                       const char *cmd,
-                                       char **result,
-                                       int asyncJob);
-
 typedef char *
 (*virDrvDomainQemuAgentCommand)(virDomainPtr domain,
                                 const char *cmd,
@@ -1650,7 +1644,6 @@ struct _virHypervisorDriver {
     virDrvDomainSnapshotDelete domainSnapshotDelete;
     virDrvDomainQemuMonitorCommand domainQemuMonitorCommand;
     virDrvDomainQemuMonitorCommandWithFiles domainQemuMonitorCommandWithFiles;
-    virDrvDomainQemuMonitorCommandAsync domainQemuMonitorCommandAsync;
     virDrvDomainQemuAttach domainQemuAttach;
     virDrvDomainQemuAgentCommand domainQemuAgentCommand;
     virDrvConnectDomainQemuMonitorEventRegister connectDomainQemuMonitorEventRegister;
diff --git a/src/libvirt-qemu.c b/src/libvirt-qemu.c
index 7a3a006776..2898b71983 100644
--- a/src/libvirt-qemu.c
+++ b/src/libvirt-qemu.c
@@ -190,70 +190,6 @@ virDomainQemuMonitorCommandWithFiles(virDomainPtr domain,
     return -1;
 }
 
-/**
- * virDomainQemuMonitorCommandAsync:
- * @domain: a domain object
- * @cmd: the QEMU monitor command string
- * @result: a string returned by @cmd
- * @asyncJob: enum of type virDomainAsyncJob
- *
- * This API is QEMU specific, so it will only work with hypervisor
- * connections to the QEMU driver.
- *
- * Send an arbitrary monitor command @cmd to @domain through the
- * QEMU monitor. There are several requirements to safely and
- * successfully use this API:
- *
- *   - A @cmd that queries state without making any modifications is safe
- *   - A @cmd that alters state that is also tracked by libvirt is unsafe,
- *     and may cause libvirtd to crash
- *   - A @cmd that alters state not tracked by the current version of
- *     libvirt is possible as a means to test new QEMU features before
- *     they have support in libvirt, but no guarantees are made to safety
- *
- * When @domain is running in async job, @asyncJob is considered to be set
- * as same as the domain's async job.
- *
- * If successful, @result will be filled with the string output of the
- * @cmd, and the caller must free this string.
- *
- * Returns 0 in case of success, -1 in case of failure
- *
- * Since: 9.10.0
- */
-int
-virDomainQemuMonitorCommandAsync(virDomainPtr domain, const char *cmd,
-                                 char **result, int asyncJob)
-{
-    virConnectPtr conn;
-
-    VIR_DOMAIN_DEBUG(domain, "cmd=%s, result=%p, asyncJob=%d",
-                     cmd, result, asyncJob);
-
-    virResetLastError();
-
-    virCheckDomainReturn(domain, -1);
-    conn = domain->conn;
-
-    virCheckNonNullArgGoto(result, error);
-    virCheckReadOnlyGoto(conn->flags, error);
-
-    if (conn->driver->domainQemuMonitorCommandAsync) {
-        int ret;
-        ret = conn->driver->domainQemuMonitorCommandAsync(domain, cmd, result,
-                                                          asyncJob);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
-
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
 /**
  * virDomainQemuAttach:
  * @conn: pointer to a hypervisor connection
diff --git a/src/libvirt_hammigrate.syms b/src/libvirt_hammigrate.syms
new file mode 100644
index 0000000000..db9d031aac
--- /dev/null
+++ b/src/libvirt_hammigrate.syms
@@ -0,0 +1,11 @@
+#
+# These symbols are dependent upon --with-ham-migrate via WITH_HAM_MIGRATE
+#
+
+
+# util/virham.h
+virHamClearAll;
+virHamGetCancelledTimeout;
+virHamGetClearReqInit;
+virHamRackIpcSyncSendAndRecv;
+virHamSetupTimeOut;
\ No newline at end of file
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 100b0cf98f..6ab78d504b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2459,14 +2459,6 @@ virGICVersionTypeToString;
 virGSListStringFree;
 
 
-# util/virham.h
-virHamClearAll;
-virHamGetCancelledTimeout;
-virHamGetClearReqInit;
-virHamRackIpcSyncSendAndRecv;
-virHamSetupTimeOut;
-
-
 # util/virhash.h
 virHashAddEntry;
 virHashAtomicNew;
diff --git a/src/libvirt_qemu.syms b/src/libvirt_qemu.syms
index 78a8d4d44b..182658bd0d 100644
--- a/src/libvirt_qemu.syms
+++ b/src/libvirt_qemu.syms
@@ -35,8 +35,3 @@ LIBVIRT_QEMU_8.2.0 {
     global:
         virDomainQemuMonitorCommandWithFiles;
 } LIBVIRT_QEMU_1.2.3;
-
-LIBVIRT_QEMU_9.10.0 {
-    global:
-        virDomainQemuMonitorCommandAsync;
-} LIBVIRT_QEMU_8.2.0;
diff --git a/src/meson.build b/src/meson.build
index f52d2d5994..5d6cefe88a 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -125,6 +125,12 @@ else
   sym_files += 'libvirt_libssh2.syms'
 endif
 
+if conf.has('WITH_HAM_MIGRATE')
+  used_sym_files += 'libvirt_hammigrate.syms'
+else
+  sym_files += 'libvirt_hammigrate.syms'
+endif
+
 # variables filled by subdirectories
 
 libvirt_libs = []
diff --git a/src/qemu/meson.build b/src/qemu/meson.build
index 90ba7810d4..2bbeacfc11 100644
--- a/src/qemu/meson.build
+++ b/src/qemu/meson.build
@@ -43,9 +43,13 @@ qemu_driver_sources = [
   'qemu_vhost_user_gpu.c',
   'qemu_virtiofs.c',
   'qemu_hotpatch.c',
-  'qemu_ham.c',
 ]
 
+
+if conf.has('WITH_HAM_MIGRATE')
+  qemu_driver_sources += 'qemu_ham.c'
+endif
+
 driver_source_files += files(qemu_driver_sources)
 stateful_driver_source_files += files(qemu_driver_sources)
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 69a2f10de4..2df60dc260 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -52,7 +52,10 @@
 #include "qemu_saveimage.h"
 #include "qemu_snapshot.h"
 #include "qemu_validate.h"
+#ifdef WITH_HAM_MIGRATE
 #include "qemu_ham.h"
+#include "virham.h"
+#endif
 
 #include "virerror.h"
 #include "virlog.h"
@@ -103,7 +106,6 @@
 #include "netdev_bandwidth_conf.h"
 #include "virdomainsnapshotobjlist.h"
 #include "virenum.h"
-#include "virham.h"
 #include "virdomaincheckpointobjlist.h"
 #include "virutil.h"
 #include "backup_conf.h"
@@ -12181,6 +12183,7 @@ qemuDomainAbortJobPostcopy(virDomainObj *vm,
     return rc;
 }
 
+#ifdef WITH_HAM_MIGRATE
 static int
 qemuHamWaitForCancelled(virDomainObj *vm)
 {
@@ -12200,7 +12203,7 @@ qemuHamWaitForCancelled(virDomainObj *vm)
 
     return 0;
 }
-
+#endif
 
 static int
 qemuDomainAbortJobFlags(virDomainPtr dom,
@@ -12209,12 +12212,18 @@ qemuDomainAbortJobFlags(virDomainPtr dom,
     virDomainObj *vm;
     int ret = -1;
     qemuDomainObjPrivate *priv;
-    bool isHam = false;
 
+#ifdef WITH_HAM_MIGRATE
+    bool isHam = false;
+#endif
     VIR_DEBUG("flags=0x%x", flags);
 
+#ifdef WITH_HAM_MIGRATE
     virCheckFlags(VIR_DOMAIN_ABORT_JOB_POSTCOPY |
                   VIR_DOMAIN_ABORT_JOB_HAM, -1);
+#else
+    virCheckFlags(VIR_DOMAIN_ABORT_JOB_POSTCOPY, -1);
+#endif
 
     if (!(vm = qemuDomainObjFromDomain(dom)))
         goto cleanup;
@@ -12229,9 +12238,10 @@ qemuDomainAbortJobFlags(virDomainPtr dom,
         goto endjob;
 
     priv = vm->privateData;
-
+#ifdef WITH_HAM_MIGRATE
     isHam = flags & VIR_DOMAIN_ABORT_JOB_HAM &&
             vm->job->asyncJob == VIR_ASYNC_JOB_MIGRATION_OUT;
+#endif
 
     if (flags & VIR_DOMAIN_ABORT_JOB_POSTCOPY &&
         (vm->job->asyncJob != VIR_ASYNC_JOB_MIGRATION_OUT ||
@@ -12298,9 +12308,10 @@ qemuDomainAbortJobFlags(virDomainPtr dom,
  endjob:
     virDomainObjEndJob(vm);
 
+#ifdef WITH_HAM_MIGRATE
     if (isHam && ret == 0)
         ret = qemuHamWaitForCancelled(vm);
-
+#endif
  cleanup:
     virDomainObjEndAPI(&vm);
     return ret;
@@ -13468,35 +13479,6 @@ qemuDomainQemuMonitorCommand(virDomainPtr domain,
 }
 
 
-static int
-qemuDomainQemuMonitorCommandAsync(virDomainPtr domain,
-                                  const char *cmd,
-                                  char **result,
-                                  int asyncJob)
-{
-    virQEMUDriver *driver = domain->conn->privateData;
-    virDomainObj *vm = NULL;
-    int ret = -1;
-
-    if (!(vm = qemuDomainObjFromDomain(domain)))
-        goto cleanup;
-
-    if (virDomainQemuMonitorCommandAsyncEnsureACL(domain->conn, vm->def) < 0)
-        goto cleanup;
-
-    if (virDomainObjCheckActive(vm) < 0)
-        goto cleanup;
-
-    qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_MONITOR, NULL);
-
-    ret = qemuDomainSendQemuMonitorCommandAsync(vm, cmd, result, asyncJob);
-
- cleanup:
-    virDomainObjEndAPI(&vm);
-    return ret;
-}
-
-
 static int
 qemuDomainOpenConsole(virDomainPtr dom,
                       const char *dev_name,
@@ -20366,7 +20348,6 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
     .domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
     .domainQemuMonitorCommandWithFiles = qemuDomainQemuMonitorCommandWithFiles, /* 8.2.0 */
-    .domainQemuMonitorCommandAsync = qemuDomainQemuMonitorCommandAsync, /* 9.10.0 */
     .domainQemuAttach = NULL, /* 0.9.4 - 5.5.0 */
     .domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
     .connectDomainQemuMonitorEventRegister = qemuConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
diff --git a/src/qemu/qemu_ham.c b/src/qemu/qemu_ham.c
index c1a2004118..9964ee411f 100644
--- a/src/qemu/qemu_ham.c
+++ b/src/qemu/qemu_ham.c
@@ -53,7 +53,7 @@ qemuHamMigrationInfoFree(qemuHamMigrationInfo *hamInfo)
 }
 
 int
-qemuDomainSendQemuMonitorCommandAsync(virDomainObj *vm,
+qemuDomainSendQemuMonitorCommand(virDomainObj *vm,
                                       const char *cmd,
                                       char **result,
                                       virDomainAsyncJob asyncJob)
@@ -100,10 +100,10 @@ qemuHamSendQemuMonitorCommand(virDomainObj *vm,
     }
 
     if (vm)
-        ret = qemuDomainSendQemuMonitorCommandAsync(vm, monitorCmd, &result, asyncJob);
+        ret = qemuDomainSendQemuMonitorCommand(vm, monitorCmd, &result, asyncJob);
 
     if (domain)
-        ret = domain->conn->driver->domainQemuMonitorCommandAsync(domain, monitorCmd, &result, asyncJob);
+        ret = domain->conn->driver->domainQemuMonitorCommand(domain, monitorCmd, &result, 0);
 
     if (ret < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/src/qemu/qemu_ham.h b/src/qemu/qemu_ham.h
index d521fd280b..415f1cde3f 100644
--- a/src/qemu/qemu_ham.h
+++ b/src/qemu/qemu_ham.h
@@ -23,7 +23,7 @@ struct _qemuHamMigrationInfo {
 void qemuHamMigrationInfoFree(qemuHamMigrationInfo *hamInfo);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuHamMigrationInfo, qemuHamMigrationInfoFree);
 
-int qemuDomainSendQemuMonitorCommandAsync(virDomainObj *vm,
+int qemuDomainSendQemuMonitorCommand(virDomainObj *vm,
                                           const char *cmd,
                                           char **result,
                                           virDomainAsyncJob asyncJob);
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 680524bf8a..e0cb195440 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -39,7 +39,10 @@
 #include "qemu_slirp.h"
 #include "qemu_block.h"
 #include "qemu_tpm.h"
+#ifdef WITH_HAM_MIGRATE
 #include "qemu_ham.h"
+#include "virham.h"
+#endif
 
 #include "domain_audit.h"
 #include "virlog.h"
@@ -59,7 +62,6 @@
 #include "virprocess.h"
 #include "virdomainsnapshotobjlist.h"
 #include "virutil.h"
-#include "virham.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -115,6 +117,11 @@ qemuMigrationJobStart(virDomainObj *vm,
     if (job == VIR_ASYNC_JOB_MIGRATION_IN) {
         op = VIR_DOMAIN_JOB_OPERATION_MIGRATION_IN;
         mask = VIR_JOB_NONE;
+#ifdef WITH_HAM_MIGRATE
+        if (apiFlags & VIR_MIGRATE_LDST) {
+            mask = JOB_MASK(VIR_JOB_QUERY);
+        }
+#endif
     } else {
         op = VIR_DOMAIN_JOB_OPERATION_MIGRATION_OUT;
         mask = VIR_JOB_DEFAULT_MASK |
@@ -5535,7 +5542,9 @@ qemuMigrationSrcPerformPeer2Peer3(virQEMUDriver *driver,
     int maxparams = 0;
     size_t i;
     bool offline = !!(flags & VIR_MIGRATE_OFFLINE);
+#ifdef WITH_HAM_MIGRATE
     g_autoptr(qemuHamMigrationInfo) hamInfo = NULL;
+#endif
 
     VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, dconnuri=%s, vm=%p, xmlin=%s, "
               "dname=%s, uri=%s, graphicsuri=%s, listenAddress=%s, "
@@ -5682,6 +5691,7 @@ qemuMigrationSrcPerformPeer2Peer3(virQEMUDriver *driver,
         goto finish;
     }
 
+#ifdef WITH_HAM_MIGRATE
     if (flags & VIR_MIGRATE_LDST) {
         VIR_INFO("Prepare for ham migration");
         hamInfo = g_new0(qemuHamMigrationInfo, 1);
@@ -5694,6 +5704,7 @@ qemuMigrationSrcPerformPeer2Peer3(virQEMUDriver *driver,
             goto finish;
         }
     }
+#endif
 
     /* Perform the migration.  The driver isn't supposed to return
      * until the migration is complete. The src VM should remain
@@ -5852,6 +5863,7 @@ qemuMigrationSrcPerformPeer2Peer3(virQEMUDriver *driver,
         ret = -1;
     }
 
+#ifdef WITH_HAM_MIGRATE
     if ((flags & VIR_MIGRATE_LDST) && hamInfo && hamInfo->name) {
         VIR_INFO("Cleanup for ham migration");
         if (ret < 0) {
@@ -5864,6 +5876,7 @@ qemuMigrationSrcPerformPeer2Peer3(virQEMUDriver *driver,
             qemuHamSendClearReq(hamInfo, VIR_HAM_CLEAR_MIGRATE_SUCCESS);
         }
     }
+#endif
 
     virObjectUnref(st);
 
@@ -6622,12 +6635,14 @@ qemuMigrationDstFinishFresh(virQEMUDriver *driver,
             return -1;
     }
 
+#ifdef WITH_HAM_MIGRATE
     if ((flags & VIR_MIGRATE_LDST) && qemuHamModifyPgtable(vm) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("failed to modify page table for ham migration"));
         if (v3proto)
             return -1;
     }
+#endif
 
     if (vm->job->current->status == VIR_DOMAIN_JOB_STATUS_POSTCOPY)
         *inPostCopy = true;
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index 393dee51bc..7c2b193f48 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -40,7 +40,7 @@
  */
 
 /* All supported qemu migration flags.  */
-#define QEMU_MIGRATION_FLAGS \
+#define QEMU_MIGRATION_BASE_FLAGS \
     (VIR_MIGRATE_LIVE | \
      VIR_MIGRATE_PEER2PEER | \
      VIR_MIGRATE_TUNNELLED | \
@@ -64,9 +64,14 @@
      VIR_MIGRATE_ZEROCOPY | \
      VIR_MIGRATE_RETURNPATH | \
      VIR_MIGRATE_ONECOPY | \
-     VIR_MIGRATE_LDST | \
      0)
 
+#ifdef WITH_HAM_MIGRATE
+#define QEMU_MIGRATION_FLAGS (QEMU_MIGRATION_BASE_FLAGS | VIR_MIGRATE_LDST)
+#else
+#define QEMU_MIGRATION_FLAGS QEMU_MIGRATION_BASE_FLAGS
+#endif
+
 /* All supported migration parameters and their types. */
 #define QEMU_MIGRATION_PARAMETERS \
     VIR_MIGRATE_PARAM_URI,              VIR_TYPED_PARAM_STRING, \
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
index 600ffeb3dd..4a39680919 100644
--- a/src/qemu/qemu_migration_params.c
+++ b/src/qemu/qemu_migration_params.c
@@ -100,7 +100,9 @@ VIR_ENUM_IMPL(qemuMigrationCapability,
               "return-path",
               "zero-copy-send",
               "onecopy",
+#ifdef WITH_HAM_MIGRATE
               "ldst",
+#endif
 );
 
 
@@ -203,10 +205,12 @@ static const qemuMigrationParamsFlagMapItem qemuMigrationParamsFlagMap[] = {
      QEMU_MIGRATION_CAP_ONECOPY,
      QEMU_MIGRATION_SOURCE},
 
+#ifdef WITH_HAM_MIGRATE
      {QEMU_MIGRATION_FLAG_REQUIRED,
      VIR_MIGRATE_LDST,
      QEMU_MIGRATION_CAP_LDST,
      QEMU_MIGRATION_SOURCE | QEMU_MIGRATION_DESTINATION},
+#endif
 };
 
 /* Translation from VIR_MIGRATE_PARAM_* typed parameters to
diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h
index ada417d15b..88e8cc5784 100644
--- a/src/qemu/qemu_migration_params.h
+++ b/src/qemu/qemu_migration_params.h
@@ -41,8 +41,10 @@ typedef enum {
     QEMU_MIGRATION_CAP_RETURN_PATH,
     QEMU_MIGRATION_CAP_ZERO_COPY_SEND,
     QEMU_MIGRATION_CAP_ONECOPY,
-    QEMU_MIGRATION_CAP_LDST,
 
+#ifdef WITH_HAM_MIGRATE
+    QEMU_MIGRATION_CAP_LDST,
+#endif
     QEMU_MIGRATION_CAP_LAST
 } qemuMigrationCapability;
 VIR_ENUM_DECL(qemuMigrationCapability);
diff --git a/src/qemu_protocol-structs b/src/qemu_protocol-structs
index daed2ced4a..ea0854385f 100644
--- a/src/qemu_protocol-structs
+++ b/src/qemu_protocol-structs
@@ -55,14 +55,6 @@ struct qemu_domain_monitor_command_with_files_args {
 struct qemu_domain_monitor_command_with_files_ret {
         remote_nonnull_string      result;
 };
-struct qemu_domain_monitor_command_async_args {
-        remote_nonnull_domain      dom;
-        remote_nonnull_string      cmd;
-        int                        asyncJob;
-};
-struct qemu_domain_monitor_command_async_ret {
-        remote_nonnull_string      result;
-};
 enum qemu_procedure {
         QEMU_PROC_DOMAIN_MONITOR_COMMAND = 1,
         QEMU_PROC_DOMAIN_ATTACH = 2,
@@ -71,5 +63,4 @@ enum qemu_procedure {
         QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER = 5,
         QEMU_PROC_DOMAIN_MONITOR_EVENT = 6,
         QEMU_PROC_DOMAIN_MONITOR_COMMAND_WITH_FILES       = 7,
-        QEMU_PROC_DOMAIN_MONITOR_COMMAND_ASYNC            = 8,
 };
diff --git a/src/remote/qemu_protocol.x b/src/remote/qemu_protocol.x
index 02788d6bc3..c7f3abfcbf 100644
--- a/src/remote/qemu_protocol.x
+++ b/src/remote/qemu_protocol.x
@@ -89,16 +89,6 @@ struct qemu_domain_monitor_command_with_files_ret {
     remote_nonnull_string result;
 };
 
-struct qemu_domain_monitor_command_async_args {
-    remote_nonnull_domain dom;
-    remote_nonnull_string cmd;
-    int asyncJob;
-};
-
-struct qemu_domain_monitor_command_async_ret {
-    remote_nonnull_string result;
-};
-
 
 /* Define the program number, protocol version and procedure numbers here. */
 const QEMU_PROGRAM = 0x20008087;
@@ -179,12 +169,5 @@ enum qemu_procedure {
      * @priority: low
      * @acl: domain:write
      */
-    QEMU_PROC_DOMAIN_MONITOR_COMMAND_WITH_FILES = 7,
-
-    /**
-     * @generate: none
-     * @priority: low
-     * @acl: domain:write
-     */
-    QEMU_PROC_DOMAIN_MONITOR_COMMAND_ASYNC = 8
+    QEMU_PROC_DOMAIN_MONITOR_COMMAND_WITH_FILES = 7
 };
diff --git a/src/remote/remote_daemon.c b/src/remote/remote_daemon.c
index cdf1df3003..8a9ae4a6e7 100644
--- a/src/remote/remote_daemon.c
+++ b/src/remote/remote_daemon.c
@@ -55,7 +55,9 @@
 #include "virsystemd.h"
 #include "virhostuptime.h"
 #include "virdaemon.h"
+#ifdef WITH_HAM_MIGRATE
 #include "virham.h"
+#endif
 
 #include "driver.h"
 
@@ -947,8 +949,9 @@ int main(int argc, char **argv) {
 
     daemonSetupNetDevOpenvswitch(config);
 
+#ifdef WITH_HAM_MIGRATE
     virHamSetupTimeOut(config->vir_ham_cancelled_timeout, (uint16_t)config->vir_ham_rack_ipc_timeout);
-
+#endif
     if (daemonSetupAccessManager(config) < 0) {
         VIR_ERROR(_("Can't initialize access manager"));
         exit(EXIT_FAILURE);
@@ -1195,9 +1198,10 @@ int main(int argc, char **argv) {
         ret = VIR_DAEMON_ERR_INIT;
         goto cleanup;
     }
-
+#ifdef WITH_HAM_MIGRATE
     VIR_DEBUG("Clear all borrowed numa nodes of ham migration");
     virHamClearAll(virGetHostname());
+#endif
 
 #if defined(__linux__) && defined(NETLINK_ROUTE)
     /* Register the netlink event service for NETLINK_ROUTE */
diff --git a/src/remote/remote_daemon_config.c b/src/remote/remote_daemon_config.c
index b7b5ba60fe..fe5724828b 100644
--- a/src/remote/remote_daemon_config.c
+++ b/src/remote/remote_daemon_config.c
@@ -162,9 +162,10 @@ daemonConfigNew(bool privileged G_GNUC_UNUSED)
 
     data->ovs_timeout = VIR_NETDEV_OVS_DEFAULT_TIMEOUT;
 
+#ifdef WITH_HAM_MIGRATE
     data->vir_ham_cancelled_timeout = 1;
     data->vir_ham_rack_ipc_timeout =  3;
-
+#endif
     return data;
 }
 
@@ -383,11 +384,12 @@ daemonConfigLoadOptions(struct daemonConfig *data,
     if (virConfGetValueUInt(conf, "ovs_timeout", &data->ovs_timeout) < 0)
         return -1;
 
+#ifdef WITH_HAM_MIGRATE
     if (virConfGetValueUInt(conf, "vir_ham_rack_ipc_timeout", &data->vir_ham_rack_ipc_timeout) < 0)
         return -1;
     if (virConfGetValueULLong(conf, "vir_ham_cancelled_timeout", &data->vir_ham_cancelled_timeout) < 0)
         return -1;
-
+#endif
     return 0;
 }
 
diff --git a/src/remote/remote_daemon_config.h b/src/remote/remote_daemon_config.h
index c8f7abcf03..22d1e016de 100644
--- a/src/remote/remote_daemon_config.h
+++ b/src/remote/remote_daemon_config.h
@@ -96,9 +96,10 @@ struct daemonConfig {
     unsigned int admin_keepalive_count;
 
     unsigned int ovs_timeout;
-
+#ifdef WITH_HAM_MIGRATE
     unsigned long long vir_ham_cancelled_timeout;
     unsigned int vir_ham_rack_ipc_timeout;
+#endif
 };
 
 
diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
index df6b01f6e4..10f343843a 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -4739,38 +4739,6 @@ qemuDispatchDomainMonitorCommandWithFiles(virNetServer *server G_GNUC_UNUSED,
 }
 
 
-static int
-qemuDispatchDomainMonitorCommandAsync(virNetServer *server G_GNUC_UNUSED,
-                                      virNetServerClient *client,
-                                      virNetMessage *msg G_GNUC_UNUSED,
-                                      struct virNetMessageError *rerr,
-                                      qemu_domain_monitor_command_async_args *args,
-                                      qemu_domain_monitor_command_async_ret *ret)
-{
-    virDomainPtr dom = NULL;
-    int rv = -1;
-    virConnectPtr conn = remoteGetHypervisorConn(client);
-
-    if (!conn)
-        goto cleanup;
-
-    if (!(dom = get_nonnull_domain(conn, args->dom)))
-        goto cleanup;
-
-    if (virDomainQemuMonitorCommandAsync(dom, args->cmd, &ret->result,
-                                         args->asyncJob) < 0)
-        goto cleanup;
-
-    rv = 0;
-
- cleanup:
-    if (rv < 0)
-        virNetMessageSaveError(rerr);
-    virObjectUnref(dom);
-    return rv;
-}
-
-
 static int
 remoteDispatchDomainMigrateBegin3(virNetServer *server G_GNUC_UNUSED,
                                   virNetServerClient *client,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index ab66af5bdb..82d4c968ea 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -5553,30 +5553,6 @@ remoteDomainQemuMonitorCommandWithFiles(virDomainPtr domain,
 }
 
 
-static int
-remoteDomainQemuMonitorCommandAsync(virDomainPtr domain, const char *cmd,
-                                    char **result, int asyncJob)
-{
-    qemu_domain_monitor_command_async_args args;
-    g_auto(qemu_domain_monitor_command_async_ret) ret = {0};
-    struct private_data *priv = domain->conn->privateData;
-    VIR_LOCK_GUARD lock = remoteDriverLock(priv);
-
-    make_nonnull_domain(&args.dom, domain);
-    args.cmd = (char *)cmd;
-    args.asyncJob = asyncJob;
-
-    if (call(domain->conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_DOMAIN_MONITOR_COMMAND_ASYNC,
-             (xdrproc_t) xdr_qemu_domain_monitor_command_async_args, (char *) &args,
-             (xdrproc_t) xdr_qemu_domain_monitor_command_async_ret, (char *) &ret) == -1)
-        return -1;
-
-    *result = g_steal_pointer(&ret.result);
-
-    return 0;
-}
-
-
 static char *
 remoteDomainMigrateBegin3(virDomainPtr domain,
                           const char *xmlin,
@@ -7810,7 +7786,6 @@ static virHypervisorDriver hypervisor_driver = {
     .domainSnapshotDelete = remoteDomainSnapshotDelete, /* 0.8.0 */
     .domainQemuMonitorCommand = remoteDomainQemuMonitorCommand, /* 0.8.3 */
     .domainQemuMonitorCommandWithFiles = remoteDomainQemuMonitorCommandWithFiles, /* 8.2.0 */
-    .domainQemuMonitorCommandAsync = remoteDomainQemuMonitorCommandAsync, /* 9.10.0 */
     .domainQemuAttach = remoteDomainQemuAttach, /* 0.9.4 */
     .domainQemuAgentCommand = remoteDomainQemuAgentCommand, /* 0.10.0 */
     .connectDomainQemuMonitorEventRegister = remoteConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
diff --git a/src/util/meson.build b/src/util/meson.build
index 9fa767f40e..a4725d32b1 100644
--- a/src/util/meson.build
+++ b/src/util/meson.build
@@ -111,9 +111,12 @@ util_sources = [
   'virvsock.c',
   'virxml.c',
   'virub.c',
-  'virham.c',
 ]
 
+if conf.has('WITH_HAM_MIGRATE')
+  util_sources += 'virham.c'
+endif
+
 util_public_sources = files(
   'virerror.c',
   'virevent.c',
diff --git a/src/util/virham.c b/src/util/virham.c
index 4f149794e9..a6a0977204 100644
--- a/src/util/virham.c
+++ b/src/util/virham.c
@@ -52,6 +52,7 @@ struct _virHamRackIpcClient {
     virHamRackIpcClientStart start;
     virHamRackIpcSyncSend syncSend;
     virHamRackIpcAsyncSend asyncSend;
+    virHamRackIpcCallbackDef *callback;
 };
 
 static virHamRackIpcClient *rackIpcClient;
@@ -85,6 +86,7 @@ virHamRackIpcInitialize(void)
     }
 
     rackIpcClient = g_new0(virHamRackIpcClient, 1);
+    rackIpcClient->callback = g_new0(virHamRackIpcCallbackDef, 1);
 
     if (!(rackIpcClient->start = dlsym(handle, "RackStartIpcClientWithTimeout"))) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -182,7 +184,7 @@ virHamGetClearReqInit(virHamClearType type, const char *hostname)
 }
 
 static int
-virHamRackIpcAsyncSendAndRecv(const char *req, virHamRackIpcCallbackDef *callback)
+virHamRackIpcAsyncSendAndRecv(const char *req)
 {
     g_autoptr(virHamRackIpcData) sendData = g_new0(virHamRackIpcData, 1);
     int code;
@@ -197,7 +199,7 @@ virHamRackIpcAsyncSendAndRecv(const char *req, virHamRackIpcCallbackDef *callbac
     sendData->buffer = g_malloc0(sendData->length);
     memcpy(sendData->buffer, req, sendData->length);
 
-    if ((code = rackIpcClient->asyncSend(sendData, callback)) != 0) {
+    if ((code = rackIpcClient->asyncSend(sendData, rackIpcClient->callback)) != 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("failed to send request to RackAgentIpcServer with code %1$d"), code);
         return -1;
@@ -210,7 +212,6 @@ void
 virHamClearAll(const char *hostname)
 {
     g_autofree char *req = NULL;
-    virHamRackIpcCallbackDef *callback = g_new0(virHamRackIpcCallbackDef, 1);
 
     if (!(req = virHamGetClearReqInit(VIR_HAM_CLEAR_ALL, hostname))) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -219,7 +220,7 @@ virHamClearAll(const char *hostname)
     }
     VIR_INFO("Ham migration clear all borrowed numa nodes request: %s", NULLSTR(req));
 
-    if (virHamRackIpcAsyncSendAndRecv(req, callback) < 0)
+    if (virHamRackIpcAsyncSendAndRecv(req) < 0)
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("failed to clear all borrowed numa nodes"));
 }
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index e4b751289c..1b5f650386 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -6527,10 +6527,12 @@ static const vshCmdOptDef opts_domjobabort[] = {
      .type = VSH_OT_BOOL,
      .help = N_("interrupt post-copy migration")
     },
+#ifdef WITH_HAM_MIGRATE
     {.name = "ham",
      .type = VSH_OT_BOOL,
      .help = N_("interrupt ham migration")
     },
+#endif
     {.name = NULL}
 };
 
@@ -6547,9 +6549,10 @@ cmdDomjobabort(vshControl *ctl, const vshCmd *cmd)
     if (vshCommandOptBool(cmd, "postcopy"))
         flags |= VIR_DOMAIN_ABORT_JOB_POSTCOPY;
 
+#ifdef WITH_HAM_MIGRATE
     if (vshCommandOptBool(cmd, "ham"))
         flags |= VIR_DOMAIN_ABORT_JOB_HAM;
-
+#endif
     if (flags == 0)
         rc = virDomainAbortJob(dom);
     else
@@ -11144,10 +11147,12 @@ static const vshCmdOptDef opts_migrate[] = {
      .type = VSH_OT_BOOL,
      .help = N_("enable one-copy migration")
     },
+#ifdef WITH_HAM_MIGRATE
     {.name = "ldst",
      .type = VSH_OT_BOOL,
      .help = N_("enable ham migration")
     },
+#endif
     {.name = NULL}
 };
 
@@ -11199,7 +11204,9 @@ doMigrate(void *opaque)
         { "suspend", VIR_MIGRATE_PAUSED },
         { "return-path", VIR_MIGRATE_RETURNPATH },
         { "onecopy", VIR_MIGRATE_ONECOPY },
+#ifdef WITH_HAM_MIGRATE
         { "ldst", VIR_MIGRATE_LDST },
+#endif
     };
 
 #ifndef WIN32
-- 
2.51.0.windows.1