repart: Slightly simplify supplement partition code (#42508)

Juts two small things that hopefully make it easier to read the code
around supplement/suppressing partitions.

cc @AdrianVovk
This commit is contained in:
Lennart Poettering
2026-06-19 22:13:12 +02:00
committed by GitHub
+54 -56
View File
@@ -543,8 +543,8 @@ typedef struct Partition {
RateLimit progress_ratelimit;
char *supplement_for_name;
struct Partition *supplement_for, *supplement_target_for;
struct Partition *suppressing;
struct Partition *supplement_for, *supplemented_by;
bool suppressing_supplement;
struct Partition *siblings[_VERITY_MODE_MAX];
@@ -553,7 +553,7 @@ typedef struct Partition {
#define PARTITION_IS_FOREIGN(p) (!(p)->definition_path)
#define PARTITION_EXISTS(p) (!!(p)->current_partition)
#define PARTITION_SUPPRESSED(p) ((p)->supplement_for && (p)->supplement_for->suppressing == (p))
#define PARTITION_SUPPRESSED(p) ((p)->supplement_for && (p)->supplement_for->suppressing_supplement)
struct FreeArea {
Partition *after;
@@ -797,23 +797,24 @@ static Partition *partition_new(Context *c) {
static void partition_unlink_supplement(Partition *p) {
assert(p);
assert(!p->supplement_for || !p->supplement_target_for); /* Can't be both */
assert(!p->supplement_for || !p->supplemented_by); /* Can't be both */
if (p->supplement_target_for) {
assert(p->supplement_target_for->supplement_for == p);
if (p->supplemented_by) {
assert(p->supplemented_by->supplement_for == p);
p->supplement_target_for->supplement_for = NULL;
p->supplemented_by->supplement_for = NULL;
}
if (p->supplement_for) {
assert(p->supplement_for->supplement_target_for == p);
assert(!p->supplement_for->suppressing || p->supplement_for->suppressing == p);
assert(p->supplement_for->supplemented_by == p);
p->supplement_for->supplement_target_for = p->supplement_for->suppressing = NULL;
p->supplement_for->supplemented_by = NULL;
p->supplement_for->suppressing_supplement = false;
}
p->supplement_for_name = mfree(p->supplement_for_name);
p->supplement_target_for = p->supplement_for = p->suppressing = NULL;
p->supplemented_by = p->supplement_for = NULL;
p->suppressing_supplement = false;
}
static Partition* partition_free(Partition *p) {
@@ -1100,7 +1101,7 @@ static void partition_drop_or_foreignize(Partition *p) {
/* If a supplement partition is dropped, we don't want to merge in its settings. */
if (PARTITION_SUPPRESSED(p))
p->supplement_for->suppressing = NULL;
p->supplement_for->suppressing_supplement = false;
}
}
@@ -1213,8 +1214,8 @@ static uint64_t partition_min_size(const Context *context, const Partition *p) {
}
uint64_t min_size = p->size_min;
if (p->suppressing && (min_size == UINT64_MAX || p->suppressing->size_min > min_size))
min_size = p->suppressing->size_min;
if (p->suppressing_supplement && (min_size == UINT64_MAX || p->supplemented_by->size_min > min_size))
min_size = p->supplemented_by->size_min;
/* Default to 10M min size, except if the file system is read-only, in which case let's not enforce a
* minimum size, because even if we wanted to we couldn't take possession of the extra space
@@ -1244,7 +1245,7 @@ static uint64_t partition_max_size(const Context *context, const Partition *p) {
if (partition_designator_is_verity_sig(p->type.designator))
return VERITY_SIG_SIZE;
override_max = p->suppressing ? MIN(p->size_max, p->suppressing->size_max) : p->size_max;
override_max = p->suppressing_supplement ? MIN(p->size_max, p->supplemented_by->size_max) : p->size_max;
if (override_max == UINT64_MAX)
return UINT64_MAX;
@@ -1261,13 +1262,13 @@ static uint64_t partition_min_padding(const Partition *p) {
assert(p);
override_min = p->suppressing ? MAX(p->padding_min, p->suppressing->padding_min) : p->padding_min;
override_min = p->suppressing_supplement ? MAX(p->padding_min, p->supplemented_by->padding_min) : p->padding_min;
return override_min != UINT64_MAX ? override_min : 0;
}
static uint64_t partition_max_padding(const Partition *p) {
assert(p);
return p->suppressing ? MIN(p->padding_max, p->suppressing->padding_max) : p->padding_max;
return p->suppressing_supplement ? MIN(p->padding_max, p->supplemented_by->padding_max) : p->padding_max;
}
static uint64_t partition_min_size_with_padding(const Context *context, const Partition *p) {
@@ -1437,32 +1438,28 @@ static bool context_unmerge_and_allocate_partitions(Context *context) {
/* First, let's try to un-suppress just one supplement partition and see if that gets us anywhere */
LIST_FOREACH(partitions, p, context->partitions) {
Partition *unsuppressed;
if (!p->suppressing)
if (!p->suppressing_supplement)
continue;
unsuppressed = TAKE_PTR(p->suppressing);
p->suppressing_supplement = false;
if (context_allocate_partitions(context, NULL))
return true;
p->suppressing = unsuppressed;
p->suppressing_supplement = true;
}
/* Looks like not. So we have to un-suppress at least two partitions. We can do this recursively */
LIST_FOREACH(partitions, p, context->partitions) {
Partition *unsuppressed;
if (!p->suppressing)
if (!p->suppressing_supplement)
continue;
unsuppressed = TAKE_PTR(p->suppressing);
p->suppressing_supplement = false;
if (context_unmerge_and_allocate_partitions(context))
return true;
p->suppressing = unsuppressed;
p->suppressing_supplement = true;
}
/* No combination of un-suppressed supplements made it possible to fit the partitions */
@@ -1471,12 +1468,12 @@ static bool context_unmerge_and_allocate_partitions(Context *context) {
static uint32_t partition_weight(const Partition *p) {
assert(p);
return p->suppressing ? p->suppressing->weight : p->weight;
return p->suppressing_supplement ? p->supplemented_by->weight : p->weight;
}
static uint32_t partition_padding_weight(const Partition *p) {
assert(p);
return p->suppressing ? p->suppressing->padding_weight : p->padding_weight;
return p->suppressing_supplement ? p->supplemented_by->padding_weight : p->padding_weight;
}
static int context_sum_weights(const Context *context, const FreeArea *a, uint64_t *ret) {
@@ -2842,13 +2839,13 @@ static bool partition_add_validatefs(const Partition *p) {
static bool partition_needs_populate(const Partition *p) {
assert(p);
assert(!p->supplement_for || !p->suppressing); /* Avoid infinite recursion */
assert(!p->supplement_for || !p->suppressing_supplement); /* Avoid infinite recursion */
return p->n_copy_files > 0 ||
!strv_isempty(p->make_directories) ||
!strv_isempty(p->make_symlinks) ||
partition_add_validatefs(p) ||
(p->suppressing && partition_needs_populate(p->suppressing));
(p->suppressing_supplement && partition_needs_populate(p->supplemented_by));
}
static MakeFileSystemFlags partition_mkfs_flags(const Partition *p) {
@@ -3518,10 +3515,10 @@ static int supplement_find_target(const Context *context, const Partition *suppl
return log_syntax(NULL, LOG_ERR, supplement->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
"SupplementFor= target is itself configured as a supplement.");
if (p->suppressing)
if (p->suppressing_supplement)
return log_syntax(NULL, LOG_ERR, supplement->definition_path, 1, SYNTHETIC_ERRNO(EINVAL),
"SupplementFor= target already has a supplement defined: %s",
p->suppressing->definition_path);
p->supplemented_by->definition_path);
*ret = p;
return 0;
@@ -3677,7 +3674,8 @@ static int context_read_definitions(Context *context) {
"PaddingMinBytes= larger than PaddingMaxBytes= when merged with SupplementFor= target.");
p->supplement_for = tgt;
tgt->suppressing = tgt->supplement_target_for = p;
tgt->supplemented_by = p;
tgt->suppressing_supplement = true;
}
return 0;
@@ -4086,7 +4084,7 @@ static int context_load_partition_table(Context *context) {
LIST_FOREACH(partitions, p, context->partitions)
if (PARTITION_SUPPRESSED(p) && PARTITION_EXISTS(p))
p->supplement_for->suppressing = NULL;
p->supplement_for->suppressing_supplement = false;
add_initial_free_area:
nsectors = sym_fdisk_get_nsectors(c);
@@ -4184,7 +4182,7 @@ static void context_unload_partition_table(Context *context) {
/* A supplement partition is only ever un-suppressed if the existing partition table prevented
* us from suppressing it. So when unloading the partition table, we must re-suppress. */
if (p->supplement_for)
p->supplement_for->suppressing = p;
p->supplement_for->suppressing_supplement = true;
}
context->start = UINT64_MAX;
@@ -6450,15 +6448,15 @@ static int make_copy_files_denylist(
/* Add the user configured excludes. */
if (p->suppressing) {
if (p->suppressing_supplement) {
r = shallow_join_strv(&override_exclude_src,
p->exclude_files_source,
p->suppressing->exclude_files_source);
p->supplemented_by->exclude_files_source);
if (r < 0)
return r;
r = shallow_join_strv(&override_exclude_tgt,
p->exclude_files_target,
p->suppressing->exclude_files_target);
p->supplemented_by->exclude_files_target);
if (r < 0)
return r;
}
@@ -6590,14 +6588,14 @@ static int make_subvolumes_hashmap(const Partition *p, Hashmap **ret) {
TAKE_PTR(path);
}
if (p->suppressing) {
Hashmap *suppressing;
if (p->suppressing_supplement) {
Hashmap *supplemented_by;
r = make_subvolumes_hashmap(p->suppressing, &suppressing);
r = make_subvolumes_hashmap(p->supplemented_by, &supplemented_by);
if (r < 0)
return r;
r = hashmap_merge(hashmap, suppressing);
r = hashmap_merge(hashmap, supplemented_by);
if (r < 0)
return log_oom();
}
@@ -6636,14 +6634,14 @@ static int make_subvolumes_by_source_inode_hashmap(
return r;
}
if (p->suppressing) {
Hashmap *suppressing;
if (p->suppressing_supplement) {
Hashmap *supplemented_by;
r = make_subvolumes_by_source_inode_hashmap(p->suppressing, source, target, &suppressing);
r = make_subvolumes_by_source_inode_hashmap(p->supplemented_by, source, target, &supplemented_by);
if (r < 0)
return r;
r = hashmap_merge(hashmap, suppressing);
r = hashmap_merge(hashmap, supplemented_by);
if (r < 0)
return log_oom();
}
@@ -6707,9 +6705,9 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
return log_oom();
size_t n_copy_files = p->n_copy_files;
if (p->suppressing) {
if (p->suppressing_supplement) {
if (!GREEDY_REALLOC_APPEND(copy_files, n_copy_files,
p->suppressing->copy_files, p->suppressing->n_copy_files))
p->supplemented_by->copy_files, p->supplemented_by->n_copy_files))
return log_oom();
}
@@ -6885,8 +6883,8 @@ static int do_make_directories(Partition *p, const char *root) {
if (r < 0)
return r;
if (p->suppressing) {
r = shallow_join_strv(&override_dirs, p->make_directories, p->suppressing->make_directories);
if (p->suppressing_supplement) {
r = shallow_join_strv(&override_dirs, p->make_directories, p->supplemented_by->make_directories);
if (r < 0)
return r;
}
@@ -6939,8 +6937,8 @@ static int make_subvolumes_read_only(Partition *p, const char *root) {
return log_error_errno(r, "Failed to make subvolume '%s' read-only: %m", subvolume->path);
}
if (p->suppressing) {
r = make_subvolumes_read_only(p->suppressing, root);
if (p->suppressing_supplement) {
r = make_subvolumes_read_only(p->supplemented_by, root);
if (r < 0)
return r;
}
@@ -7258,12 +7256,12 @@ static int finalize_extra_mkfs_options(const Partition *p, const char *root, cha
if (r < 0)
return r;
if (p->suppressing) {
r = append_btrfs_subvols(&sv, p->suppressing->subvolumes, NULL);
if (p->suppressing_supplement) {
r = append_btrfs_subvols(&sv, p->supplemented_by->subvolumes, NULL);
if (r < 0)
return r;
r = append_btrfs_inode_flags(&sv, p->suppressing->subvolumes);
r = append_btrfs_inode_flags(&sv, p->supplemented_by->subvolumes);
if (r < 0)
return r;
}