diff --git a/src/vmspawn/vmspawn-qmp.c b/src/vmspawn/vmspawn-qmp.c index 7c54ba968a..0ccfbfb1e2 100644 --- a/src/vmspawn/vmspawn-qmp.c +++ b/src/vmspawn/vmspawn-qmp.c @@ -24,11 +24,69 @@ #include "vmspawn-qmp.h" #include "vmspawn-util.h" +/* Pending job continuation — called when a QMP background job reaches "concluded" state. + * Used by blockdev-create to chain remaining drive setup after the job completes. */ +typedef int (*pending_job_callback_t)(QmpClient *qmp, void *userdata); +typedef void (*pending_job_free_t)(void *userdata); + +typedef struct PendingJob { + pending_job_callback_t on_concluded; + pending_job_free_t free_userdata; + void *userdata; +} PendingJob; + +static PendingJob* pending_job_free(PendingJob *j) { + if (!j) + return NULL; + if (j->free_userdata) + j->free_userdata(j->userdata); + return mfree(j); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(PendingJob *, pending_job_free); + DEFINE_PRIVATE_HASH_OPS_FULL( pending_job_hash_ops, char, string_hash_func, string_compare_func, free, PendingJob, pending_job_free); +static int vmspawn_qmp_bridge_register_job( + VmspawnQmpBridge *b, + const char *job_id, + pending_job_callback_t on_concluded, + void *userdata, + pending_job_free_t free_userdata) { + + _cleanup_free_ PendingJob *job = NULL; + _cleanup_free_ char *id = NULL; + int r; + + assert(b); + assert(job_id); + + id = strdup(job_id); + if (!id) + return -ENOMEM; + + job = new(PendingJob, 1); + if (!job) + return -ENOMEM; + + *job = (PendingJob) { + .on_concluded = on_concluded, + .free_userdata = free_userdata, + .userdata = userdata, + }; + + r = hashmap_ensure_put(&b->pending_jobs, &pending_job_hash_ops, id, job); + if (r < 0) + return r; + + TAKE_PTR(id); + TAKE_PTR(job); + return 0; +} + DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( block_devices_hash_ops, char, string_hash_func, string_compare_func, @@ -1685,14 +1743,6 @@ int vmspawn_qmp_setup_drives(VmspawnQmpBridge *bridge, DriveInfos *drives) { return 0; } -PendingJob* pending_job_free(PendingJob *j) { - if (!j) - return NULL; - if (j->free_userdata) - j->free_userdata(j->userdata); - return mfree(j); -} - VmspawnQmpBridge* vmspawn_qmp_bridge_free(VmspawnQmpBridge *b) { if (!b) return NULL; @@ -1710,43 +1760,6 @@ VmspawnQmpBridge* vmspawn_qmp_bridge_free(VmspawnQmpBridge *b) { return mfree(b); } -int vmspawn_qmp_bridge_register_job( - VmspawnQmpBridge *b, - const char *job_id, - pending_job_callback_t on_concluded, - void *userdata, - pending_job_free_t free_userdata) { - - _cleanup_free_ PendingJob *job = NULL; - _cleanup_free_ char *id = NULL; - int r; - - assert(b); - assert(job_id); - - id = strdup(job_id); - if (!id) - return -ENOMEM; - - job = new(PendingJob, 1); - if (!job) - return -ENOMEM; - - *job = (PendingJob) { - .on_concluded = on_concluded, - .free_userdata = free_userdata, - .userdata = userdata, - }; - - r = hashmap_ensure_put(&b->pending_jobs, &pending_job_hash_ops, id, job); - if (r < 0) - return r; - - TAKE_PTR(id); - TAKE_PTR(job); - return 0; -} - QmpClient* vmspawn_qmp_bridge_get_qmp(VmspawnQmpBridge *b) { assert(b); return b->qmp; diff --git a/src/vmspawn/vmspawn-qmp.h b/src/vmspawn/vmspawn-qmp.h index 5eedc5248d..df0e018d77 100644 --- a/src/vmspawn/vmspawn-qmp.h +++ b/src/vmspawn/vmspawn-qmp.h @@ -8,20 +8,6 @@ #define VMSPAWN_PCIE_HOTPLUG_SPARES 10 -/* Pending job continuation — called when a QMP background job reaches "concluded" state. - * Used by blockdev-create to chain remaining drive setup after the job completes. */ -typedef int (*pending_job_callback_t)(QmpClient *qmp, void *userdata); -typedef void (*pending_job_free_t)(void *userdata); - -typedef struct PendingJob { - pending_job_callback_t on_concluded; - pending_job_free_t free_userdata; - void *userdata; -} PendingJob; - -PendingJob* pending_job_free(PendingJob *j); -DEFINE_TRIVIAL_CLEANUP_FUNC(PendingJob *, pending_job_free); - typedef enum VmspawnQmpFeatureFlags { VMSPAWN_QMP_FEATURE_IO_URING = 1u << 0, VMSPAWN_QMP_FEATURE_DISCARD_NO_UNREF = 1u << 1, @@ -61,13 +47,6 @@ int vmspawn_qmp_probe_features(VmspawnQmpBridge *bridge); /* Phase 3: Resume vCPUs. All commands are async — responses arrive during sd_event_loop(). */ int vmspawn_qmp_start(VmspawnQmpBridge *bridge); -int vmspawn_qmp_bridge_register_job( - VmspawnQmpBridge *b, - const char *job_id, - pending_job_callback_t on_concluded, - void *userdata, - pending_job_free_t free_userdata); - typedef enum QmpDriveFlags { QMP_DRIVE_BLOCK_DEVICE = 1u << 0, QMP_DRIVE_READ_ONLY = 1u << 1,