Skip to content

Commit

Permalink
factory: create components compatible mount units for kernel
Browse files Browse the repository at this point in the history
The kernel-modules components require that /lib/{modules,firmware} can
be created by composition of what is shipped with the kernel plus
parts that will be shipped by said component type.

For this, we need to have modinfo files in a writable directory as
these files will need to be regenerated when a new kernel-modules
component is installed. These files need to be readable from
/lib/modules/UTS_RELEASE. Inside this directory, "kernel" and "vdso"
subfolders will be bind-mounted from the kernel snap, while "updates"
will have modules from the components.

In the case of UC, for modules we need an additional bind mount on top
of the directory coming from the base (this is not needed for hybrid
systems).

In the case of firmware, content from the kernel will be mounted to
/lib/firmware as in the past. However, we will rely on the existence
of a /lib/firmware/updates in the kernel to mount firware coming from
components.

The mount units for the active kernel are created at boot time and
stored in /run/systemd/system so they are accessible after the switch
root, and are actually mounted after the switch happens, but with
dependencies set so kernel modules are not loaded before the mounts
are ready. This replaces the fstab/generator that was creating the
mounts for modules/firmware in UC and hybrid respectively, and now
unifies the approach for both.
  • Loading branch information
alfonsosanchezbeato committed Jan 25, 2024
1 parent dc9e042 commit a1bafdd
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 62 deletions.
2 changes: 0 additions & 2 deletions factory/usr/lib/core/extra-paths
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@ set -eu

cat <<EOF >>/sysroot/etc/fstab
/run/mnt/data /writable none bind,x-initrd.mount 0 0
/run/mnt/kernel/firmware /usr/lib/firmware none bind,x-initrd.mount 0 0
/run/mnt/kernel/modules /usr/lib/modules none bind,x-initrd.mount 0 0
EOF
81 changes: 81 additions & 0 deletions factory/usr/lib/core/kernel-mounts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/bin/sh

set -eux

# Prepare kernel modules/firmware tree if it does not exist

ksnap_d=/run/mnt/kernel
core=false
data_d=/run/mnt/data
if [ -d /run/mnt/base ]; then
core=true
data_d=/run/mnt/data/system-data
fi

kernelVer=
for f in "$ksnap_d"/System.map-*; do
kernelVer=${f##"$ksnap_d"/System.map-}
done
mod_root_d="$data_d"/usr/lib/modules
mod_d="$mod_root_d"/"$kernelVer"
ksnap_mod_d="$ksnap_d"/modules/"$kernelVer"

if [ ! -d "$mod_d" ]; then
for d in initrd kernel vdso updates; do
mkdir -p "$mod_d"/"$d"
done
# Copy modinfo files
cp "$ksnap_mod_d"/modules.* "$mod_d"
fi

fw_root_d="$data_d"/usr/lib/firmware/updates
mkdir -p "$fw_root_d"

sysinit_wants=/run/systemd/system/sysinit.target.wants
mkdir -p "$sysinit_wants"

conf_mount_dir() {
what=$1
where=$2
options=$3
before_deps=
if [ $# -gt 3 ]; then
before_deps=$4
fi

unit=$(systemd-escape -p --suffix=mount "$where")
unit_path=/run/systemd/system/"$unit"
cat <<EOF > "$unit_path"
[Unit]
ConditionPathExists=!/etc/initrd-release
DefaultDependencies=no
After=systemd-remount-fs.service
Before=systemd-udev.service systemd-modules-load.service $before_deps
Before=sysinit.target
Before=umount.target
Conflicts=umount.target
[Mount]
What=$what
Options=$options
EOF

ln -s "$unit_path" "$sysinit_wants"/"$unit"
}

mod_unit_dep=
if [ "$core" = true ]; then
# For classic we are actually working on the rootfs, for core
# we need to bind mount to the base that is the rootfs.
mod_where=/usr/lib/modules
mod_unit_dep=$(systemd-escape -p --suffix=mount "$mod_where")
conf_mount_dir "$mod_root_d" "$mod_where" rbind,ro
fi
conf_mount_dir "$ksnap_mod_d"/kernel "$mod_d"/kernel bind,ro "$mod_unit_dep"
conf_mount_dir "$ksnap_mod_d"/vdso "$mod_d"/vdso bind,ro "$mod_unit_dep"

fw_where=/usr/lib/firmware
fw_unit=$(systemd-escape -p --suffix=mount "$fw_where")
conf_mount_dir "$ksnap_d"/firmware "$fw_where" rbind,ro
# Note that this will fail if the kernel snap does not have a firmware/updates dir
conf_mount_dir "$fw_root_d" /usr/lib/firmware/updates rbind,ro "$fw_unit"
57 changes: 0 additions & 57 deletions factory/usr/lib/systemd/system-generators/kernel-snap-generator

This file was deleted.

3 changes: 1 addition & 2 deletions factory/usr/lib/systemd/system/classic-mounts.service
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@ Before=initrd-fs.target

[Service]
Type=oneshot
# We force re-running kernel-snap-generator
ExecStart=systemctl daemon-reload
ExecStart=/usr/lib/core/kernel-mounts
StandardError=journal+console
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ Description=Detect Ubuntu classic sysroot
DefaultDependencies=no
Before=initrd-root-device.target
After=snap-initramfs-mounts.service
Wants=classic-mounts.service

ConditionPathIsMountPoint=!/run/mnt/base

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/ln -s data /run/mnt/sysroot
ExecStart=/usr/lib/core/kernel-mounts
1 change: 1 addition & 0 deletions factory/usr/lib/systemd/system/populate-writable.service
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ ExecStart=/usr/bin/chroot /sysroot /usr/lib/core/handle-writable-paths / /etc/sy
# TODO:UC20: move the-modeenv implementation to snap-bootstrap too
ExecStart=/usr/lib/the-modeenv
ExecStart=/usr/lib/core/extra-paths
ExecStart=/usr/lib/core/kernel-mounts

0 comments on commit a1bafdd

Please sign in to comment.