Add a new internal qemuCPUModelCompatResult enum to qemu_process.h with values for IDENTICAL, SUBSET, SUPERSET, INCOMPATIBLE, and ERROR, and a new shared helper qemuProcessCPUModelComparison() in qemu_process.c that wraps the QMP probe and maps the result string to the enum.
Refactor qemuConnectCPUModelComparison() in qemu_driver.c to delegate to the new helper, eliminating the duplicated QMP probe boilerplate. qemuConnectCPUModelComparison() maps the internal enum back to virCPUCompareResult, treating SUBSET as VIR_CPU_COMPARE_INCOMPATIBLE to preserve existing public API behaviour. Signed-off-by: Rorie Reyes <[email protected]> --- src/qemu/qemu_driver.c | 20 +++++++---------- src/qemu/qemu_process.c | 50 +++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_process.h | 21 +++++++++++++++++ 3 files changed, 79 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7332ec0256..56a254f0ec 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -12127,25 +12127,21 @@ qemuConnectCPUModelComparison(virQEMUCaps *qemuCaps, virCPUDef *cpu_b, bool failIncompatible) { - g_autoptr(qemuProcessQMP) proc = NULL; - g_autofree char *result = NULL; - - if (!(proc = qemuProcessQMPNew(virQEMUCapsGetBinary(qemuCaps), - libDir, runUid, runGid, false))) - return VIR_CPU_COMPARE_ERROR; - - if (qemuProcessQMPStart(proc) < 0) - return VIR_CPU_COMPARE_ERROR; + qemuCPUModelCompatResult cmp = + qemuProcessCPUModelComparison(qemuCaps, libDir, runUid, runGid, + cpu_a, cpu_b, NULL); - if (qemuMonitorGetCPUModelComparison(proc->mon, cpu_a, cpu_b, &result, NULL) < 0) + if (cmp == QEMU_CPU_COMPAT_ERROR) return VIR_CPU_COMPARE_ERROR; - if (STREQ(result, "identical")) + if (cmp == QEMU_CPU_COMPAT_IDENTICAL) return VIR_CPU_COMPARE_IDENTICAL; - if (STREQ(result, "superset")) + if (cmp == QEMU_CPU_COMPAT_SUPERSET) return VIR_CPU_COMPARE_SUPERSET; + /* cpu_a is the host. SUBSET means the host lacks features the guest + * needs — treat as incompatible, same as INCOMPATIBLE. */ if (failIncompatible) { virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL); return VIR_CPU_COMPARE_ERROR; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 57a3ed3720..90b8acc6c2 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -113,6 +113,14 @@ VIR_LOG_INIT("qemu.qemu_process"); +VIR_ENUM_IMPL(qemuCPUModelCompatResult, + QEMU_CPU_COMPAT_LAST, + "incompatible", + "identical", + "superset", + "subset", +); + /** * qemuProcessRemoveDomainStatus * @@ -10583,6 +10591,48 @@ qemuProcessQMPStart(qemuProcessQMP *proc) } +qemuCPUModelCompatResult +qemuProcessCPUModelComparison(virQEMUCaps *qemuCaps, + const char *libDir, + uid_t runUid, + gid_t runGid, + virCPUDef *cpu_a, + virCPUDef *cpu_b, + char ***responsibleProps) +{ + g_autoptr(qemuProcessQMP) proc = NULL; + g_autofree char *result = NULL; + qemuCPUModelCompatResult compatResult; + + if (!(proc = qemuProcessQMPNew(virQEMUCapsGetBinary(qemuCaps), + libDir, runUid, runGid, false))) + return QEMU_CPU_COMPAT_ERROR; + + if (qemuProcessQMPStart(proc) < 0) + return QEMU_CPU_COMPAT_ERROR; + + if (qemuMonitorGetCPUModelComparison(proc->mon, cpu_a, cpu_b, &result, + responsibleProps) < 0) + return QEMU_CPU_COMPAT_ERROR; + + compatResult = qemuCPUModelCompatResultTypeFromString(result); + + switch (compatResult) { + case QEMU_CPU_COMPAT_INCOMPATIBLE: + case QEMU_CPU_COMPAT_IDENTICAL: + case QEMU_CPU_COMPAT_SUPERSET: + case QEMU_CPU_COMPAT_SUBSET: + return compatResult; + case QEMU_CPU_COMPAT_ERROR: + case QEMU_CPU_COMPAT_LAST: + default: + VIR_WARN("unknown query-cpu-model-comparison result '%s', treating as incompatible", + result); + return QEMU_CPU_COMPAT_INCOMPATIBLE; + } +} + + void qemuProcessHandleNbdkitExit(qemuNbdkitProcess *nbdkit, virDomainObj *vm) diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index 5d8f1f89d5..059966e0a7 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -258,6 +258,27 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuProcessQMP, qemuProcessQMPFree); int qemuProcessQMPStart(qemuProcessQMP *proc); +typedef enum { + QEMU_CPU_COMPAT_ERROR = -1, + QEMU_CPU_COMPAT_INCOMPATIBLE = 0, + QEMU_CPU_COMPAT_IDENTICAL = 1, + QEMU_CPU_COMPAT_SUPERSET = 2, + QEMU_CPU_COMPAT_SUBSET = 3, + + QEMU_CPU_COMPAT_LAST, +} qemuCPUModelCompatResult; + +VIR_ENUM_DECL(qemuCPUModelCompatResult); + +qemuCPUModelCompatResult +qemuProcessCPUModelComparison(virQEMUCaps *qemuCaps, + const char *libDir, + uid_t runUid, + gid_t runGid, + virCPUDef *cpu_a, + virCPUDef *cpu_b, + char ***responsibleProps); + void qemuProcessCleanupMigrationJob(virQEMUDriver *driver, virDomainObj *vm); -- 2.48.1
