Skip to content

Commit 762bb78

Browse files
committed
investigate squashfs to overcome BR2_TARGET_ROOTFS_EXT2_SIZE but fail
Generate qcow2 when running QEMU if it is not present.
1 parent 8372b16 commit 762bb78

File tree

6 files changed

+63
-39
lines changed

6 files changed

+63
-39
lines changed

README.adoc

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ We use `./build-buildroot` because the kernel modules go inside the root filesys
222222

223223
The reboot after rebuild is annoying. We don't have a perfect solution for it yet, but there are some ideas cooking at: <<gem5-restore-new-script>>.
224224

225-
Using <<KVM>> can speed boot up however if your host and guest have the same arch, e.g. on an `x86_64` host:
225+
Using <<KVM>> can <<benchmark-linux-kernel-boot,speed up>> the boot however if your host and guest have the same arch, e.g. on an `x86_64` host:
226226

227227
....
228228
./run --kvm
@@ -7103,6 +7103,7 @@ But TODO we didn't get it working yet:
71037103

71047104
* https://stackoverflow.com/questions/41119656/how-can-i-overlayfs-the-root-filesystem-on-linux
71057105
* https://unix.stackexchange.com/questions/316018/how-to-use-overlayfs-to-protect-the-root-filesystem
7106+
* https://unix.stackexchange.com/questions/420646/mount-root-as-overlayfs
71067107

71077108
Test with the script:
71087109

@@ -7129,11 +7130,13 @@ ls /overlay/proc
71297130

71307131
A less good alternative is to set `LD_LIBRARY_PATH` on the 9p mount and run executables directly from the mount.
71317132

7132-
Even mor awesome than `chroot` be to `pivot_root`, but I couldn't get that working either:
7133+
Even more awesome than `chroot` would be to `pivot_root`, but I couldn't get that working either:
71337134

71347135
* https://stackoverflow.com/questions/28015688/pivot-root-device-or-resource-busy
71357136
* https://unix.stackexchange.com/questions/179788/pivot-root-device-or-resource-busy
71367137

7138+
Here is a more basic working example of OverlayFS usage: https://askubuntu.com/questions/109413/how-do-i-use-overlayfs/1075564#1075564
7139+
71377140
=== Guest host networking
71387141

71397142
First ensure that networking is enabled before trying out anything in this section: <<networking>>
@@ -9298,11 +9301,22 @@ Unfortunately, TODO we don't have a perfect way to find the right value for `BR2
92989301
du -hsx "$(./getvar --arch arm target_dir)"
92999302
....
93009303

9301-
https://stackoverflow.com/questions/49211241/is-there-a-way-to-automatically-detect-the-minimum-required-br2-target-rootfs-ex
9304+
Some promising ways to overcome this problem include:
9305+
9306+
* <<squashfs>>
9307+
TODO benchmark: would gem5 suffer a considerable disk read performance hit due to decompressing SquashFS?
9308+
* libguestfs: link:https://serverfault.com/questions/246835/convert-directory-to-qemu-kvm-virtual-disk-image/916697#916697[], in particular link:http://libguestfs.org/guestfish.1.html#vfs-minimum-size[`vfs-minimum-size`]
9309+
* use methods described at: <<gem5-restore-new-script>> instead of putting builds on the root filesystem
9310+
9311+
Bibliography: https://stackoverflow.com/questions/49211241/is-there-a-way-to-automatically-detect-the-minimum-required-br2-target-rootfs-ex
9312+
9313+
==== SquashFS
9314+
9315+
link:https://en.wikipedia.org/wiki/SquashFS[SquashFS] creation with `mksquashfs` does not take fixed sizes, and I have successfully booted from it, but it is readonly, which is unacceptable.
93029316

9303-
libguestfs is very promising link:https://serverfault.com/questions/246835/convert-directory-to-qemu-kvm-virtual-disk-image/916697#916697[], in particular link:http://libguestfs.org/guestfish.1.html#vfs-minimum-size[`vfs-minimum-size`].
9317+
But then we could mount link:https://wiki.debian.org/ramfs[ramfs] on top of it with <<overlayfs>> to make it writable, but my attempts failed exactly as mentioned at <<overlayfs>>.
93049318

9305-
One way to overcome this problem is to mount benchmarks from host instead of adding them to the root filesystem, e.g. with: <<9p>>.
9319+
This is the exact unanswered question: https://unix.stackexchange.com/questions/343484/mounting-squashfs-image-with-read-write-overlay-for-rootfs
93069320

93079321
[[rpath]]
93089322
=== Buildroot rebuild is slow when the root filesystem is large

build-buildroot

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ https://stackoverflow.com/questions/49260466/why-when-i-change-br2-linux-kernel-
9797
That target builds the root filesystem and all its dependencies.'''
9898
)
9999
kernel_module_group.add_argument(
100-
'--no-kernel-modules', default=defaults['kernel_modules'], action='store_true',
100+
'--no-kernel-modules', default=defaults['no_kernel_modules'], action='store_true',
101101
help="Don't build the kernel modules package"
102102
)
103103
parser.add_argument(
@@ -293,18 +293,11 @@ def main(args, extra_args=None):
293293
cwd=common.buildroot_src_dir,
294294
) == 0
295295

296-
# Create the qcow2 from ext2. This is optional, because gem5
297-
# does not need the qcow2.
298-
if os.path.exists(common.qemu_img_executable) and os.path.exists(common.ext2_file):
299-
assert common.run_cmd([
300-
common.qemu_img_executable,
301-
'-T', 'pr_manager_run,file=/dev/null',
302-
'convert',
303-
'-f', 'raw',
304-
'-O', 'qcow2',
305-
common.ext2_file,
306-
common.qcow2_file,
307-
]) == 0
296+
# Create the qcow2 from ext2.
297+
# Skip if qemu is not present, because gem5 does not need the qcow2.
298+
# so we don't force a QEMU build for gem5.
299+
if not args.no_all and os.path.exists(common.qemu_img_executable):
300+
common.raw_to_qcow2()
308301

309302
return 0
310303

buildroot_config/default

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ BR2_TOOLCHAIN_BUILDROOT_WCHAR=y
1616
# Rootfs
1717
BR2_TARGET_ROOTFS_CPIO=n
1818
BR2_TARGET_ROOTFS_EXT2=y
19-
BR2_TARGET_ROOTFS_INITRAMFS=n
2019
BR2_TARGET_ROOTFS_EXT2_SIZE="512M"
20+
BR2_TARGET_ROOTFS_SQUASHFS=n
21+
BR2_TARGET_ROOTFS_INITRAMFS=n
22+
# TODO can you boot with those as root filesystem?
23+
BR2_TARGET_ROOTFS_TAR=n
2124

2225
# Host GDB
2326
BR2_GDB_VERSION="7.11.1"

common.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,18 @@ def print_time(ellapsed_seconds):
219219
minutes, seconds = divmod(rem, 60)
220220
print("time {:02}:{:02}:{:02}".format(int(hours), int(minutes), int(seconds)))
221221

222+
def raw_to_qcow2():
223+
global this
224+
assert this.run_cmd([
225+
this.qemu_img_executable,
226+
'-T', 'pr_manager_run,file=/dev/null',
227+
'convert',
228+
'-f', 'raw',
229+
'-O', 'qcow2',
230+
this.rootfs_raw_file,
231+
this.qcow2_file,
232+
]) == 0
233+
222234
def resolve_args(defaults, args, extra_args):
223235
if extra_args is None:
224236
extra_args = {}
@@ -331,8 +343,8 @@ def setup(parser, **extra_args):
331343
this.host_dir = os.path.join(this.buildroot_build_dir, 'host')
332344
this.host_bin_dir = os.path.join(this.host_dir, 'usr', 'bin')
333345
this.images_dir = os.path.join(this.buildroot_build_dir, 'images')
334-
this.ext2_file = os.path.join(this.images_dir, 'rootfs.ext2')
335-
this.qcow2_file = os.path.join(this.images_dir, 'rootfs.ext2.qcow2')
346+
this.rootfs_raw_file = os.path.join(this.images_dir, 'rootfs.squashfs')
347+
this.qcow2_file = this.rootfs_raw_file + '.qcow2'
336348
this.staging_dir = os.path.join(this.buildroot_build_dir, 'staging')
337349
this.target_dir = os.path.join(this.buildroot_build_dir, 'target')
338350
this.run_dir_base = os.path.join(this.out_dir, 'run')

kernel_config/default

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
# Misc.
22
CONFIG_BLK_DEV_INITRD=y
3-
CONFIG_DEBUG_FS=y
43
CONFIG_DYNAMIC_DEBUG=y
54
CONFIG_MODULE_SRCVERSION_ALL=y
6-
CONFIG_OVERLAY_FS=y
75
CONFIG_STRICT_DEVMEM=n
86

7+
# Filesystems.
8+
CONFIG_DEBUG_FS=y
9+
CONFIG_OVERLAY_FS=y
10+
CONFIG_SQUASHFS=y
11+
912
# GDB debugging.
1013
CONFIG_DEBUG_INFO=y
1114
CONFIG_DEBUG_KERNEL=y

run

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def main(args, extra_args=None):
125125
os.path.join(common.gem5_src_dir, 'configs', 'example', 'arm', 'fs_bigLITTLE.py'),
126126
'--big-cpus', '2',
127127
'--cpu-type', 'atomic',
128-
'--disk', common.ext2_file,
128+
'--disk', common.rootfs_raw_file,
129129
'--dtb', os.path.join(common.gem5_system_dir, 'arm', 'dt', 'armv8_gem5_v1_big_little_2_2.dtb'),
130130
'--kernel', common.vmlinux,
131131
'--little-cpus', '2'
@@ -138,7 +138,7 @@ def main(args, extra_args=None):
138138
extra_emulator_args.extend(['-r', str(sorted(cpt_dirs).index(cpt_dir) + 1)])
139139
cmd += [
140140
common.gem5_fs_file,
141-
'--disk-image', common.ext2_file,
141+
'--disk-image', common.rootfs_raw_file,
142142
'--kernel', common.vmlinux,
143143
'--mem-size', memory,
144144
'--num-cpus', str(args.cpus),
@@ -159,6 +159,19 @@ def main(args, extra_args=None):
159159
else:
160160
extra_emulator_args.extend(extra_qemu_args)
161161
os.makedirs(common.run_dir, exist_ok=True)
162+
if args.prebuilt:
163+
common.mkdir()
164+
qemu_executable = "qemu-system-{}".format(args.arch)
165+
else:
166+
qemu_executable = common.qemu_executable
167+
if not os.path.exists(qemu_executable):
168+
raise Exception('QEMU executable does not exist, did you forget to build or install it?\n' \
169+
'Tried to use: ' + qemu_executable)
170+
if not os.path.exists(common.qcow2_file):
171+
if not os.path.exists(common.rootfs_raw_file):
172+
raise Exception('Root filesystem not found. Did you build it?\n' \
173+
'Tried to use: ' + common.rootfs_raw_file)
174+
common.raw_to_qcow2()
162175
if args.debug_vm:
163176
serial_monitor = []
164177
else:
@@ -167,11 +180,6 @@ def main(args, extra_args=None):
167180
extra_emulator_args.append('-enable-kvm')
168181
if args.kgdb:
169182
extra_emulator_args.extend(['-serial', 'tcp::{},server,nowait'.format(common.gdb_port)])
170-
if args.prebuilt:
171-
common.mkdir()
172-
qemu_executable = "qemu-system-{}".format(args.arch)
173-
else:
174-
qemu_executable = common.qemu_executable
175183
cmd = (
176184
debug_vm +
177185
[
@@ -212,12 +220,6 @@ def main(args, extra_args=None):
212220
'-drive',
213221
'file={},format=qcow2,if={}{}{}'.format(common.qcow2_file, driveif, snapshot, rrid)
214222
])
215-
if not os.path.exists(common.qcow2_file):
216-
raise Exception(
217-
'Cannot find the qcow2 root filesystem. You must build QEMU\n'
218-
'before building the root filesystem? That is needed because the qcow2\n' +
219-
'is created with qemu-img. Tried to use: ' + qemu_executable
220-
)
221223
if rr:
222224
extra_emulator_args.extend([
223225
'-drive', 'driver=blkreplay,if=none,image=img-direct,id=img-blkreplay',
@@ -257,9 +259,6 @@ def main(args, extra_args=None):
257259
] +
258260
virtio_gpu_pci
259261
)
260-
if not os.path.exists(qemu_executable):
261-
raise Exception('QEMU executable does not exist, did you forget to build or install it?\n' +
262-
'Tried to use: ' + qemu_executable)
263262
if args.tmux:
264263
if args.gem5:
265264
subprocess.Popen([os.path.join(common.root_dir, 'tmu'),

0 commit comments

Comments
 (0)