diff options
| author | Pierre-Loup GOSSE <pierre-loup.gosse@smile.fr> | 2025-09-03 16:45:27 +0200 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2025-09-08 18:02:39 +0100 |
| commit | 21d98bd960132033b2bbd460a40274d40ea28b60 (patch) | |
| tree | 6ced7d142b61b8adfc270b85c9c332190c025d4a | |
| parent | 857bb50a3533f897290add64706b98b72a0bded2 (diff) | |
| download | poky-21d98bd960132033b2bbd460a40274d40ea28b60.tar.gz | |
wic: add --extra-partition-space option to set unused space
By default, the content of the partition is filled by the filesystem
without leaving any unused free space. The --extra-space flag adds
extra space to the filesystem size, not to the partition.
Unused free space after the filesystem can be useful for some cases,
such as encrypting a partition at runtime.
With --extra-partition-space 32M, we ensure that the last 32M of the
partition is unused: this space does not contain filesystem data and
can store the LUKS2 header.
The implementation sets a difference between the partition and
filesystem size:
- With --fixed-size, the extra part space is removed from the
filesystem size.
- Otherwise (with or without --size flag), the extra part space is
added to the partition size.
(From OE-Core rev: 22fd1702aedf40257aa53963b62b5ef1bbd2818a)
Signed-off-by: Pierre-Loup GOSSE <pierre-loup.gosse@smile.fr>
CC: Alexander Kanavin <alex.kanavin@gmail.com>
CC: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | meta/lib/oeqa/selftest/cases/wic.py | 49 | ||||
| -rw-r--r-- | scripts/lib/wic/help.py | 8 | ||||
| -rw-r--r-- | scripts/lib/wic/ksparser.py | 3 | ||||
| -rw-r--r-- | scripts/lib/wic/partition.py | 34 |
4 files changed, 79 insertions, 15 deletions
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py index 44442e402d..c244c9f188 100644 --- a/meta/lib/oeqa/selftest/cases/wic.py +++ b/meta/lib/oeqa/selftest/cases/wic.py | |||
| @@ -1166,7 +1166,7 @@ run_wic_cmd() { | |||
| 1166 | 1166 | ||
| 1167 | return wkspath | 1167 | return wkspath |
| 1168 | 1168 | ||
| 1169 | def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False): | 1169 | def _get_wic(self, wkspath, ignore_status=False): |
| 1170 | p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir), | 1170 | p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir), |
| 1171 | ignore_status=ignore_status) | 1171 | ignore_status=ignore_status) |
| 1172 | 1172 | ||
| @@ -1180,7 +1180,13 @@ run_wic_cmd() { | |||
| 1180 | if not wicout: | 1180 | if not wicout: |
| 1181 | return (p, None) | 1181 | return (p, None) |
| 1182 | 1182 | ||
| 1183 | wicimg = wicout[0] | 1183 | return (p, wicout[0]) |
| 1184 | |||
| 1185 | def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False): | ||
| 1186 | p, wicimg = self._get_wic(wkspath, ignore_status) | ||
| 1187 | |||
| 1188 | if wicimg is None: | ||
| 1189 | return (p, None) | ||
| 1184 | 1190 | ||
| 1185 | if not native_sysroot: | 1191 | if not native_sysroot: |
| 1186 | native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") | 1192 | native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") |
| @@ -1320,6 +1326,45 @@ run_wic_cmd() { | |||
| 1320 | size = int(size[:-3]) | 1326 | size = int(size[:-3]) |
| 1321 | self.assertGreaterEqual(size, 204800) | 1327 | self.assertGreaterEqual(size, 204800) |
| 1322 | 1328 | ||
| 1329 | def test_extra_partition_space(self): | ||
| 1330 | native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") | ||
| 1331 | |||
| 1332 | with NamedTemporaryFile("w", suffix=".wks") as tempf: | ||
| 1333 | tempf.write("bootloader --ptable gpt\n" \ | ||
| 1334 | "part --ondisk hda --size 10M --extra-partition-space 10M --fstype=ext4\n" \ | ||
| 1335 | "part --ondisk hda --fixed-size 20M --extra-partition-space 10M --fstype=ext4\n" \ | ||
| 1336 | "part --source rootfs --ondisk hda --extra-partition-space 10M --fstype=ext4\n" \ | ||
| 1337 | "part --source rootfs --ondisk hda --fixed-size 200M --extra-partition-space 10M --fstype=ext4\n") | ||
| 1338 | tempf.flush() | ||
| 1339 | |||
| 1340 | _, wicimg = self._get_wic(tempf.name) | ||
| 1341 | |||
| 1342 | res = runCmd("parted -m %s unit b p" % wicimg, | ||
| 1343 | native_sysroot=native_sysroot, stderr=subprocess.PIPE) | ||
| 1344 | |||
| 1345 | # parse parted output which looks like this: | ||
| 1346 | # BYT;\n | ||
| 1347 | # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n | ||
| 1348 | # 1:0.00MiB:200MiB:200MiB:ext4::;\n | ||
| 1349 | partlns = res.output.splitlines()[2:] | ||
| 1350 | |||
| 1351 | self.assertEqual(4, len(partlns)) | ||
| 1352 | |||
| 1353 | # Test for each partitions that the extra part space exists | ||
| 1354 | for part in range(0, len(partlns)): | ||
| 1355 | part_file = os.path.join(self.resultdir, "selftest_img.part%d" % (part + 1)) | ||
| 1356 | partln = partlns[part].split(":") | ||
| 1357 | self.assertEqual(7, len(partln)) | ||
| 1358 | self.assertRegex(partln[3], r'^[0-9]+B$') | ||
| 1359 | part_size = int(partln[3].rstrip("B")) | ||
| 1360 | start = int(partln[1].rstrip("B")) / 512 | ||
| 1361 | length = part_size / 512 | ||
| 1362 | runCmd("dd if=%s of=%s skip=%d count=%d" % | ||
| 1363 | (wicimg, part_file, start, length)) | ||
| 1364 | res = runCmd("dumpe2fs %s -h | grep \"^Block count\"" % part_file) | ||
| 1365 | fs_size = int(res.output.split(":")[1].strip()) * 1024 | ||
| 1366 | self.assertLessEqual(fs_size + 10485760, part_size, "part file: %s" % part_file) | ||
| 1367 | |||
| 1323 | # TODO this test could also work on aarch64 | 1368 | # TODO this test could also work on aarch64 |
| 1324 | @skipIfNotArch(['i586', 'i686', 'x86_64']) | 1369 | @skipIfNotArch(['i586', 'i686', 'x86_64']) |
| 1325 | @OETestTag("runqemu") | 1370 | @OETestTag("runqemu") |
diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py index 2e3061f343..800c0abf0f 100644 --- a/scripts/lib/wic/help.py +++ b/scripts/lib/wic/help.py | |||
| @@ -1020,6 +1020,14 @@ DESCRIPTION | |||
| 1020 | By default, 10MB. This option cannot be used | 1020 | By default, 10MB. This option cannot be used |
| 1021 | with --fixed-size option. | 1021 | with --fixed-size option. |
| 1022 | 1022 | ||
| 1023 | --extra-partition-space: This option is specific to wic. It adds extra | ||
| 1024 | empty space after the space filled by the | ||
| 1025 | filesystem. With --fixed-size, the extra | ||
| 1026 | partition space is removed from the filesystem | ||
| 1027 | size. Otherwise (with or without --size flag), | ||
| 1028 | the extra partition space is added to the final | ||
| 1029 | paritition size. The default value is 0MB. | ||
| 1030 | |||
| 1023 | --overhead-factor: This option is specific to wic. The | 1031 | --overhead-factor: This option is specific to wic. The |
| 1024 | size of the partition is multiplied by | 1032 | size of the partition is multiplied by |
| 1025 | this factor. It has to be greater than or | 1033 | this factor. It has to be greater than or |
diff --git a/scripts/lib/wic/ksparser.py b/scripts/lib/wic/ksparser.py index 596b6e8e7e..a1aaf1b4b3 100644 --- a/scripts/lib/wic/ksparser.py +++ b/scripts/lib/wic/ksparser.py | |||
| @@ -154,6 +154,7 @@ class KickStart(): | |||
| 154 | part.add_argument('--include-path', nargs='+', action='append') | 154 | part.add_argument('--include-path', nargs='+', action='append') |
| 155 | part.add_argument('--change-directory') | 155 | part.add_argument('--change-directory') |
| 156 | part.add_argument("--extra-space", type=sizetype("M")) | 156 | part.add_argument("--extra-space", type=sizetype("M")) |
| 157 | part.add_argument('--extra-partition-space', type=sizetype("M")) | ||
| 157 | part.add_argument('--fsoptions', dest='fsopts') | 158 | part.add_argument('--fsoptions', dest='fsopts') |
| 158 | part.add_argument('--fspassno', dest='fspassno') | 159 | part.add_argument('--fspassno', dest='fspassno') |
| 159 | part.add_argument('--fstype', default='vfat', | 160 | part.add_argument('--fstype', default='vfat', |
| @@ -259,6 +260,8 @@ class KickStart(): | |||
| 259 | err = "%s:%d: Must set the label with --label" \ | 260 | err = "%s:%d: Must set the label with --label" \ |
| 260 | % (confpath, lineno) | 261 | % (confpath, lineno) |
| 261 | raise KickStartError(err) | 262 | raise KickStartError(err) |
| 263 | if not parsed.extra_partition_space: | ||
| 264 | parsed.extra_partition_space = 0 | ||
| 262 | # using ArgumentParser one cannot easily tell if option | 265 | # using ArgumentParser one cannot easily tell if option |
| 263 | # was passed as argument, if said option has a default | 266 | # was passed as argument, if said option has a default |
| 264 | # value; --overhead-factor/--extra-space cannot be used | 267 | # value; --overhead-factor/--extra-space cannot be used |
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py index b34691d313..d358aabbd6 100644 --- a/scripts/lib/wic/partition.py +++ b/scripts/lib/wic/partition.py | |||
| @@ -29,6 +29,7 @@ class Partition(): | |||
| 29 | self.disk = args.disk | 29 | self.disk = args.disk |
| 30 | self.device = None | 30 | self.device = None |
| 31 | self.extra_space = args.extra_space | 31 | self.extra_space = args.extra_space |
| 32 | self.extra_partition_space = args.extra_partition_space | ||
| 32 | self.exclude_path = args.exclude_path | 33 | self.exclude_path = args.exclude_path |
| 33 | self.include_path = args.include_path | 34 | self.include_path = args.include_path |
| 34 | self.change_directory = args.change_directory | 35 | self.change_directory = args.change_directory |
| @@ -91,13 +92,12 @@ class Partition(): | |||
| 91 | def get_rootfs_size(self, actual_rootfs_size=0): | 92 | def get_rootfs_size(self, actual_rootfs_size=0): |
| 92 | """ | 93 | """ |
| 93 | Calculate the required size of rootfs taking into consideration | 94 | Calculate the required size of rootfs taking into consideration |
| 94 | --size/--fixed-size flags as well as overhead and extra space, as | 95 | --size/--fixed-size and --extra-partition-space flags as well as overhead |
| 95 | specified in kickstart file. Raises an error if the | 96 | and extra space, as specified in kickstart file. Raises an error |
| 96 | `actual_rootfs_size` is larger than fixed-size rootfs. | 97 | if the `actual_rootfs_size` is larger than fixed-size rootfs. |
| 97 | |||
| 98 | """ | 98 | """ |
| 99 | if self.fixed_size: | 99 | if self.fixed_size: |
| 100 | rootfs_size = self.fixed_size | 100 | rootfs_size = self.fixed_size - self.extra_partition_space |
| 101 | if actual_rootfs_size > rootfs_size: | 101 | if actual_rootfs_size > rootfs_size: |
| 102 | raise WicError("Actual rootfs size (%d kB) is larger than " | 102 | raise WicError("Actual rootfs size (%d kB) is larger than " |
| 103 | "allowed size %d kB" % | 103 | "allowed size %d kB" % |
| @@ -119,10 +119,18 @@ class Partition(): | |||
| 119 | def disk_size(self): | 119 | def disk_size(self): |
| 120 | """ | 120 | """ |
| 121 | Obtain on-disk size of partition taking into consideration | 121 | Obtain on-disk size of partition taking into consideration |
| 122 | --size/--fixed-size options. | 122 | --size/--fixed-size and --extra-partition-space options. |
| 123 | |||
| 124 | """ | ||
| 125 | return self.fixed_size if self.fixed_size else self.size + self.extra_partition_space | ||
| 123 | 126 | ||
| 127 | @property | ||
| 128 | def fs_size(self): | ||
| 129 | """ | ||
| 130 | Obtain on-disk size of filesystem inside the partition taking into | ||
| 131 | consideration --size/--fixed-size and --extra-partition-space options. | ||
| 124 | """ | 132 | """ |
| 125 | return self.fixed_size if self.fixed_size else self.size | 133 | return self.fixed_size - self.extra_partition_space if self.fixed_size else self.size |
| 126 | 134 | ||
| 127 | def prepare(self, creator, cr_workdir, oe_builddir, rootfs_dir, | 135 | def prepare(self, creator, cr_workdir, oe_builddir, rootfs_dir, |
| 128 | bootimg_dir, kernel_dir, native_sysroot, updated_fstab_path): | 136 | bootimg_dir, kernel_dir, native_sysroot, updated_fstab_path): |
| @@ -202,10 +210,10 @@ class Partition(): | |||
| 202 | "This a bug in source plugin %s and needs to be fixed." % | 210 | "This a bug in source plugin %s and needs to be fixed." % |
| 203 | (self.mountpoint, self.source)) | 211 | (self.mountpoint, self.source)) |
| 204 | 212 | ||
| 205 | if self.fixed_size and self.size > self.fixed_size: | 213 | if self.fixed_size and self.size + self.extra_partition_space > self.fixed_size: |
| 206 | raise WicError("File system image of partition %s is " | 214 | raise WicError("File system image of partition %s is " |
| 207 | "larger (%d kB) than its allowed size %d kB" % | 215 | "larger (%d kB + %d kB extra part space) than its allowed size %d kB" % |
| 208 | (self.mountpoint, self.size, self.fixed_size)) | 216 | (self.mountpoint, self.size, self.extra_partition_space, self.fixed_size)) |
| 209 | 217 | ||
| 210 | def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir, | 218 | def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir, |
| 211 | native_sysroot, real_rootfs = True, pseudo_dir = None): | 219 | native_sysroot, real_rootfs = True, pseudo_dir = None): |
| @@ -440,7 +448,7 @@ class Partition(): | |||
| 440 | """ | 448 | """ |
| 441 | Prepare an empty ext2/3/4 partition. | 449 | Prepare an empty ext2/3/4 partition. |
| 442 | """ | 450 | """ |
| 443 | size = self.disk_size | 451 | size = self.fs_size |
| 444 | with open(rootfs, 'w') as sparse: | 452 | with open(rootfs, 'w') as sparse: |
| 445 | os.ftruncate(sparse.fileno(), size * 1024) | 453 | os.ftruncate(sparse.fileno(), size * 1024) |
| 446 | 454 | ||
| @@ -464,7 +472,7 @@ class Partition(): | |||
| 464 | """ | 472 | """ |
| 465 | Prepare an empty btrfs partition. | 473 | Prepare an empty btrfs partition. |
| 466 | """ | 474 | """ |
| 467 | size = self.disk_size | 475 | size = self.fs_size |
| 468 | with open(rootfs, 'w') as sparse: | 476 | with open(rootfs, 'w') as sparse: |
| 469 | os.ftruncate(sparse.fileno(), size * 1024) | 477 | os.ftruncate(sparse.fileno(), size * 1024) |
| 470 | 478 | ||
| @@ -482,7 +490,7 @@ class Partition(): | |||
| 482 | """ | 490 | """ |
| 483 | Prepare an empty vfat partition. | 491 | Prepare an empty vfat partition. |
| 484 | """ | 492 | """ |
| 485 | blocks = self.disk_size | 493 | blocks = self.fs_size |
| 486 | 494 | ||
| 487 | label_str = "-n boot" | 495 | label_str = "-n boot" |
| 488 | if self.label: | 496 | if self.label: |
