diff mbox series

[1/3] overlayfs: re-introduce helper unit

Message ID 20260616144043.3303124-1-andreas.muetzel@emlix.com
State Under Review
Headers show
Series [1/3] overlayfs: re-introduce helper unit | expand

Commit Message

Andreas Mützel June 16, 2026, 2:40 p.m. UTC
systemd v256+ automatically creates the upperdir and workdir when
starting an overlayfs mount unit. The directories created this way are
owned by root:root; this behaviour differs from the previously used
helper unit, which explicitly applied the ownership of the lowerdir to
the upperdir.

Revert commit 623c20ff1e989730138c3fbe6e8247eaada20707 to restore the
previous behaviour.

Signed-off-by: Andreas Mützel <andreas.muetzel@emlix.com>
---
 meta/classes-recipe/overlayfs.bbclass           | 10 ++++++++++
 meta/classes-recipe/rootfs-postcommands.bbclass | 13 ++++++++++++-
 meta/files/overlayfs-create-dirs.service.in     | 13 +++++++++++++
 meta/files/overlayfs-create-dirs.sh             | 11 +++++++++++
 meta/files/overlayfs-unit.mount.in              |  3 ++-
 meta/lib/oe/overlayfs.py                        |  4 ++++
 6 files changed, 52 insertions(+), 2 deletions(-)
 create mode 100644 meta/files/overlayfs-create-dirs.service.in
 create mode 100644 meta/files/overlayfs-create-dirs.sh
diff mbox series

Patch

diff --git a/meta/classes-recipe/overlayfs.bbclass b/meta/classes-recipe/overlayfs.bbclass
index 07cc68ad7b..a82763ec10 100644
--- a/meta/classes-recipe/overlayfs.bbclass
+++ b/meta/classes-recipe/overlayfs.bbclass
@@ -55,21 +55,27 @@  REQUIRED_DISTRO_FEATURES += "systemd overlayfs"
 
 inherit systemd features_check
 
+OVERLAYFS_CREATE_DIRS_TEMPLATE ??= "${COREBASE}/meta/files/overlayfs-create-dirs.service.in"
 OVERLAYFS_MOUNT_UNIT_TEMPLATE ??= "${COREBASE}/meta/files/overlayfs-unit.mount.in"
 OVERLAYFS_ALL_OVERLAYS_TEMPLATE ??= "${COREBASE}/meta/files/overlayfs-all-overlays.service.in"
 
 python do_create_overlayfs_units() {
     from oe.overlayfs import mountUnitName
 
+    with open(d.getVar("OVERLAYFS_CREATE_DIRS_TEMPLATE"), "r") as f:
+        CreateDirsUnitTemplate = f.read()
     with open(d.getVar("OVERLAYFS_MOUNT_UNIT_TEMPLATE"), "r") as f:
         MountUnitTemplate = f.read()
     with open(d.getVar("OVERLAYFS_ALL_OVERLAYS_TEMPLATE"), "r") as f:
         AllOverlaysTemplate = f.read()
 
     def prepareUnits(data, lower):
+        from oe.overlayfs import helperUnitName
+
         args = {
             'DATA_MOUNT_POINT': data,
             'DATA_MOUNT_UNIT': mountUnitName(data),
+            'CREATE_DIRS_SERVICE': helperUnitName(lower),
             'LOWERDIR': lower,
         }
 
@@ -77,6 +83,10 @@  python do_create_overlayfs_units() {
         with open(os.path.join(d.getVar('WORKDIR'), mountUnitName(lower)), 'w') as f:
             f.write(MountUnitTemplate.format(**args))
 
+        bb.debug(1, "Generate helper systemd unit %s" % helperUnitName(lower))
+        with open(os.path.join(d.getVar('WORKDIR'), helperUnitName(lower)), 'w') as f:
+            f.write(CreateDirsUnitTemplate.format(**args))
+
     def prepareGlobalUnit(dependentUnits):
         from oe.overlayfs import allOverlaysUnitName
         args = {
diff --git a/meta/classes-recipe/rootfs-postcommands.bbclass b/meta/classes-recipe/rootfs-postcommands.bbclass
index f0c7ee658d..2a36840f29 100644
--- a/meta/classes-recipe/rootfs-postcommands.bbclass
+++ b/meta/classes-recipe/rootfs-postcommands.bbclass
@@ -47,7 +47,7 @@  ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("DISTRO_FEATURES", "systemd"
 
 ROOTFS_POSTPROCESS_COMMAND += 'empty_var_volatile'
 
-ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("DISTRO_FEATURES", "overlayfs", "overlayfs_qa_check", "", d)}'
+ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("DISTRO_FEATURES", "overlayfs", "overlayfs_qa_check overlayfs_postprocess", "", d)}'
 
 inherit image-artifact-names
 
@@ -570,3 +570,14 @@  python overlayfs_qa_check() {
     if not allUnitExist:
         bb.fatal('Not all mount paths and units are installed in the image')
 }
+
+python overlayfs_postprocess() {
+    import shutil
+
+    # install helper script
+    helperScriptName = "overlayfs-create-dirs.sh"
+    helperScriptSource = oe.path.join(d.getVar("COREBASE"), "meta/files", helperScriptName)
+    helperScriptDest = oe.path.join(d.getVar("IMAGE_ROOTFS"), "/usr/sbin/", helperScriptName)
+    shutil.copyfile(helperScriptSource, helperScriptDest)
+    os.chmod(helperScriptDest, 0o755)
+}
diff --git a/meta/files/overlayfs-create-dirs.service.in b/meta/files/overlayfs-create-dirs.service.in
new file mode 100644
index 0000000000..c8431548d7
--- /dev/null
+++ b/meta/files/overlayfs-create-dirs.service.in
@@ -0,0 +1,13 @@ 
+[Unit]
+Description=Overlayfs directories setup {LOWERDIR}
+RequiresMountsFor={DATA_MOUNT_POINT}
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+ExecStart=/usr/sbin/overlayfs-create-dirs.sh {LOWERDIR} {DATA_MOUNT_POINT}
+RemainAfterExit=true
+StandardOutput=journal
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta/files/overlayfs-create-dirs.sh b/meta/files/overlayfs-create-dirs.sh
new file mode 100644
index 0000000000..9f38ad7648
--- /dev/null
+++ b/meta/files/overlayfs-create-dirs.sh
@@ -0,0 +1,11 @@ 
+#!/bin/sh
+# This script is intended to be used solely by overlayfs-create-dirs.service
+# Usage: overlayfs-create-dirs.sh <LOWERDIR> <DATA_MOUNT_POINT>
+
+lowerdir=$1
+datamountpoint=$2
+mkdir -p ${datamountpoint}/upper${lowerdir}
+mkdir -p ${datamountpoint}/workdir${lowerdir}
+if [ -d "$lowerdir" ]; then
+    chown $(stat -c "%U:%G" ${lowerdir}) ${datamountpoint}/upper${lowerdir}
+fi
diff --git a/meta/files/overlayfs-unit.mount.in b/meta/files/overlayfs-unit.mount.in
index eb78d2cb4f..9c117f2c52 100644
--- a/meta/files/overlayfs-unit.mount.in
+++ b/meta/files/overlayfs-unit.mount.in
@@ -1,6 +1,7 @@ 
 [Unit]
 Description=Overlayfs mount unit {LOWERDIR}
-RequiresMountsFor={DATA_MOUNT_POINT}
+Requires={CREATE_DIRS_SERVICE}
+After={CREATE_DIRS_SERVICE}
 
 [Mount]
 What=overlay
diff --git a/meta/lib/oe/overlayfs.py b/meta/lib/oe/overlayfs.py
index 5a5ea03d45..8b88900f71 100644
--- a/meta/lib/oe/overlayfs.py
+++ b/meta/lib/oe/overlayfs.py
@@ -23,6 +23,9 @@  def allOverlaysUnitName(d):
 def mountUnitName(unit):
     return escapeSystemdUnitName(unit) + '.mount'
 
+def helperUnitName(unit):
+    return escapeSystemdUnitName(unit) + '-create-upper-dir.service'
+
 def unitFileList(d):
     fileList = []
     overlayMountPoints = d.getVarFlags("OVERLAYFS_MOUNT_POINT")
@@ -43,6 +46,7 @@  def unitFileList(d):
             continue
         for path in mountPointList.split():
             fileList.append(mountUnitName(path))
+            fileList.append(helperUnitName(path))
 
     fileList.append(allOverlaysUnitName(d))