mirror of
https://dev.lirent.ru/Vatrog/vm-automation-signaling.git
synced 2026-06-26 04:36:37 +03:00
vmsig: management daemon, runtime endpoint lifecycle, roster, discovery, in-tree drivers, packaging
- core: runtime attach/detach of a per-endpoint adapter trio (runtime-safe add_adapter + vmsig_core_detach_endpoint, deferred reap) - roster: VMSIG_EV_ROSTER + CAP_ROSTER, retained per-endpoint and replayed to late subscribers - discovery: inotify trigger dir, vmid/endpoint slot allocator, host probe; vmsigd daemon with config + per-uid admission - input driver and vgpu perception built in-tree; vgpu perception as a separate library - memctx: own the supplied ro_fd (closed at detach) - deb packaging: install rules, systemd unit, tmpfiles, default config
This commit is contained in:
+49
-10
@@ -68,10 +68,22 @@ vmsig_core* vmsig_core_new(vmsig_ctx* ctx) {
|
||||
|
||||
int vmsig_core_add_adapter(vmsig_core* c, const vmsig_adapter_ops* ops,
|
||||
const void* cfg, uint32_t endpoint) {
|
||||
if (!c || !ops || c->nadapters >= VMSIG_MAX_ADAPTERS) return -1;
|
||||
if (!c || !ops) return -1;
|
||||
|
||||
/* Reuse a reaped (inactive) adapter entry so runtime detach/re-attach churn does
|
||||
* not exhaust the fixed table; otherwise grow up to the ceiling. */
|
||||
int id = -1;
|
||||
for (int i = 0; i < c->nadapters; i++)
|
||||
if (!c->adapters[i].active) { id = i; break; }
|
||||
if (id < 0) {
|
||||
if (c->nadapters >= VMSIG_MAX_ADAPTERS) return -1;
|
||||
id = c->nadapters++;
|
||||
}
|
||||
core_adapter_ent* e = &c->adapters[id];
|
||||
uint16_t gen = e->gen; /* generation survives the memset below */
|
||||
|
||||
vmsig_adapter* a = ops->open(cfg, endpoint);
|
||||
if (!a) return -1;
|
||||
if (!a) return -1; /* entry stays inactive (reusable) */
|
||||
|
||||
vmsig_emit emit = { core_emit_up, core_register_memctx, core_unregister_memctx, c };
|
||||
vmsig_fd_reg reg[VMSIG_ADAPTER_FDS];
|
||||
@@ -80,23 +92,48 @@ int vmsig_core_add_adapter(vmsig_core* c, const vmsig_adapter_ops* ops,
|
||||
int n = ops->attach(a, &emit, reg, VMSIG_ADAPTER_FDS);
|
||||
if (n < 0) { ops->close(a); return -1; }
|
||||
|
||||
memset(e, 0, sizeof *e);
|
||||
e->ops = ops;
|
||||
e->a = a;
|
||||
e->endpoint = endpoint;
|
||||
e->active = 1;
|
||||
e->gen = (uint16_t)(gen + 1);
|
||||
e->nslot = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
uint32_t events = reg[i].epoll_events ? reg[i].epoll_events : (uint32_t)EPOLLIN;
|
||||
core_slot* s = core_register_fd(c, reg[i].fd, events, SLOT_ADAPTER);
|
||||
if (!s) { ops->close(a); return -1; }
|
||||
if (!s) {
|
||||
/* roll back: deregister the fds enrolled so far, then close + free the entry. */
|
||||
for (int k = 0; k < e->nslot; k++) {
|
||||
epoll_ctl(c->epfd, EPOLL_CTL_DEL, e->slots[k]->fd, NULL);
|
||||
e->slots[k]->role = SLOT_DEAD;
|
||||
}
|
||||
ops->close(a);
|
||||
e->active = 0; e->a = NULL; e->nslot = 0;
|
||||
return -1;
|
||||
}
|
||||
s->ops = ops;
|
||||
s->adapter = a;
|
||||
s->cookie = reg[i].cookie;
|
||||
if (e->nslot < VMSIG_ADAPTER_FDS) e->slots[e->nslot++] = s;
|
||||
}
|
||||
|
||||
int id = c->nadapters;
|
||||
c->adapters[c->nadapters].ops = ops;
|
||||
c->adapters[c->nadapters].a = a;
|
||||
c->adapters[c->nadapters].endpoint = endpoint;
|
||||
c->nadapters++;
|
||||
return id;
|
||||
}
|
||||
|
||||
/* Request runtime detach of every adapter on `endpoint` (deferred reap after the batch,
|
||||
* mirrors core_request_drop). The teardown itself (epoch settle, SEAM_DOWN, lease release,
|
||||
* epoll DEL, ops->close) runs in core_reap_adapters on the loop thread. */
|
||||
void vmsig_core_detach_endpoint(vmsig_core* c, uint32_t endpoint) {
|
||||
if (!c || endpoint >= 64) return;
|
||||
int any = 0;
|
||||
for (int i = 0; i < c->nadapters; i++) {
|
||||
core_adapter_ent* e = &c->adapters[i];
|
||||
if (e->active && e->endpoint == endpoint) { e->reap = 1; any = 1; }
|
||||
}
|
||||
if (any) core_wake(c);
|
||||
}
|
||||
|
||||
int vmsig_core_add_control(vmsig_core* c, const vmsig_control_ops* ops, void* ctl,
|
||||
const vmsig_grant* grant) {
|
||||
if (!c || !ops) return -1;
|
||||
@@ -137,6 +174,7 @@ int vmsig_core_add_control(vmsig_core* c, const vmsig_control_ops* ops, void* ct
|
||||
* this control is qualified). For a control added BEFORE the first publication,
|
||||
* the cell is not yet valid — it receives MEMCTX via the normal multicast in pump_up. */
|
||||
core_memctx_replay(c, id);
|
||||
core_roster_replay(c, id); /* late subscriber: retained VM roster (CAP_ROSTER) */
|
||||
|
||||
return id; /* ncontrols already bumped when picking id (on growth); reuse does not grow it */
|
||||
}
|
||||
@@ -205,7 +243,8 @@ void vmsig_core_free(vmsig_core* c) {
|
||||
* FIRST: their close stops off-loop workers and unregisters their seams (e.g.
|
||||
* memctx) BEFORE destruction. */
|
||||
for (int i = 0; i < c->nadapters; i++)
|
||||
if (c->adapters[i].ops->close) c->adapters[i].ops->close(c->adapters[i].a);
|
||||
if (c->adapters[i].active && c->adapters[i].ops->close)
|
||||
c->adapters[i].ops->close(c->adapters[i].a);
|
||||
for (int i = 0; i < c->ncontrols; i++)
|
||||
if (c->controls[i].active && c->controls[i].ops->close)
|
||||
c->controls[i].ops->close(c->controls[i].ctl);
|
||||
|
||||
Reference in New Issue
Block a user