vmspawn: add QmpClient userdata and VmspawnQmpBridge.setup_done flag
Add qmp_client_set_userdata()/qmp_client_get_userdata() accessors mirroring the sd_varlink API, and wire up the VmspawnQmpBridge as userdata on the QmpClient so that command callbacks can retrieve it. Add a setup_done flag to VmspawnQmpBridge, set by on_cont_complete() when the VM has booted and all boot-time device setup is finished. This lets command callbacks differentiate boot-time errors (fatal — exit event loop) from runtime errors (recoverable — log and continue). Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
@@ -49,6 +49,8 @@ struct QmpClient {
|
||||
|
||||
QmpClientState state;
|
||||
sd_json_variant *current; /* most recently parsed message, pending dispatch */
|
||||
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
static void qmp_slot_hash_func(const QmpSlot *p, struct siphash *state) {
|
||||
@@ -508,6 +510,21 @@ bool qmp_client_is_disconnected(QmpClient *c) {
|
||||
return c->state == QMP_CLIENT_DISCONNECTED;
|
||||
}
|
||||
|
||||
void* qmp_client_set_userdata(QmpClient *c, void *userdata) {
|
||||
void *old;
|
||||
|
||||
assert(c);
|
||||
|
||||
old = c->userdata;
|
||||
c->userdata = userdata;
|
||||
return old;
|
||||
}
|
||||
|
||||
void* qmp_client_get_userdata(QmpClient *c) {
|
||||
assert(c);
|
||||
return c->userdata;
|
||||
}
|
||||
|
||||
/* Map our state to the transport phase used for POLLIN / salvage / timeout decisions. */
|
||||
static JsonStreamPhase qmp_client_phase(void *userdata) {
|
||||
QmpClient *c = ASSERT_PTR(userdata);
|
||||
|
||||
@@ -54,6 +54,9 @@ bool qmp_client_is_idle(QmpClient *c);
|
||||
/* True iff the connection is dead. Stable terminal state — once set, it stays set. */
|
||||
bool qmp_client_is_disconnected(QmpClient *c);
|
||||
|
||||
void* qmp_client_set_userdata(QmpClient *c, void *userdata);
|
||||
void* qmp_client_get_userdata(QmpClient *c);
|
||||
|
||||
/* Async send. Returns 0 on send (callback will fire later), negative errno on failure. If
|
||||
* ret_slot is non-NULL, returns a reference to a QmpSlot which can be used to cancel the call
|
||||
* (by unreffing it before the reply arrives). */
|
||||
|
||||
@@ -1042,6 +1042,8 @@ static int on_cont_complete(
|
||||
int error,
|
||||
void *userdata) {
|
||||
|
||||
VmspawnQmpBridge *bridge = ASSERT_PTR(qmp_client_get_userdata(client));
|
||||
|
||||
assert(client);
|
||||
|
||||
if (error < 0) {
|
||||
@@ -1049,6 +1051,8 @@ static int on_cont_complete(
|
||||
return sd_event_exit(qmp_client_get_event(client), error);
|
||||
}
|
||||
|
||||
/* VM is running — all boot-time device setup has completed. */
|
||||
bridge->setup_done = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ typedef struct VmspawnQmpBridge {
|
||||
QmpClient *qmp;
|
||||
Hashmap *pending_jobs; /* job_id (string, owned) -> PendingJob* */
|
||||
VmspawnQmpFeatureFlags features;
|
||||
bool setup_done;
|
||||
} VmspawnQmpBridge;
|
||||
|
||||
VmspawnQmpBridge* vmspawn_qmp_bridge_free(VmspawnQmpBridge *b);
|
||||
|
||||
@@ -387,6 +387,7 @@ int vmspawn_varlink_setup(
|
||||
ctx->bridge = bridge;
|
||||
qmp_client_bind_event(ctx->bridge->qmp, on_qmp_event, ctx);
|
||||
qmp_client_bind_disconnect(ctx->bridge->qmp, on_qmp_disconnect, ctx);
|
||||
qmp_client_set_userdata(ctx->bridge->qmp, ctx->bridge);
|
||||
|
||||
log_debug("Varlink control server listening on %s", listen_address);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user