From: Lennart Poettering Date: Wed, 25 Jun 2025 09:02:05 +0000 (+0200) Subject: repart: respect minimum sector size for ESP/VFAT partitions X-Git-Tag: v258-rc1~244^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F37899%2Fhead;p=thirdparty%2Fsystemd.git repart: respect minimum sector size for ESP/VFAT partitions Fixes: #37801 --- diff --git a/man/repart.d.xml b/man/repart.d.xml index eb628ffc169..d3a8f6fcea7 100644 --- a/man/repart.d.xml +++ b/man/repart.d.xml @@ -341,6 +341,11 @@ and the placing algorithm restarted. By default, a minimum size constraint of 10M and no maximum size constraint is set. + If Format= is set, the minimum size is automatically raised to the minimum + file system size for the selected file system type, if known. Moreover, for the ESP/XBOOTLDR + partitions the minimum is raised to 100M (for 512b sector images) or 260M (for 4K sector images) + automatically, if specified smaller. + diff --git a/src/repart/repart.c b/src/repart/repart.c index 937d4dcd895..ca211702bfc 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -105,6 +105,15 @@ * filesystems will then also be compatible with sector sizes 512, 1024 and 2048. */ #define DEFAULT_FILESYSTEM_SECTOR_SIZE 4096ULL +/* Minimum sizes for the ESP depending on sector size. What the minimum is, is severely underdocumented, but + * it appears for 4K sector size it must be 260M, and otherwise 100M. This is what Microsoft says here: + * + * https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/configure-uefigpt-based-hard-drive-partitions?view=windows-11 + * https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/oem-deployment-of-windows-desktop-editions-sample-scripts?view=windows-11&preserve-view=true#-createpartitions-uefitxt + */ +#define ESP_MIN_SIZE (100 * U64_MB) +#define ESP_MIN_SIZE_4K (260 * U64_MB) + #define APIVFS_TMP_DIRS_NULSTR "proc\0sys\0dev\0tmp\0run\0var/tmp\0" #define AUTOMATIC_FSTAB_HEADER_START "# Start section ↓ of automatically generated fstab by systemd-repart" @@ -929,6 +938,21 @@ static uint64_t partition_fs_sector_size(const Context *c, const Partition *p) { return MAX(ss, c->sector_size); } +static uint64_t partition_fstype_min_size(const Context *c, const Partition *p) { + assert(c); + assert(p); + + /* If a file system type is configured, then take it into consideration for the minimum partition + * size */ + + if (IN_SET(p->type.designator, PARTITION_ESP, PARTITION_XBOOTLDR) && streq_ptr(p->format, "vfat")) { + uint64_t ss = partition_fs_sector_size(c, p); + return ss >= 4096 ? ESP_MIN_SIZE_4K : ESP_MIN_SIZE; + } + + return minimal_size_by_fs_name(p->format); +} + static uint64_t partition_min_size(const Context *context, const Partition *p) { uint64_t sz, override_min; @@ -964,8 +988,8 @@ static uint64_t partition_min_size(const Context *context, const Partition *p) { uint64_t f; /* If we shall synthesize a file system, take minimal fs size into account (assumed to be 4K if not known) */ - f = p->format ? round_up_size(minimal_size_by_fs_name(p->format), context->grain_size) : UINT64_MAX; - d += f == UINT64_MAX ? context->grain_size : f; + f = partition_fstype_min_size(context, p); + d += f == UINT64_MAX ? context->grain_size : round_up_size(f, context->grain_size); } if (d > sz) diff --git a/test/units/TEST-58-REPART.sh b/test/units/TEST-58-REPART.sh index 97e37836134..aa472df99ad 100755 --- a/test/units/TEST-58-REPART.sh +++ b/test/units/TEST-58-REPART.sh @@ -565,9 +565,9 @@ EOF output=$(sfdisk --dump "$imgs/zzz") - assert_in "$imgs/zzz1 : start= 2048, size= 20480, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=39107B09-615D-48FB-BA37-C663885FCE67, name=\"esp\"" "$output" - assert_in "$imgs/zzz2 : start= 22528, size= 65536, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output" - assert_in "$imgs/zzz3 : start= 88064, size= 65536, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:60\"" "$output" + assert_in "$imgs/zzz1 : start= 2048, size= 532480, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=39107B09-615D-48FB-BA37-C663885FCE67, name=\"esp\"" "$output" + assert_in "$imgs/zzz2 : start= 534528, size= 65536, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output" + assert_in "$imgs/zzz3 : start= 600064, size= 65536, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:60\"" "$output" if systemd-detect-virt --quiet --container; then echo "Skipping second part of copy blocks tests in container." @@ -1573,7 +1573,7 @@ EOF systemd-repart --empty=create --size=auto --dry-run=no --definitions="$defs" "$image" output=$(sfdisk -d "$image") - assert_in "${image}1 : start= 2048, size= 204800, type=${esp_guid}" "$output" + assert_in "${image}1 : start= 2048, size= 532480, type=${esp_guid}" "$output" assert_not_in "${image}2" "$output" # Disk with small ESP => ESP grows @@ -1586,12 +1586,12 @@ EOF systemd-repart --dry-run=no --definitions="$defs" "$image" output=$(sfdisk -d "$image") - assert_in "${image}1 : start= 2048, size= 204800, type=${esp_guid}" "$output" + assert_in "${image}1 : start= 2048, size= 532480, type=${esp_guid}" "$output" assert_not_in "${image}2" "$output" # Disk with small ESP that can't grow => XBOOTLDR created - truncate -s 150M "$image" + truncate -s 400M "$image" sfdisk "$image" < XBOOTLDR grows, small ESP created @@ -1614,8 +1614,8 @@ EOF systemd-repart --dry-run=no --definitions="$defs" "$image" output=$(sfdisk -d "$image") - assert_in "${image}1 : start= 2048, size= 204800, type=${xbootldr_guid}" "$output" - assert_in "${image}2 : start= 206848, size= 100312, type=${esp_guid}" "$output" + assert_in "${image}1 : start= 2048, size= 284632, type=${xbootldr_guid}" "$output" + assert_in "${image}2 : start= 286680, size= 532480, type=${esp_guid}" "$output" } OFFLINE="yes" diff --git a/test/units/TEST-87-AUX-UTILS-VM.validatefs.sh b/test/units/TEST-87-AUX-UTILS-VM.validatefs.sh index ede0d710195..86120975be7 100755 --- a/test/units/TEST-87-AUX-UTILS-VM.validatefs.sh +++ b/test/units/TEST-87-AUX-UTILS-VM.validatefs.sh @@ -74,7 +74,7 @@ MountPoint=/somewhere/else Format=ext4 EOF -systemd-repart --dry-run=no --empty=create --size=256M --definitions=/tmp/validatefs-test /var/tmp/validatefs-test.raw +systemd-repart --dry-run=no --empty=create --size=410M --definitions=/tmp/validatefs-test /var/tmp/validatefs-test.raw systemd-dissect --mount --mkdir /var/tmp/validatefs-test.raw /tmp/validatefs-test.mount