summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrevor Woerner <twoerner@gmail.com>2025-04-14 22:04:05 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2025-04-17 11:03:22 +0100
commit35807e8f634ce86bc77b3461cb0deb466c08a9d2 (patch)
treeb5f2e19ef78881b5fdd8d2f5a68ea2a7eb9d63dc
parent94d2759dd72c2e26ccecea072ecac4831671f00b (diff)
downloadpoky-35807e8f634ce86bc77b3461cb0deb466c08a9d2.tar.gz
wic: do not ignore ROOTFS_SIZE if the rootfs is modified
If the *.wks file contains a "--source rootfs" then lib/wic/plugins/source/rootfs.py will be invoked to generate (what is assumed to be) the rootfs partition. If the rootfs partition needs to be tweaked or modified, the "rootfs.py" plugin will make a copy of the filesystem and then perform the changes on that copy. In other words, if the "--source rootfs" line of the *.wks file also contains any of: --exclude-path --include-path --change-directory --use-label (i.e. modify etc/fstab) then the rootfs will be copied first, then the copy is modified. If, for example, the unmodified IMAGE_ROOTFS is: .../tmp/work/qemuarm64_secureboot-oe-linux/core-image-base/1.0/rootfs then the copy would be made at: .../tmp/work/qemuarm64_secureboot-oe-linux/core-image-base/1.0/tmp-wic/rootfs${LINENO} where ${LINENO} is the line number where this "--source rootfs" line appears in the *wks file. When it comes time to make an actual partition of a specific filesystem type, lib/wic/partition.py::prepare_rootfs() is called. It is in this function that wic figures out if any extra size needs to be added. The bitbake variable used to specify the ultimate rootfs size is ROOTFS_SIZE, and since this variable is only valid for the rootfs (and not any other partitions), the code also verifies that the partition being created is ${IMAGE_ROOTFS}: rsize_bb = get_bitbake_var('ROOTFS_SIZE') rdir = get_bitbake_var('IMAGE_ROOTFS') if rsize_bb and rdir == rootfs_dir: <use rsize_bb> else: <calculate the partition size using "du -ks $p"> As noted above, if lib/wic/plugins/source/rootfs.py has made a copy, then the "rdir == rootfs_dir" clause will fail and the code will assume this partition is not a rootfs since the strings do not compare equal. Therefore, in order to determine if this is a rootfs, retain the existing "rdir == rootfs_dir" comparison, but also add another one to check whether or not this is a wic-generated copy of the rootfs. STEPS TO REPRODUCE: - start with the following *wks file: bootloader --ptable gpt part /boot --size=100M --active --fstype=ext4 --label boot part / --source rootfs --fstype=ext4 --label root - and the following extra variable in conf/local.conf: IMAGE_ROOTFS_EXTRA_SPACE = "500000" - build an image - run it in qemu $ runqemu slirp nographic serial - verify the root partition has extra space: root@qemuarm64-secureboot:~# df -h Filesystem Size Used Available Use% Mounted on /dev/root 721.5M 67.4M 600.6M 10% / devtmpfs 477.7M 0 477.7M 0% /dev tmpfs 40.0K 0 40.0K 0% /mnt tmpfs 489.3M 92.0K 489.2M 0% /run tmpfs 489.3M 68.0K 489.2M 0% /var/volatile /dev/vda1 120.4M 19.9M 91.4M 18% /boot - modify the "/" line of the *wks file to be: part / --source rootfs --fstype=ext4 --label root --exclude-path boot/ - build image when it fails: root@qemuarm64-secureboot:~# df -h Filesystem Size Used Available Use% Mounted on /dev/root 73.4M 41.9M 25.8M 62% / devtmpfs 477.7M 0 477.7M 0% /dev tmpfs 40.0K 0 40.0K 0% /mnt tmpfs 489.3M 92.0K 489.2M 0% /run tmpfs 489.3M 68.0K 489.2M 0% /var/volatile /dev/vda1 120.4M 19.9M 91.4M 18% /boot after this fix: root@qemuarm64-secureboot:~# df -h Filesystem Size Used Available Use% Mounted on /dev/root 721.5M 47.4M 620.6M 7% / devtmpfs 477.7M 0 477.7M 0% /dev tmpfs 40.0K 0 40.0K 0% /mnt tmpfs 489.3M 92.0K 489.2M 0% /run tmpfs 489.3M 68.0K 489.2M 0% /var/volatile /dev/vda1 120.4M 19.9M 91.4M 18% /boot Doing the math we see that the /boot partition is ~20MB and in the first image the / partition contains this ~20MB in addition to the rest of the rootfs. This ~20MB is completely wasted since it is used in the / partition, but then the /boot partition is mounted on top of it, making the /boot directory of / inaccessible. After the fix the / partition has an additional ~20MB since the /boot portion is excluded. Fixes [YOCTO #15555] (From OE-Core rev: 1c690aa046ebca13d7b29de50d42b5d8a4a8486c) Signed-off-by: Trevor Woerner <twoerner@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/lib/oeqa/selftest/cases/wic.py33
-rw-r--r--scripts/lib/wic/partition.py2
2 files changed, 34 insertions, 1 deletions
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py
index 59fd99a788..d98af8713a 100644
--- a/meta/lib/oeqa/selftest/cases/wic.py
+++ b/meta/lib/oeqa/selftest/cases/wic.py
@@ -535,6 +535,39 @@ part /mnt --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/whoa
535 finally: 535 finally:
536 os.environ['PATH'] = oldpath 536 os.environ['PATH'] = oldpath
537 537
538 def test_exclude_path_with_extra_space(self):
539 """Test having --exclude-path with IMAGE_ROOTFS_EXTRA_SPACE. [Yocto #15555]"""
540
541 with NamedTemporaryFile("w", suffix=".wks") as wks:
542 wks.writelines(
543 ['bootloader --ptable gpt\n',
544 'part /boot --size=100M --active --fstype=ext4 --label boot\n',
545 'part / --source rootfs --fstype=ext4 --label root --exclude-path boot/\n'])
546 wks.flush()
547 config = 'IMAGE_ROOTFS_EXTRA_SPACE = "500000"\n'\
548 'DEPENDS:pn-core-image-minimal += "wic-tools"\n'\
549 'IMAGE_FSTYPES += "wic"\n'\
550 'WKS_FILE = "%s"\n' % wks.name
551 self.append_config(config)
552 bitbake('core-image-minimal')
553
554 """
555 the output of "wic ls <image>.wic" will look something like:
556 Num Start End Size Fstype
557 1 17408 136332287 136314880 ext4
558 2 136332288 171464703 35132416 ext4
559 we are looking for the size of partition 2
560 i.e. in this case the number 35,132,416
561 without the fix the size will be around 85,403,648
562 with the fix the size should be around 799,960,064
563 """
564 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'], 'core-image-minimal')
565 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
566 machine = bb_vars['MACHINE']
567 wicout = glob(os.path.join(deploy_dir, "core-image-minimal-%s.rootfs-*.wic" % machine))[0]
568 size_of_root_partition = int(runCmd("wic ls %s" % wicout).output.split('\n')[2].split()[3])
569 self.assertGreater(size_of_root_partition, 500000000)
570
538 def test_include_path(self): 571 def test_include_path(self):
539 """Test --include-path wks option.""" 572 """Test --include-path wks option."""
540 573
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
index bf2c34d594..b18431d8fb 100644
--- a/scripts/lib/wic/partition.py
+++ b/scripts/lib/wic/partition.py
@@ -244,7 +244,7 @@ class Partition():
244 # from bitbake variable 244 # from bitbake variable
245 rsize_bb = get_bitbake_var('ROOTFS_SIZE') 245 rsize_bb = get_bitbake_var('ROOTFS_SIZE')
246 rdir = get_bitbake_var('IMAGE_ROOTFS') 246 rdir = get_bitbake_var('IMAGE_ROOTFS')
247 if rsize_bb and rdir == rootfs_dir: 247 if rsize_bb and (rdir == rootfs_dir or (rootfs_dir.split('/')[-2] == "tmp-wic" and rootfs_dir.split('/')[-1][:6] == "rootfs")):
248 # Bitbake variable ROOTFS_SIZE is calculated in 248 # Bitbake variable ROOTFS_SIZE is calculated in
249 # Image._get_rootfs_size method from meta/lib/oe/image.py 249 # Image._get_rootfs_size method from meta/lib/oe/image.py
250 # using IMAGE_ROOTFS_SIZE, IMAGE_ROOTFS_ALIGNMENT, 250 # using IMAGE_ROOTFS_SIZE, IMAGE_ROOTFS_ALIGNMENT,