repart: Keep new partitions after existing same-type partitions
When a partition is deleted from a table containing multiple partitions of the same type, filling the resulting partition-number gap can place a new partition before an existing partition matched to an earlier definition. This changes definition matching on the next invocation and breaks idempotency. Keep new partitions after existing partitions of the same type. If no partition table slot is available after them, fall back to the first unused slot. Which existing partition is matched to which definition is still determined by partition type and partition number order, as documented, and is unchanged by this. Fixes #43449
This commit is contained in:
committed by
Luca Boccassi
parent
9bb06d5cd6
commit
a9ff124143
+29
-3
@@ -1766,16 +1766,42 @@ static int context_grow_partitions(Context *context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t find_first_unused_partno(Context *context) {
|
||||
static uint64_t find_unused_partno(Context *context, const Partition *partition) {
|
||||
uint64_t partno = 0;
|
||||
size_t nents;
|
||||
|
||||
assert(context);
|
||||
assert(partition);
|
||||
|
||||
/* Keep new partitions after existing partitions of the same type, as those are matched
|
||||
* to definitions in partition number order. */
|
||||
LIST_FOREACH(partitions, p, context->partitions)
|
||||
if (PARTITION_EXISTS(p) && p->partno != UINT64_MAX &&
|
||||
sd_id128_equal(p->type.uuid, partition->type.uuid))
|
||||
partno = MAX(partno, p->partno + 1);
|
||||
|
||||
nents = sym_fdisk_get_npartitions(context->fdisk_context);
|
||||
|
||||
/* Prefer a free slot after all existing partitions of the same type. */
|
||||
for (; partno < nents; partno++) {
|
||||
bool found = false;
|
||||
LIST_FOREACH(partitions, p, context->partitions)
|
||||
if (p->partno != UINT64_MAX && p->partno == partno) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
return partno;
|
||||
}
|
||||
|
||||
/* Fall back to the first unused slot if there is no such slot. */
|
||||
for (partno = 0;; partno++) {
|
||||
bool found = false;
|
||||
LIST_FOREACH(partitions, p, context->partitions)
|
||||
if (p->partno != UINT64_MAX && p->partno == partno)
|
||||
if (p->partno != UINT64_MAX && p->partno == partno) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
break;
|
||||
}
|
||||
@@ -1811,7 +1837,7 @@ static void context_place_partitions(Context *context) {
|
||||
continue;
|
||||
|
||||
p->offset = start;
|
||||
p->partno = find_first_unused_partno(context);
|
||||
p->partno = find_unused_partno(context, p);
|
||||
|
||||
assert(left >= p->new_size);
|
||||
start += p->new_size;
|
||||
|
||||
Reference in New Issue
Block a user