summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-11-10 09:21:24 +0900
committerGitHub <noreply@github.com>2021-11-10 09:21:24 +0900
commit3f6a18633ff48cfe79b1f556007d1dcff71879eb (patch)
treedbfc7e8616c9f9f1ce1239e67fa4a59d7f70ff20
parent4a77b47ed85a1207a6cbdbda073fd7d7e205e148 (diff)
parent15c597764424214617034165bbc62d90f7cf1ae5 (diff)
downloadsystemd-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.c50
-rwxr-xr-xtest/units/testsuite-58.sh32
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