public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
From: Uladzimir Bely <ubely@ilbers.de>
To: Felix Moessbauer <felix.moessbauer@siemens.com>,
	isar-users@googlegroups.com
Cc: adriaan.schmidt@siemens.com, cedric.hombourger@siemens.com
Subject: Re: [PATCH 1/2] delay creation of initrd until end of rootfs install
Date: Tue, 22 Apr 2025 12:16:14 +0300	[thread overview]
Message-ID: <1d1d8ce5d778413cfd092be84e26ee3a9186be05.camel@ilbers.de> (raw)
In-Reply-To: <20250410052751.3835154-2-felix.moessbauer@siemens.com>

On Thu, 2025-04-10 at 07:27 +0200, 'Felix Moessbauer' via isar-users
wrote:
> This patch solves major performance issues around the initramfs
> creation by ensuring that the initrd is only created once. This is
> implemented by stubbing the update-initramfs call during the package
> installing. After all apt operations are completed, we manually
> trigger the initrd creation. In case a custom initramfs is used, the
> creation is completely skipped in the image rootfs, as this would
> anyways not be used. We further unify the initrd generation in the
> rootfs and in the initramfs class.
> 
> Before that, each package install that made a initrd relevant change
> triggered the update of the initrd. As we have multiple apt calls
> during
> the build, this step was sometimes executed multiple times. In
> addition,
> the apt install step is emulated, further slowing down the initrd
> generation.
> 
> On a test build of the RPi4b target with a detached initramfs and a
> distro kernel, this patch set reduced the build time form ~50min to
> ~15min.
> 
> Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
> ---
>  meta/classes/image.bbclass                    | 17 ++---
>  meta/classes/initramfs.bbclass                | 39 +----------
>  meta/classes/rootfs.bbclass                   | 66
> ++++++++++++++++++-
>  .../sbuild-chroot/sbuild-chroot.inc           |  1 +
>  4 files changed, 72 insertions(+), 51 deletions(-)
> 

Hello.

The patch makes builds for ubuntu targets fail:

```
| DEBUG: Executing shell function rootfs_generate_initramfs
| basename: extra operand '/boot/vmlinuz.old'
| Try 'basename --help' for more information.
| Generating initrd
| Available versions:
| Nothing to do, exiting.
| cp: cannot stat '/build/tmp/work/ubuntu-focal-amd64/isar-image-base-
qemuamd64/1.0-r0/rootfs/initrd.img': No such file or directory
| WARNING: exit code 1 from a shell command.
| DEBUG: Executing shell function rootfs_do_umounts
| DEBUG: Shell function rootfs_do_umounts finished
| DEBUG: Python function do_generate_initramfs finished
ERROR: Task (/build/../repo/meta-isar/recipes-core/images/isar-image-
base.bb:do_generate_initramfs) failed with exit code '1'
```

It's easy to reproduce in kas-container, even on amd64 target, for any
ubuntu (focal/jammy/noble) distro.

> diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass
> index ff3cd737..8523a662 100644
> --- a/meta/classes/image.bbclass
> +++ b/meta/classes/image.bbclass
> @@ -67,6 +67,8 @@ inherit essential
>  
>  ROOTFSDIR = "${IMAGE_ROOTFS}"
>  ROOTFS_FEATURES += "clean-package-cache clean-pycache generate-
> manifest export-dpkg-status clean-log-files clean-debconf-cache"
> +# when using a custom initrd, do not generate one as part of the
> image rootfs
> +ROOTFS_FEATURES += "${@ '' if d.getVar('INITRD_IMAGE') == '' else
> 'no-generate-initrd'}"
>  ROOTFS_PACKAGES += "${IMAGE_PREINSTALL}
> ${@isar_multiarch_packages('IMAGE_INSTALL', d)}"
>  ROOTFS_MANIFEST_DEPLOY_DIR ?= "${DEPLOY_DIR_IMAGE}"
>  ROOTFS_DPKGSTATUS_DEPLOY_DIR ?= "${DEPLOY_DIR_IMAGE}"
> @@ -341,17 +343,6 @@ do_copy_boot_files() {
>          sudo cat "$kernel" > "${DEPLOYDIR}/${KERNEL_IMAGE}"
>      fi
>  
> -    if [ -z "${INITRD_IMAGE}" ]; then
> -        # deploy default initrd if no custom one is build
> -        initrd="$(realpath -q '${IMAGE_ROOTFS}/initrd.img')"
> -        if [ ! -f "$initrd" ]; then
> -            initrd="$(realpath -q
> '${IMAGE_ROOTFS}/boot/initrd.img')"
> -        fi
> -        if [ -f "$initrd" ]; then
> -            cp -f "$initrd" '${DEPLOYDIR}/${INITRD_DEPLOY_FILE}'
> -        fi
> -    fi
> -
>      for file in ${DTB_FILES}; do
>          dtb="$(find '${IMAGE_ROOTFS}/usr/lib' -type f \
>                      -iwholename '*linux-image-*/'${file} | head -1)"
> @@ -450,7 +441,7 @@ EOSUDO
>          -exec touch '{}' -h -d@${SOURCE_DATE_EPOCH} ';'
>  }
>  do_rootfs_finalize[network] = "${TASK_USE_SUDO}"
> -addtask rootfs_finalize before do_rootfs after do_rootfs_postprocess
> +addtask rootfs_finalize before do_rootfs after do_rootfs_postprocess
> do_generate_initramfs
>  
>  ROOTFS_QA_FIND_ARGS ?= ""
>  
> @@ -461,6 +452,8 @@ do_rootfs_quality_check() {
>      args="${ROOTFS_QA_FIND_ARGS}"
>      # rootfs_finalize chroot-setup.sh
>      args="${args} ! -path ${ROOTFSDIR}/var/lib/dpkg/diversions"
> +    # initramfs is generated outside of the image rootfs
> +    args="${args} ! -path ${ROOTFSDIR}/boot/initrd.img*"
>      for cmd in ${ROOTFS_POSTPROCESS_COMMAND}; do
>          case "${cmd}" in
>  	    image_postprocess_mark)
> diff --git a/meta/classes/initramfs.bbclass
> b/meta/classes/initramfs.bbclass
> index 0197a60b..3a996f78 100644
> --- a/meta/classes/initramfs.bbclass
> +++ b/meta/classes/initramfs.bbclass
> @@ -6,14 +6,11 @@ DEPLOYDIR = "${WORKDIR}/deploy"
>  STAMP = "${STAMPS_DIR}/${DISTRO}-${DISTRO_ARCH}/${PN}-
> ${MACHINE}/${PV}-${PR}"
>  STAMPCLEAN = "${STAMPS_DIR}/${DISTRO}-${DISTRO_ARCH}/${PN}-
> ${MACHINE}/*-*"
>  
> -# Sstate also needs to be machine-specific
> -SSTATE_MANIFESTS = "${TMPDIR}/sstate-control/${MACHINE}-${DISTRO}-
> ${DISTRO_ARCH}"
> -SSTATETASKS += "do_generate_initramfs"
> -
>  INITRAMFS_INSTALL ?= ""
>  INITRAMFS_PREINSTALL ?= ""
>  INITRAMFS_ROOTFS ?= "${WORKDIR}/rootfs"
>  INITRAMFS_IMAGE_NAME = "${INITRAMFS_FULLNAME}.initrd.img"
> +INITRD_DEPLOY_FILE = "${INITRAMFS_IMAGE_NAME}"
>  
>  # Install proper kernel
>  INITRAMFS_INSTALL += "${@ ("linux-image-" + d.getVar("KERNEL_NAME"))
> if d.getVar("KERNEL_NAME") else ""}"
> @@ -28,37 +25,3 @@ ROOTFS_FEATURES = ""
>  ROOTFS_PACKAGES = "initramfs-tools ${INITRAMFS_PREINSTALL}
> ${INITRAMFS_INSTALL}"
>  
>  inherit rootfs
> -
> -do_generate_initramfs[network] = "${TASK_USE_SUDO}"
> -do_generate_initramfs[cleandirs] += "${DEPLOYDIR}"
> -do_generate_initramfs[sstate-inputdirs] = "${DEPLOYDIR}"
> -do_generate_initramfs[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}"
> -do_generate_initramfs() {
> -    rootfs_do_mounts
> -
> -    trap 'exit 1' INT HUP QUIT TERM ALRM USR1
> -    trap 'rootfs_do_umounts' EXIT
> -
> -    rootfs_do_qemu
> -
> -    sudo -E chroot "${INITRAMFS_ROOTFS}" sh -c '\
> -        export kernel_version=$(basename /boot/vmlinu[xz]* | cut -
> d'-' -f2-); \
> -        if [ -n "$kernel_version" ]; then \
> -          update-initramfs -u -v -k "$kernel_version"; \
> -        else \
> -          update-initramfs -u -v ;  \
> -        fi'
> -
> -    rootfs_do_umounts
> -
> -    if [ ! -e "${INITRAMFS_ROOTFS}/initrd.img" ]; then
> -        bberror "No initramfs was found after generation!"
> -    fi
> -    cp ${INITRAMFS_ROOTFS}/initrd.img
> ${DEPLOYDIR}/${INITRAMFS_IMAGE_NAME}
> -}
> -addtask generate_initramfs after do_rootfs before do_build
> -
> -python do_generate_initramfs_setscene () {
> -    sstate_setscene(d)
> -}
> -addtask do_generate_initramfs_setscene
> diff --git a/meta/classes/rootfs.bbclass
> b/meta/classes/rootfs.bbclass
> index 446d92d6..d49cd1ef 100644
> --- a/meta/classes/rootfs.bbclass
> +++ b/meta/classes/rootfs.bbclass
> @@ -14,6 +14,7 @@ ROOTFS_BASE_DISTRO ?= "${BASE_DISTRO}"
>  # 'generate-manifest' - generate a package manifest of the rootfs
> into ${ROOTFS_MANIFEST_DEPLOY_DIR}
>  # 'export-dpkg-status' - exports /var/lib/dpkg/status file to
> ${ROOTFS_DPKGSTATUS_DEPLOY_DIR}
>  # 'clean-log-files' - delete log files that are not owned by
> packages
> +# 'no-generate-initrd' - do not generate debian default initrd
>  ROOTFS_FEATURES ?= ""
>  
>  ROOTFS_APT_ARGS="install --yes -o Debug::pkgProblemResolver=yes"
> @@ -22,6 +23,9 @@ ROOTFS_CLEAN_FILES="/etc/hostname /etc/resolv.conf"
>  
>  ROOTFS_PACKAGE_SUFFIX ?= "${PN}-${DISTRO}-${DISTRO_ARCH}"
>  
> +# path to deploy stubbed versions of initrd update scripts during
> do_rootfs_install
> +ROOTFS_STUBS_DIR = "/usr/local/isar-sbin"
> +
>  # Useful environment variables:
>  export E = "${@ isar_export_proxies(d)}"
>  export DEBIAN_FRONTEND = "noninteractive"
> @@ -165,6 +169,13 @@ rootfs_configure_apt() {
>  EOSUDO
>  }
>  
> +ROOTFS_CONFIGURE_COMMAND += "rootfs_disable_initrd_generation"
> +rootfs_disable_initrd_generation[weight] = "1"
> +rootfs_disable_initrd_generation() {
> +    # fully disable initrd generation
> +    sudo mkdir -p "${ROOTFSDIR}${ROOTFS_STUBS_DIR}"
> +    sudo cp -a ${ROOTFSDIR}/usr/bin/true
> ${ROOTFSDIR}${ROOTFS_STUBS_DIR}/update-initramfs
> +}
>  
>  ROOTFS_INSTALL_COMMAND += "rootfs_install_pkgs_update"
>  rootfs_install_pkgs_update[weight] = "5"
> @@ -227,7 +238,21 @@ rootfs_install_pkgs_install[progress] =
> "custom:rootfs_progress.PkgsInstallProgr
>  rootfs_install_pkgs_install[network] = "${TASK_USE_SUDO}"
>  rootfs_install_pkgs_install() {
>      sudo -E chroot "${ROOTFSDIR}" \
> -        /usr/bin/apt-get ${ROOTFS_APT_ARGS} ${ROOTFS_PACKAGES}
> +        /usr/bin/apt-get ${ROOTFS_APT_ARGS} \
> +            -o
> DPkg::Path='${ROOTFS_STUBS_DIR}:/usr/sbin:/usr/bin:/sbin:/bin' \
> +            ${ROOTFS_PACKAGES}
> +}
> +
> +ROOTFS_INSTALL_COMMAND += "rootfs_restore_initrd_tooling"
> +rootfs_restore_initrd_tooling[weight] = "1"
> +rootfs_restore_initrd_tooling() {
> +    sudo rm -rf "${ROOTFSDIR}${ROOTFS_STUBS_DIR}"
> +}
> +
> +ROOTFS_INSTALL_COMMAND += "${@bb.utils.contains('ROOTFS_FEATURES',
> 'no-generate-initrd', 'rootfs_clear_initrd_symlinks', '', d)}"
> +rootfs_clear_initrd_symlinks() {
> +    sudo rm -f ${ROOTFSDIR}/initrd.img
> +    sudo rm -f ${ROOTFSDIR}/initrd.img.old
>  }
>  
>  do_rootfs_install[root_cleandirs] = "${ROOTFSDIR}"
> @@ -421,6 +446,45 @@ python do_rootfs_postprocess() {
>  }
>  addtask rootfs_postprocess before do_rootfs after do_unpack
>  
> +SSTATETASKS += "do_generate_initramfs"
> +do_generate_initramfs[network] = "${TASK_USE_SUDO}"
> +do_generate_initramfs[cleandirs] += "${DEPLOYDIR}"
> +do_generate_initramfs[sstate-inputdirs] = "${DEPLOYDIR}"
> +do_generate_initramfs[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}"
> +python do_generate_initramfs() {
> +    bb.build.exec_func('rootfs_do_mounts', d)
> +    bb.build.exec_func('rootfs_do_qemu', d)
> +    try:
> +        bb.build.exec_func('rootfs_generate_initramfs', d)
> +    finally:
> +        bb.build.exec_func('rootfs_do_umounts', d)
> +}
> +
> +python do_generate_initramfs_setscene () {
> +    sstate_setscene(d)
> +}
> +
> +rootfs_generate_initramfs[progress] =
> "custom:rootfs_progress.InitrdProgressHandler"
> +rootfs_generate_initramfs() {
> +    if [ -n "$(sudo find '${ROOTFSDIR}/boot' -type f -name
> 'vmlinu[xz]*')" ]; then
> +        sudo -E chroot "${ROOTFSDIR}" sh -c '\
> +            export kernel_version=$(basename /boot/vmlinu[xz]* | cut
> -d'-' -f2-); \
> +            echo "Generating initrd"; \
> +            update-initramfs -u -v -k "$kernel_version";'
> +        if [ -n "${INITRD_DEPLOY_FILE}" ]; then
> +            cp ${ROOTFSDIR}/initrd.img
> ${DEPLOYDIR}/${INITRD_DEPLOY_FILE}
> +        fi
> +    else
> +        echo "no kernel in this rootfs, do not generate initrd"
> +    fi
> +}
> +
> +python() {
> +    if 'no-generate-initrd' not in d.getVar('ROOTFS_FEATURES',
> True).split():
> +        bb.build.addtask('do_generate_initramfs', 'do_rootfs',
> 'do_rootfs_postprocess', d)
> +        bb.build.addtask('do_generate_initramfs_setscene', None,
> None, d)
> +}
> +
>  python do_rootfs() {
>      """Virtual task"""
>      pass
> diff --git a/meta/recipes-devtools/sbuild-chroot/sbuild-chroot.inc
> b/meta/recipes-devtools/sbuild-chroot/sbuild-chroot.inc
> index 6478d3a6..98e427e5 100644
> --- a/meta/recipes-devtools/sbuild-chroot/sbuild-chroot.inc
> +++ b/meta/recipes-devtools/sbuild-chroot/sbuild-chroot.inc
> @@ -55,6 +55,7 @@ SBUILD_CHROOT_PREINSTALL_COMMON = " \
>  SBUILD_CHROOT_DIR = "${WORKDIR}/rootfs"
>  ROOTFSDIR = "${SBUILD_CHROOT_DIR}"
>  ROOTFS_PACKAGES = "${SBUILD_CHROOT_PREINSTALL}"
> +ROOTFS_FEATURES += "no-generate-initrd"
>  
>  ROOTFS_POSTPROCESS_COMMAND:remove = "rootfs_cleanup_isar_apt"
>  
> -- 
> 2.39.5

-- 
Best regards,
Uladzimir.


-- 
You received this message because you are subscribed to the Google Groups "isar-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/isar-users/1d1d8ce5d778413cfd092be84e26ee3a9186be05.camel%40ilbers.de.

  reply	other threads:[~2025-04-22  9:16 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-10  5:27 [PATCH 0/2] Significantly speedup image generation 'Felix Moessbauer' via isar-users
2025-04-10  5:27 ` [PATCH 1/2] delay creation of initrd until end of rootfs install 'Felix Moessbauer' via isar-users
2025-04-22  9:16   ` Uladzimir Bely [this message]
2025-04-10  5:27 ` [PATCH 2/2] report approximate progress during initrd generation 'Felix Moessbauer' via isar-users

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1d1d8ce5d778413cfd092be84e26ee3a9186be05.camel@ilbers.de \
    --to=ubely@ilbers.de \
    --cc=adriaan.schmidt@siemens.com \
    --cc=cedric.hombourger@siemens.com \
    --cc=felix.moessbauer@siemens.com \
    --cc=isar-users@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox