From: Lennart Poettering Date: Tue, 9 Nov 2021 15:25:24 +0000 (+0100) Subject: repart: don't distribute space after unaligned partitions X-Git-Tag: v250-rc1~320^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0b7f574f72c72afb9384d7ea11b324ead067c8d1;p=thirdparty%2Fsystemd.git repart: don't distribute space after unaligned partitions If we operate on a disk that has a pre-existing unaligned partition (i.e. one that doesn't start on multiple of 4K, or doesn't have a size of multiple 4K), then the amount of space after it to distribute among partitions isn't a multiple of 4K either. So far we might end up passing the remaining fraction to any partition that wanted it, which was usually the first one after it that is newly defined. This then confused the later placement algorithm, since it assumed all partitions we newly allocate were properly aligned but by being extended by the fractional space they wouldn't be anymore. Let's hence fix that by ensuring we never pass space to later partitions so that things wouldn't be aligned anymore. Anything that is left-over then at the very end (i.e. typically exactly the remaining fraction) is added as padding to the existing, unaligned partition, so that it can't confuse anyone. Fixes: #20622 --- diff --git a/src/partition/repart.c b/src/partition/repart.c index db2f95afc7c..3ff97520056 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -796,7 +796,9 @@ static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) { uint64_t m, xsz; assert(a->after->new_size != UINT64_MAX); - m = a->after->new_size + span; + + /* Calculate new size and align (but ensure this doesn't shrink the size) */ + m = MAX(a->after->new_size, round_down_size(a->after->new_size + span, 4096)); xsz = partition_max_size(a->after); if (xsz != UINT64_MAX && m > xsz) @@ -821,7 +823,7 @@ static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) { continue; assert(p->new_size != UINT64_MAX); - m = p->new_size + span; + m = MAX(p->new_size, round_down_size(p->new_size + span, 4096)); xsz = partition_max_size(p); if (xsz != UINT64_MAX && m > xsz) @@ -4973,7 +4975,7 @@ static int run(int argc, char *argv[]) { if (r < 0) return r; - /* Now calculate where each partition gets placed */ + /* Now calculate where each new partition gets placed */ context_place_partitions(context); /* Make sure each partition has a unique UUID and unique label */