diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-11-10 09:21:24 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-10 09:21:24 +0900 |
commit | 3f6a18633ff48cfe79b1f556007d1dcff71879eb (patch) | |
tree | dbfc7e8616c9f9f1ce1239e67fa4a59d7f70ff20 | |
parent | 4a77b47ed85a1207a6cbdbda073fd7d7e205e148 (diff) | |
parent | 15c597764424214617034165bbc62d90f7cf1ae5 (diff) | |
download | systemd-3f6a18633ff48cfe79b1f556007d1dcff71879eb.tar.gz |
Merge pull request #21281 from poettering/repart-align-fixes
repart: fixes when operating on unaligned partitions
-rw-r--r-- | src/partition/repart.c | 50 | ||||
-rwxr-xr-x | test/units/testsuite-58.sh | 32 |
2 files changed, 52 insertions, 30 deletions
diff --git a/src/partition/repart.c b/src/partition/repart.c index 62cc8ff7ae..5e6e88df94 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -505,18 +505,21 @@ static uint64_t free_area_available_for_new_partitions(const FreeArea *a) { avail = free_area_available(a); if (a->after) { - uint64_t need, space; + uint64_t need, space_end, new_end; need = partition_min_size_with_padding(a->after); assert(a->after->offset != UINT64_MAX); assert(a->after->current_size != UINT64_MAX); - space = round_up_size(a->after->offset + a->after->current_size, 4096) - a->after->offset + avail; - if (need >= space) - return 0; + /* Calculate where the free area ends, based on the offset of the partition preceding it */ + space_end = round_up_size(a->after->offset + a->after->current_size, 4096) + avail; + + /* Calculate where the partition would end when we give it as much as it needs */ + new_end = round_up_size(a->after->offset + need, 4096); - return space - need; + /* Calculate saturated difference of the two: that's how much we have free for other partitions */ + return LESS_BY(space_end, new_end); } return avail; @@ -528,16 +531,9 @@ static int free_area_compare(FreeArea *const *a, FreeArea *const*b) { } static uint64_t charge_size(uint64_t total, uint64_t amount) { - uint64_t rounded; - - assert(amount <= total); - /* Subtract the specified amount from total, rounding up to multiple of 4K if there's room */ - rounded = round_up_size(amount, 4096); - if (rounded >= total) - return 0; - - return total - rounded; + assert(amount <= total); + return LESS_BY(total, round_up_size(amount, 4096)); } static uint64_t charge_weight(uint64_t total, uint64_t amount) { @@ -651,6 +647,8 @@ typedef enum GrowPartitionPhase { /* The third phase: we distribute what remains among the remaining partitions, according to the weights */ PHASE_DISTRIBUTE, + + _GROW_PARTITION_PHASE_MAX, } GrowPartitionPhase; static int context_grow_partitions_phase( @@ -786,20 +784,14 @@ static int context_grow_partitions_on_free_area(Context *context, FreeArea *a) { span += round_up_size(a->after->offset + a->after->current_size, 4096) - a->after->offset; } - GrowPartitionPhase phase = PHASE_OVERCHARGE; - for (;;) { + for (GrowPartitionPhase phase = 0; phase < _GROW_PARTITION_PHASE_MAX;) { r = context_grow_partitions_phase(context, a, phase, &span, &weight_sum); if (r < 0) return r; if (r == 0) /* not done yet, re-run this phase */ continue; - if (phase == PHASE_OVERCHARGE) - phase = PHASE_UNDERCHARGE; - else if (phase == PHASE_UNDERCHARGE) - phase = PHASE_DISTRIBUTE; - else if (phase == PHASE_DISTRIBUTE) - break; + phase++; /* got to next phase */ } /* We still have space left over? Donate to preceding partition if we have one */ @@ -807,7 +799,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) @@ -832,7 +826,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) @@ -1491,11 +1485,7 @@ static int determine_current_padding( offset = round_up_size(offset, 4096); next = round_down_size(next, 4096); - if (next >= offset) /* Check again, rounding might have fucked things up */ - *ret = next - offset; - else - *ret = 0; - + *ret = LESS_BY(next, offset); /* Saturated substraction, rounding might have fucked things up */ return 0; } @@ -4988,7 +4978,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 */ diff --git a/test/units/testsuite-58.sh b/test/units/testsuite-58.sh index 16cd8385fb..62d0a29cb5 100755 --- a/test/units/testsuite-58.sh +++ b/test/units/testsuite-58.sh @@ -84,6 +84,38 @@ cmp /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img rm /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img /tmp/testsuite-58.dump rm -r /tmp/testsuite-58-defs/ +# Third part: operate on an an image with unaligned partition, to see if that works. + +rm -f /var/tmp/testsuite-58.3.img /tmp/testsuite-58-3.dump +mkdir -p /tmp/testsuite-58.3-defs/ + +cat >/tmp/testsuite-58.3-defs/root.conf <<EOF +[Partition] +Type=root +EOF + +truncate -s 10g /var/tmp/testsuite-58.3.img +sfdisk /var/tmp/testsuite-58.3.img <<EOF +label: gpt + +start=2048, size=69044 +start=71092, size=3591848 +EOF + +systemd-repart --definitions=/tmp/testsuite-58.3-defs/ \ + --seed=750b6cd5c4ae4012a15e7be3c29e6a47 \ + --dry-run=no \ + /var/tmp/testsuite-58.3.img + +sfdisk --dump /var/tmp/testsuite-58.3.img | tee /tmp/testsuite-58.3.dump + +grep -qF '/var/tmp/testsuite-58.3.img1 : start= 2048, size= 69044,' /tmp/testsuite-58.3.dump +grep -qF '/var/tmp/testsuite-58.3.img2 : start= 71092, size= 3591848,' /tmp/testsuite-58.3.dump +grep -qxF '/var/tmp/testsuite-58.3.img3 : start= 3662944, size= 17308536, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=60F33797-1D71-4DCB-AA6F-20564F036CD0, name="root-x86-64", attrs="GUID:59"' /tmp/testsuite-58.3.dump + +rm /var/tmp/testsuite-58.3.img /tmp/testsuite-58.3.dump +rm -r /tmp/testsuite-58.3-defs/ + echo OK >/testok exit 0 |