From e4c45cae510bfc7b45db801094b6646de4f09494 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Sun, 4 Oct 2026 07:27:51 +0000 Subject: [PATCH] vmspawn: factor out the synchronous QMP pump The upcoming boot-time device setup will need the same synchronous driving of the QMP client before resuming the VM. Move the loop into a helper, and generalize the error messages. Signed-off-by: Martin Pitt (cherry picked from commit 73833bdddfd4e8a1aa003516a8eda53515c9110f) --- src/vmspawn/vmspawn-qmp.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/vmspawn/vmspawn-qmp.c b/src/vmspawn/vmspawn-qmp.c index 3bee5ae4c1..f9e5376127 100644 --- a/src/vmspawn/vmspawn-qmp.c +++ b/src/vmspawn/vmspawn-qmp.c @@ -2007,6 +2007,28 @@ int vmspawn_qmp_init(VmspawnQmpBridge **ret, int fd, sd_event *event) { return 0; } +/* Canonical sync-on-async pump, matching varlink_call_internal(). The QMP client tracks + * outstanding replies in its own slots set; drain until it's idle. */ +static int vmspawn_qmp_bridge_drain(VmspawnQmpBridge *bridge) { + int r; + + assert(bridge); + + while (!qmp_client_is_idle(bridge->qmp)) { + r = qmp_client_process(bridge->qmp); + if (r < 0) + return log_error_errno(r, "Failed to process QMP messages: %m"); + if (r > 0) + continue; + + r = qmp_client_wait(bridge->qmp, USEC_INFINITY); + if (r < 0) + return log_error_errno(r, "Failed to wait for QMP messages: %m"); + } + + return 0; +} + int vmspawn_qmp_probe_features(VmspawnQmpBridge *bridge) { int r; @@ -2022,19 +2044,9 @@ int vmspawn_qmp_probe_features(VmspawnQmpBridge *bridge) { if (r < 0) return log_error_errno(r, "Failed to issue schema probe: %m"); - /* Canonical sync-on-async pump, matching varlink_call_internal(). The QMP client tracks - * outstanding replies in its own slots set; drain until it's idle. */ - while (!qmp_client_is_idle(bridge->qmp)) { - r = qmp_client_process(bridge->qmp); - if (r < 0) - return log_error_errno(r, "QMP probe pump failed: %m"); - if (r > 0) - continue; - - r = qmp_client_wait(bridge->qmp, USEC_INFINITY); - if (r < 0) - return log_error_errno(r, "QMP probe wait failed: %m"); - } + r = vmspawn_qmp_bridge_drain(bridge); + if (r < 0) + return r; /* If fail_pending() drained the slots (transport dropped mid-probe), features can't be * trusted and we have no QMP channel for device setup anyway. */