Files
vatrog-vm-signaling/src/discovery/slot.c
T

92 lines
2.8 KiB
C
Raw Normal View History

/* slot.c — vmid <-> endpoint allocator (see slot.h). Pure logic + a tiny pointer-free
* on-disk format; no core dependency. */
#define _GNU_SOURCE
#include "slot.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
void slot_init(slot_table* t) {
memset(t, 0, sizeof *t);
}
int slot_lookup(const slot_table* t, uint32_t vmid) {
if (!vmid) return -1;
for (int e = 0; e < VMSIG_SLOT_COUNT; e++)
if (t->ent[e].vmid == vmid) return e;
return -1;
}
int slot_alloc(slot_table* t, uint32_t vmid) {
if (!vmid) return -1;
int e = slot_lookup(t, vmid);
if (e >= 0) return e; /* idempotent pin */
/* lowest free bit: ffsll of the complement (1-based; 0 => none free) */
int b = __builtin_ffsll((long long)~t->used_mask);
if (b == 0) return -1; /* table full (64-VM ceiling) */
e = b - 1;
t->ent[e].vmid = vmid;
t->used_mask |= (1ull << e);
return e;
}
void slot_free(slot_table* t, uint32_t vmid) {
int e = slot_lookup(t, vmid);
if (e < 0) return;
t->ent[e].vmid = 0;
t->used_mask &= ~(1ull << e);
}
/* ---- persistence: magic + version + 64 * uint32 vmid (native byte order, tmpfs-local) ---- */
#define SLOT_MAGIC 0x534C4F54u /* "SLOT" */
#define SLOT_VERSION 1u
typedef struct {
uint32_t magic;
uint32_t version;
uint32_t vmid[VMSIG_SLOT_COUNT];
} slot_blob;
int slot_save(const slot_table* t, const char* path) {
if (!path) return -1;
slot_blob b;
memset(&b, 0, sizeof b);
b.magic = SLOT_MAGIC; b.version = SLOT_VERSION;
for (int e = 0; e < VMSIG_SLOT_COUNT; e++) b.vmid[e] = t->ent[e].vmid;
char tmp[512];
int n = snprintf(tmp, sizeof tmp, "%s.tmp", path);
if (n < 0 || (size_t)n >= sizeof tmp) return -1;
int fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
if (fd < 0) return -1;
ssize_t w = write(fd, &b, sizeof b);
int rc = (w == (ssize_t)sizeof b) ? 0 : -1;
if (close(fd) != 0) rc = -1;
if (rc == 0 && rename(tmp, path) != 0) rc = -1;
if (rc != 0) unlink(tmp);
return rc;
}
int slot_load(slot_table* t, const char* path) {
slot_init(t);
if (!path) return 0;
int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) return 0; /* no file => fresh start (valid) */
slot_blob b;
ssize_t r = read(fd, &b, sizeof b);
close(fd);
if (r != (ssize_t)sizeof b || b.magic != SLOT_MAGIC || b.version != SLOT_VERSION) {
slot_init(t); /* corrupt/old => fresh start */
return 0;
}
for (int e = 0; e < VMSIG_SLOT_COUNT; e++) {
t->ent[e].vmid = b.vmid[e];
if (b.vmid[e]) t->used_mask |= (1ull << e);
}
return 0;
}