From 89f85e45041eb39f686f6b20f909a20bb48277cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Mon, 5 Oct 2020 15:54:00 +0200 Subject: [PATCH 1/2] Use custom tmpfs for managing overlays Provide a method to manage the base mount point for overlay and iso mount points and set the base directory to it because /run has a RAM space limitation which is unfortunate to handle live systems. This Fixes #1558 --- .../customize_the_boot_process.rst | 8 ++++ doc/source/image_description/elements.rst | 30 ++++++++++--- .../modules.d/90kiwi-live/kiwi-generator.sh | 4 +- dracut/modules.d/90kiwi-live/kiwi-live-lib.sh | 42 +++++++++++++++---- dracut/modules.d/90kiwi-live/module-setup.sh | 2 +- .../modules.d/90kiwi-live/parse-kiwi-live.sh | 9 ++-- .../90kiwi-overlay/kiwi-generator.sh | 4 +- .../90kiwi-overlay/kiwi-overlay-root.sh | 17 +++++--- .../modules.d/90kiwi-overlay/module-setup.sh | 2 +- .../99kiwi-lib/kiwi-filesystem-lib.sh | 14 +++++++ dracut/modules.d/99kiwi-lib/module-setup.sh | 2 +- package/python-kiwi-spec-template | 1 + 12 files changed, 107 insertions(+), 28 deletions(-) diff --git a/doc/source/concept_and_workflow/customize_the_boot_process.rst b/doc/source/concept_and_workflow/customize_the_boot_process.rst index bd00213c..f8faebab 100644 --- a/doc/source/concept_and_workflow/customize_the_boot_process.rst +++ b/doc/source/concept_and_workflow/customize_the_boot_process.rst @@ -189,6 +189,14 @@ the available kernel boot parameters for this modules: OS deployment is `/dev/sdj`. With `rd.kiwi.oem.maxdisk=500G` the deployment will land on that RAID disk. +``rd.live.overlay.size`` + Tells a live ISO image the size for the `tmpfs` filesystem that is used + for the `overlayfs` mount process. If the write area of the overlayfs + mount uses this tmpfs, any new data written during the runtime of + the system will fillup this space. The default value used is set + to `50%` which means one half of the available RAM space can be used + for writing new data. + ``rd.live.overlay.persistent`` Tells a live ISO image to prepare a persistent write partition. diff --git a/doc/source/image_description/elements.rst b/doc/source/image_description/elements.rst index 95d992d3..b4612d5b 100644 --- a/doc/source/image_description/elements.rst +++ b/doc/source/image_description/elements.rst @@ -473,11 +473,31 @@ squashfscompression="uncompressed|gzip|lzo|lz4|xz|zstd": Specifies the compression type for mksquashfs overlayroot="true|false" - Specifies to use an overlay root system consisting - out of a squashfs compressed read-only root system - overlayed using the overlayfs filesystem into an - extra read-write partition. Available for the disk - image type oem only + For the `oem` type only, specifies to use an `overlayfs` based root + filesystem consisting out of a squashfs compressed read-only root + filesystem combined with a write-partition or tmpfs. + The optional kernel boot parameter `rd.root.overlay.readonly` can + be used to point the write area into a `tmpfs` instead of + the existing persistent write-partition. In this mode all + written data is temporary until reboot of the system. The kernel + boot parameter `rd.root.overlay.size` can be used to configure + the size for the `tmpfs` that is used for the `overlayfs` mount + process if `rd.root.overlay.readonly` is requested. That size + basically configures the amount of space available for writing + new data during the runtime of the system. The default value + is set to `50%` which means one half of the available RAM space can + be used for writing new data. By default the persistent + write-partition is used. The size of that partition can be + influenced via the optional `` element in the `` + section or via the optional `` element in the + `` section of the XML description. Setting a fixed + `` value will set the size of the image disk to that + value and results in an image file of that size. The available + space for the write partition is that size reduced by the + size the squashfs read-only system needs. If the `` + element is set to `true` an eventually given `` element + will not have any effect because the write partition will be + resized on first boot to the available disk space. bootfilesystem="ext2|ext3|ext4|fat32|fat16": If an extra boot partition is required this attribute diff --git a/dracut/modules.d/90kiwi-live/kiwi-generator.sh b/dracut/modules.d/90kiwi-live/kiwi-generator.sh index a53b00e8..69c9cb51 100755 --- a/dracut/modules.d/90kiwi-live/kiwi-generator.sh +++ b/dracut/modules.d/90kiwi-live/kiwi-generator.sh @@ -1,6 +1,7 @@ #!/bin/bash -x type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh +type getOverlayBaseDirectory >/dev/null 2>&1 || . /lib/kiwi-live-lib.sh [ -z "${root}" ] && root=$(getarg root=) @@ -29,6 +30,7 @@ GENERATOR_DIR="$2" [ -z "$GENERATOR_DIR" ] && exit 1 [ -d "$GENERATOR_DIR" ] || mkdir "$GENERATOR_DIR" +OVERLAY_BASE="$(getOverlayBaseDirectory)" ROOTFLAGS="$(getarg rootflags)" { echo "[Unit]" @@ -37,7 +39,7 @@ ROOTFLAGS="$(getarg rootflags)" echo "[Mount]" echo "Where=/sysroot" echo "What=LiveOS_rootfs" - echo "Options=${ROOTFLAGS},lowerdir=/run/rootfsbase,upperdir=/run/overlayfs/rw,workdir=/run/overlayfs/work" + echo "Options=${ROOTFLAGS},lowerdir=${OVERLAY_BASE}/rootfsbase,upperdir=${OVERLAY_BASE}/overlayfs/rw,workdir=${OVERLAY_BASE}/overlayfs/work" echo "Type=overlay" _dev=LiveOS_rootfs } > "$GENERATOR_DIR"/sysroot.mount diff --git a/dracut/modules.d/90kiwi-live/kiwi-live-lib.sh b/dracut/modules.d/90kiwi-live/kiwi-live-lib.sh index 7bcf51f5..fade0afb 100755 --- a/dracut/modules.d/90kiwi-live/kiwi-live-lib.sh +++ b/dracut/modules.d/90kiwi-live/kiwi-live-lib.sh @@ -1,6 +1,20 @@ #!/bin/bash type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh +function getOverlayBaseDirectory { + # initialize and print overlay base directory below which + # the iso and overlayfs based mountpoints are managed + local overlay_base=/run/overlay + local overlay_size + mkdir -p "${overlay_base}" + if ! mountpoint -q "${overlay_base}";then + overlay_size=$(getarg rd.live.overlay.size) + [ -z "${overlay_size}" ] && overlay_size="50%" + mount -t tmpfs -o "size=${overlay_size}" tmpfs "${overlay_base}" + fi + echo "${overlay_base}" +} + function lookupIsoDiskDevice { local root=$1 local iso_label=${root#/dev/disk/by-label/} @@ -100,8 +114,10 @@ function initGlobalOptions { } function mountIso { - ln -s "${isodev}" /run/initramfs/isodev - local iso_mount_point=/run/initramfs/live + local overlay_base + overlay_base=$(getOverlayBaseDirectory) + ln -s "${isodev}" "${overlay_base}/isodev" + local iso_mount_point="${overlay_base}/live" mkdir -m 0755 -p "${iso_mount_point}" if ! mount -o ro -n -t "${isofs_type}" "${isodev}" "${iso_mount_point}"; then die "Failed to mount live ISO device" @@ -111,7 +127,9 @@ function mountIso { function mountCompressedContainerFromIso { local iso_mount_point=$1 - local container_mount_point=/run/initramfs/squashfs_container + local overlay_base + overlay_base=$(getOverlayBaseDirectory) + local container_mount_point="${overlay_base}/squashfs_container" squashfs_container="${iso_mount_point}/${live_dir}/${squash_image}" mkdir -m 0755 -p "${container_mount_point}" if ! mount -n "${squashfs_container}" "${container_mount_point}";then @@ -122,8 +140,10 @@ function mountCompressedContainerFromIso { function mountReadOnlyRootImageFromContainer { local container_mount_point=$1 + local overlay_base + overlay_base=$(getOverlayBaseDirectory) local rootfs_image="${container_mount_point}/LiveOS/rootfs.img" - local root_mount_point=/run/rootfsbase + local root_mount_point="${overlay_base}/rootfsbase" mkdir -m 0755 -p "${root_mount_point}" if ! mount -n "${rootfs_image}" "${root_mount_point}"; then die "Failed to mount live ISO root filesystem" @@ -132,15 +152,19 @@ function mountReadOnlyRootImageFromContainer { } function prepareTemporaryOverlay { - mkdir -m 0755 -p /run/overlayfs/rw - mkdir -m 0755 -p /run/overlayfs/work + local overlay_base + overlay_base=$(getOverlayBaseDirectory) + mkdir -m 0755 -p "${overlay_base}/overlayfs/rw" + mkdir -m 0755 -p "${overlay_base}/overlayfs/work" } function preparePersistentOverlay { if [ -z "${isodiskmode}" ] || [ -z "${isodiskdev}" ]; then return 1 fi - local overlay_mount_point=/run/overlayfs + local overlay_base + overlay_base=$(getOverlayBaseDirectory) + local overlay_mount_point="${overlay_base}/overlayfs" mkdir -m 0755 -p "${overlay_mount_point}" if [ "${isodiskmode}" = "disk_boot" ];then if ! preparePersistentOverlayDiskBoot "${overlay_mount_point}"; then @@ -151,8 +175,8 @@ function preparePersistentOverlay { return 1 fi fi - mkdir -m 0755 -p ${overlay_mount_point}/rw - mkdir -m 0755 -p ${overlay_mount_point}/work + mkdir -m 0755 -p "${overlay_mount_point}/rw" + mkdir -m 0755 -p "${overlay_mount_point}/work" } function preparePersistentOverlayLoopBoot { diff --git a/dracut/modules.d/90kiwi-live/module-setup.sh b/dracut/modules.d/90kiwi-live/module-setup.sh index 9c620fe7..80568e67 100755 --- a/dracut/modules.d/90kiwi-live/module-setup.sh +++ b/dracut/modules.d/90kiwi-live/module-setup.sh @@ -29,7 +29,7 @@ install() { inst_multiple \ umount dmsetup blockdev blkid lsblk dd losetup \ grep cut partprobe find wc fdisk tail mkfs.ext4 mkfs.xfs \ - dialog cat + dialog cat mountpoint dmsquashdir=$(find "${dracutbasedir}/modules.d" -name "*dmsquash-live") if [ -n "${dmsquashdir}" ] && \ diff --git a/dracut/modules.d/90kiwi-live/parse-kiwi-live.sh b/dracut/modules.d/90kiwi-live/parse-kiwi-live.sh index 2fb64bb5..b7441a5c 100755 --- a/dracut/modules.d/90kiwi-live/parse-kiwi-live.sh +++ b/dracut/modules.d/90kiwi-live/parse-kiwi-live.sh @@ -2,6 +2,7 @@ # live images are specified with # root=live:CDLABEL=label # root=live:AOEINTERFACE=name +type getOverlayBaseDirectory >/dev/null 2>&1 || . /lib/kiwi-live-lib.sh [ -z "${root}" ] && root=$(getarg root=) @@ -33,8 +34,10 @@ info "root was ${liveroot}, is now ${root}" # make sure that init doesn't complain [ -z "${root}" ] && root="live" -wait_for_dev -n /run/rootfsbase -wait_for_dev -n /run/overlayfs/rw -wait_for_dev -n /run/overlayfs/work +OVERLAY_BASE="$(getOverlayBaseDirectory)" + +wait_for_dev -n "${OVERLAY_BASE}/rootfsbase" +wait_for_dev -n "${OVERLAY_BASE}/overlayfs/rw" +wait_for_dev -n "${OVERLAY_BASE}/overlayfs/work" return 0 diff --git a/dracut/modules.d/90kiwi-overlay/kiwi-generator.sh b/dracut/modules.d/90kiwi-overlay/kiwi-generator.sh index 89b84f3a..a71f64aa 100755 --- a/dracut/modules.d/90kiwi-overlay/kiwi-generator.sh +++ b/dracut/modules.d/90kiwi-overlay/kiwi-generator.sh @@ -1,6 +1,7 @@ #!/bin/bash type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh +type getOverlayBaseDirectory >/dev/null 2>&1 || . /lib/kiwi-filesystem-lib.sh [ -z "${root}" ] && root=$(getarg root=) @@ -24,6 +25,7 @@ GENERATOR_DIR="$2" [ -z "$GENERATOR_DIR" ] && exit 1 [ -d "$GENERATOR_DIR" ] || mkdir "$GENERATOR_DIR" +OVERLAY_BASE="$(getOverlayBaseDirectory)" ROOTFLAGS="$(getarg rootflags)" { echo "[Unit]" @@ -32,7 +34,7 @@ ROOTFLAGS="$(getarg rootflags)" echo "[Mount]" echo "Where=/sysroot" echo "What=OverlayOS_rootfs" - echo "Options=${ROOTFLAGS},lowerdir=/run/rootfsbase,upperdir=/run/overlayfs/rw,workdir=/run/overlayfs/work" + echo "Options=${ROOTFLAGS},lowerdir=${OVERLAY_BASE}/rootfsbase,upperdir=${OVERLAY_BASE}/overlayfs/rw,workdir=${OVERLAY_BASE}/overlayfs/work" echo "Type=overlay" _dev=OverlayOS_rootfs } > "$GENERATOR_DIR"/sysroot.mount diff --git a/dracut/modules.d/90kiwi-overlay/kiwi-overlay-root.sh b/dracut/modules.d/90kiwi-overlay/kiwi-overlay-root.sh index 37dd7b46..7c34f6ea 100755 --- a/dracut/modules.d/90kiwi-overlay/kiwi-overlay-root.sh +++ b/dracut/modules.d/90kiwi-overlay/kiwi-overlay-root.sh @@ -1,6 +1,7 @@ #!/bin/bash # root=overlay:UUID=uuid was converted to # root=block:/dev/disk/by-uuid/uuid in cmdline hook +type getOverlayBaseDirectory >/dev/null 2>&1 || . /lib/kiwi-filesystem-lib.sh #====================================== # functions @@ -35,8 +36,10 @@ function initGlobalDevices { } function mountReadOnlyRootImage { - local root_mount_point=/run/rootfsbase - mkdir -m 0755 -p ${root_mount_point} + local overlay_base + overlay_base=$(getOverlayBaseDirectory) + local root_mount_point="${overlay_base}/rootfsbase" + mkdir -m 0755 -p "${root_mount_point}" if ! mount -n "${read_only_partition}" "${root_mount_point}"; then die "Failed to mount overlay(ro) root filesystem" fi @@ -44,13 +47,15 @@ function mountReadOnlyRootImage { } function preparePersistentOverlay { - local overlay_mount_point=/run/overlayfs - mkdir -m 0755 -p ${overlay_mount_point} + local overlay_base + overlay_base=$(getOverlayBaseDirectory) + local overlay_mount_point="${overlay_base}/overlayfs" + mkdir -m 0755 -p "${overlay_mount_point}" if ! mount "${write_partition}" "${overlay_mount_point}"; then die "Failed to mount overlay(rw) filesystem" fi - mkdir -m 0755 -p ${overlay_mount_point}/rw - mkdir -m 0755 -p ${overlay_mount_point}/work + mkdir -m 0755 -p "${overlay_mount_point}/rw" + mkdir -m 0755 -p "${overlay_mount_point}/work" } #====================================== diff --git a/dracut/modules.d/90kiwi-overlay/module-setup.sh b/dracut/modules.d/90kiwi-overlay/module-setup.sh index f4c82b49..3914aa5b 100755 --- a/dracut/modules.d/90kiwi-overlay/module-setup.sh +++ b/dracut/modules.d/90kiwi-overlay/module-setup.sh @@ -7,7 +7,7 @@ check() { # called by dracut depends() { - echo rootfs-block dm + echo rootfs-block dm kiwi-lib return 0 } diff --git a/dracut/modules.d/99kiwi-lib/kiwi-filesystem-lib.sh b/dracut/modules.d/99kiwi-lib/kiwi-filesystem-lib.sh index 5c6f42e2..c3e2eddd 100644 --- a/dracut/modules.d/99kiwi-lib/kiwi-filesystem-lib.sh +++ b/dracut/modules.d/99kiwi-lib/kiwi-filesystem-lib.sh @@ -1,5 +1,19 @@ type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh +function getOverlayBaseDirectory { + # initialize and print overlay base directory below which + # the overlayfs based mountpoints are managed + local overlay_base=/run/overlay + local overlay_size + mkdir -p "${overlay_base}" + if ! mountpoint -q "${overlay_base}";then + overlay_size=$(getarg rd.root.overlay.size) + [ -z "${overlay_size}" ] && overlay_size="50%" + mount -t tmpfs -o "size=${overlay_size}" tmpfs "${overlay_base}" + fi + echo "${overlay_base}" +} + function resize_filesystem { local device=$1 test -n "${device}" || return diff --git a/dracut/modules.d/99kiwi-lib/module-setup.sh b/dracut/modules.d/99kiwi-lib/module-setup.sh index 410ba35a..c1087579 100755 --- a/dracut/modules.d/99kiwi-lib/module-setup.sh +++ b/dracut/modules.d/99kiwi-lib/module-setup.sh @@ -16,7 +16,7 @@ install() { declare moddir=${moddir} inst_multiple \ blkid blockdev dd mkdir rmdir \ - grep cut tail head tr bc true false \ + grep cut tail head tr bc true false mountpoint \ basename partprobe sfdisk sgdisk mkswap readlink lsblk \ btrfs xfs_growfs resize2fs \ e2fsck btrfsck xfs_repair \ diff --git a/package/python-kiwi-spec-template b/package/python-kiwi-spec-template index 1c4c4d81..15e00620 100644 --- a/package/python-kiwi-spec-template +++ b/package/python-kiwi-spec-template @@ -345,6 +345,7 @@ Summary: KIWI - Dracut module for vmx(+overlay) image type # to set up the build environment... BuildRequires: dracut %endif +Requires: dracut-kiwi-lib = %{version}-%{release} Requires: util-linux Requires: dracut License: GPL-3.0-or-later From aaa70813a3fad9476c3984147efef91977bbcada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Wed, 7 Oct 2020 16:44:15 +0200 Subject: [PATCH 2/2] Add support for rd.root.overlay.readonly Allow to use an overlayroot system with read-only feature. If kernelcmdline="rd.root.overlay.readonly" is set in combination with overlayroot="true" the overlayfs uses a tmpfs to store new data temporary as long as the system runs. On reboot the newly written data is lost and the system is back to its factory state. --- .../modules.d/90kiwi-overlay/kiwi-overlay-root.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/dracut/modules.d/90kiwi-overlay/kiwi-overlay-root.sh b/dracut/modules.d/90kiwi-overlay/kiwi-overlay-root.sh index 7c34f6ea..4c4fed31 100755 --- a/dracut/modules.d/90kiwi-overlay/kiwi-overlay-root.sh +++ b/dracut/modules.d/90kiwi-overlay/kiwi-overlay-root.sh @@ -46,6 +46,13 @@ function mountReadOnlyRootImage { echo "${root_mount_point}" } +function prepareTemporaryOverlay { + local overlay_base + overlay_base=$(getOverlayBaseDirectory) + mkdir -m 0755 -p "${overlay_base}/overlayfs/rw" + mkdir -m 0755 -p "${overlay_base}/overlayfs/work" +} + function preparePersistentOverlay { local overlay_base overlay_base=$(getOverlayBaseDirectory) @@ -78,7 +85,11 @@ loadKernelModules mountReadOnlyRootImage # prepare overlay for generated systemd OverlayOS_rootfs service -preparePersistentOverlay +if getargbool 0 rd.root.overlay.readonly; then + prepareTemporaryOverlay +else + preparePersistentOverlay +fi need_shutdown