]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysupdate: Vacuum partial/pending instances first
authorPhilip Withnall <pwithnall@gnome.org>
Wed, 31 Dec 2025 00:05:05 +0000 (00:05 +0000)
committerPhilip Withnall <pwithnall@gnome.org>
Mon, 9 Feb 2026 12:03:59 +0000 (12:03 +0000)
Modify the vacuum implementation to preferentially vacuum partial or
pending transfers first (unless protected) as they are meant to be
fairly transitory, and ones which are hanging around have probably been
forgotten about and/or are out of date.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Helps: https://github.com/systemd/systemd/issues/34814

src/sysupdate/sysupdate-transfer.c

index 6d1262c1612fb2b6b7748ab4619c3b6998cdc977..f624a50cf40a9feb24efa81502b4acc298f3e22a 100644 (file)
@@ -798,7 +798,45 @@ int transfer_vacuum(
 
         transfer_remove_temporary(t);
 
-        /* First, calculate how many instances to keep, based on the instance limit — but keep at least one */
+        /* First, remove any partial or pending instances (unless protected) */
+        for (size_t i = 0; i < t->target.n_instances;) {
+                Instance *instance = t->target.instances[i];
+
+                assert(instance);
+
+                if (!instance->is_pending && !instance->is_partial) {
+                        i++;
+                        continue;
+                }
+
+                /* If this is listed among the protected versions, then let's not remove it */
+                if (strv_contains(t->protected_versions, instance->metadata.version) ||
+                    (extra_protected_version && streq(extra_protected_version, instance->metadata.version))) {
+                        log_debug("Version '%s' is pending/partial but protected, not removing.", instance->metadata.version);
+                        i++;
+                        continue;
+                }
+
+                assert(instance->resource);
+
+                log_info("%s Removing old %s '%s' (%s).",
+                         glyph(GLYPH_RECYCLING),
+                         instance->is_partial ? "partial" : "pending",
+                         instance->path,
+                         resource_type_to_string(instance->resource->type));
+
+                r = transfer_instance_vacuum(t, instance);
+                if (r < 0)
+                        return 0;
+
+                instance_free(instance);
+                memmove(t->target.instances + i, t->target.instances + i + 1, (t->target.n_instances - i - 1) * sizeof(Instance*));
+                t->target.n_instances--;
+
+                count++;
+        }
+
+        /* Second, calculate how many instances to keep, based on the instance limit — but keep at least one */
 
         instances_max = arg_instances_max != UINT64_MAX ? arg_instances_max : t->instances_max;
         assert(instances_max >= 1);