LUO: only deserialize on boot, add version and structure to JSON payload (#42607)

This commit is contained in:
Luca Boccassi
2026-06-16 17:55:56 +01:00
committed by GitHub
4 changed files with 116 additions and 38 deletions
+47 -8
View File
@@ -53,7 +53,7 @@ int manager_luo_restore_fd_stores(Manager *m) {
_cleanup_close_ int device_fd = -EBADF;
_cleanup_(luo_session_finishp) int session_fd = -EBADF;
const char *unit_id;
sd_json_variant *fds_json;
sd_json_variant *unit_json;
int r, n_total = 0;
assert(m);
@@ -83,18 +83,39 @@ int manager_luo_restore_fd_stores(Manager *m) {
if (r < 0)
return r;
struct {
uint64_t version;
sd_json_variant *units;
} q = {};
static const sd_json_dispatch_field mapping_dispatch_table[] = {
{ "version", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, voffsetof(q, version), SD_JSON_MANDATORY },
{ "units", SD_JSON_VARIANT_OBJECT, sd_json_dispatch_variant_noref, voffsetof(q, units), 0 },
{}
};
r = sd_json_dispatch(mapping, mapping_dispatch_table, SD_JSON_ALLOW_EXTENSIONS|SD_JSON_LOG, &q);
if (r < 0)
return r;
if (q.version > LUO_PROTOCOL_VERSION) {
log_warning("LUO mapping has unsupported version %" PRIu64 ", skipping state restoration.", q.version);
return 0;
}
/* Retrieve all fds from the session and dispatch each to the named unit, eagerly loading the
* unit if necessary. */
JSON_VARIANT_OBJECT_FOREACH(unit_id, fds_json, mapping) {
sd_json_variant *entry;
JSON_VARIANT_OBJECT_FOREACH(unit_id, unit_json, q.units) {
sd_json_variant *entry, *fds_json;
if (!unit_name_is_valid(unit_id, UNIT_NAME_ANY)) {
log_warning("Invalid unit name '%s' in LUO mapping, skipping.", unit_id);
continue;
}
fds_json = sd_json_variant_by_key(unit_json, "fdstore");
if (!sd_json_variant_is_array(fds_json)) {
log_warning("LUO mapping for unit '%s' is not a JSON array, skipping.", unit_id);
log_warning("LUO mapping fdstore for unit '%s' is not a JSON array, skipping.", unit_id);
continue;
}
@@ -172,7 +193,7 @@ int manager_luo_restore_fd_stores(Manager *m) {
}
int manager_luo_serialize_fd_stores(Manager *m, FILE **ret_f, FDSet **ret_fds) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *root = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *root = NULL, *units = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_fdset_free_ FDSet *fds = NULL;
Unit *u;
@@ -192,8 +213,9 @@ int manager_luo_serialize_fd_stores(Manager *m, FILE **ret_f, FDSet **ret_fds) {
if (!fds)
return log_oom();
/* Build a JSON object: { "unit_id": [ { "type": "fd", "name": "...", "fd": N },
* { "type": "luo_session", "name": "...", "fd": N, "sessionName": "..." } ], ... }
/* Build a JSON object: { "version": 1,
* "units": { "unit_id": { "fdstore": [ { "type": "fd", "name": "...", "fd": N },
* { "type": "luo_session", "name": "...", "fd": N, "sessionName": "..." } ] }, ... } }
* This is passed to systemd-shutdown which will create a LUO session and preserve the fds. */
HASHMAP_FOREACH(u, m->units) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *entries = NULL;
@@ -247,7 +269,17 @@ int manager_luo_serialize_fd_stores(Manager *m, FILE **ret_f, FDSet **ret_fds) {
n_serialized++;
}
r = sd_json_variant_set_field(&root, u->id, entries);
if (!entries)
continue;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *unit_json = NULL;
r = sd_json_buildo(
&unit_json,
SD_JSON_BUILD_PAIR_VARIANT("fdstore", entries));
if (r < 0)
return log_error_errno(r, "Failed to build LUO unit object: %m");
r = sd_json_variant_set_field(&units, u->id, unit_json);
if (r < 0)
return log_error_errno(r, "Failed to add unit to LUO serialization JSON: %m");
}
@@ -259,6 +291,13 @@ int manager_luo_serialize_fd_stores(Manager *m, FILE **ret_f, FDSet **ret_fds) {
return 0;
}
r = sd_json_buildo(
&root,
SD_JSON_BUILD_PAIR_UNSIGNED("version", LUO_PROTOCOL_VERSION),
SD_JSON_BUILD_PAIR_CONDITION(!!units, "units", SD_JSON_BUILD_VARIANT(units)));
if (r < 0)
return log_error_errno(r, "Failed to build LUO serialization JSON: %m");
r = open_serialization_file("luo-fd-store", &f);
if (r < 0)
return log_error_errno(r, "Failed to create LUO serialization file: %m");
+4 -2
View File
@@ -2194,8 +2194,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, Hashmap *named_
m->soft_reboots_count++;
/* If a LUO (Live Update Orchestrator) session from a previous kexec is available, restore
* preserved file descriptors into the appropriate service fd stores now, before coldplug. */
(void) manager_luo_restore_fd_stores(m);
* preserved file descriptors into the appropriate service fd stores now, before coldplug.
* Only do this when booting up (i.e., skip on reexec/soft reboot/etc.) */
if (m->previous_objective < 0)
(void) manager_luo_restore_fd_stores(m);
/* Pick up fds passed via the LISTEN_FDS=/LISTEN_FDNAMES= protocol that are tagged with a
* unit id ("unit-id|fdname"), and route them into the matching unit's fd store. Untagged